Copiar automáticamente elementos de la última lista

Copiar automáticamente elementos de la última lista

En criptografía, la prueba implica una secuencia de juegos. Cada juego contiene una lista de líneas. Los juegos adyacentes son casi iguales excepto por una pequeña cantidad de líneas (generalmente 1). Solía ​​copiar el juego antiguo al siguiente y modificarlo en el nuevo. Pero esto es realmente inconveniente y difícil de mantener. El archivo fuente resultante también es innecesariamente grande. Basta pensar en una prueba con 20 juegos y cada uno de ellos tiene 10 líneas.

Entonces decidí crear un ambiente para esto. Parece un entorno "enumerado" donde cada uno de sus elementos es también un entorno "enumerado". Cada vez que creo un nuevo elemento (juego) para el enumerador externo, también especificaré como parámetro variable qué líneas del último juego quiero cambiar. Quiero que el entorno copie automáticamente cada línea del último juego que no esté especificado en el parámetro.

¿Alguna idea de cómo se puede lograr esto?

Respuesta1

Después de una pequeña pelea con él (la primera vez que lo uso prop), creo que esto funciona, aunque es una mezcla de cosas, y tal vez sería mejor pensar en una mejor "interfaz de usuario".

Primero, tienes un entorno cryptolistque es como un enumerateexcepto que \item{…}tiene un argumento. cryptolisttiene un argumento opcional que es elnombre de la lista(por defecto es default) que le da la opción de mantener muchas listas diferentes al mismo tiempo.

Luego hay dos comandos \replacecryptoitems(el nombre en el argumento opcional y una lista habitual de valores-clave de los elementos a reemplazar) y \printcryptolist(el nombre en el argumento opcional). Por ejemplo, puedes \replacecryptoitems{2=Modified second item, 3=modified third item}y luego \printcryptolistimprimirlo.

Para inicializar una nueva lista de cifrado necesita \newcryptolist{name}.

ingrese la descripción de la imagen aquí

\documentclass{scrartcl}
\usepackage{xparse,enumitem}

\ExplSyntaxOn
\NewDocumentCommand \newcryptolist { m }
 {
  \prop_new:c { g_cryptolist_#1_prop }
  \int_new:c  { g_cryptolist_#1_int  }
 }
\NewDocumentEnvironment { cryptolist } { O{default} }
 {
  \tl_set:Nn \l_cryptolist_name_tl { #1 }
  \int_gzero:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int }
  \prop_gclear:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
  \enumerate
   \cs_set_eq:NN \normalitem \item
   \cs_set_eq:NN \item \cryptoitem
 }
 { \endenumerate }
\NewDocumentCommand \cryptoitem { o m }
 {
  \int_gincr:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int }
  \tl_set:Nx \l_cryptolist_item_tl
   { \int_use:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int } }
  \prop_gput:con { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
   { \l_cryptolist_item_tl }
   { #2 }
  \IfValueTF { #1 } { \normalitem [ #1 ] } { \normalitem }
  #2
 }
\NewDocumentCommand \printcryptolist { O{default} }
 { \cc_printitems:n { #1 } }
\NewDocumentCommand \replacecryptoitems { O{default} m }
 { \cc_replaceitems:nn { #1 } { #2 } }

\tl_new:N \l_cryptolist_name_tl
\tl_new:N \l_cryptolist_item_tl
\prop_new:N \g_cryptolist_default_prop
\int_new:N  \g_cryptolist_default_int
\keys_define:nn { cryptolist }
 {
  unknown .code:n =
   \prop_gput:cVn { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
    \l_keys_key_tl { #1 }
 }
\cs_new_protected:Npn \cc_printitems:n #1
 {
  \begin{enumerate}
    \tl_set:Nn \l_cryptolist_name_tl { #1 }
    \int_step_inline:nnnn { 1 } { 1 }
     { \int_use:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int } }
     {
      \item
      \prop_item:cn { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
       { ##1 }
     }
  \end{enumerate}
 }
\cs_new_protected:Npn \cc_replaceitems:nn #1 #2
 {
  \tl_set:Nn \l_cryptolist_name_tl { #1 }
  \keys_set:nn { cryptolist } { #2 }
 }
\ExplSyntaxOff

\newcryptolist{anotherlist}

\begin{document}

\begin{cryptolist}[anotherlist]
  \item{First item to be used later;}
  \item{second item.}
\end{cryptolist}

\begin{cryptolist}
  \item{First item}
  \item{Second item}
  \item{Third item}
  \item{Last item}
\end{cryptolist}

\replacecryptoitems{2 = Second (modified) item, 4 = Last modified item.}
\printcryptolist

\replacecryptoitems[anotherlist]{1=Changing the first one to be used now;}
\printcryptolist[anotherlist]

\end{document}

Código extendido para ayudar a la nueva solicitud. En este caso, cada vez que se utiliza \replacecryptoitemsse registran las entradas reemplazadas. Y la próxima vez \printcryptoitemsse da (solola próxima vez, después de un uso se reinicia) las entradas modificadas se \gamediff{…}eliminan.

ingrese la descripción de la imagen aquí

\documentclass{scrartcl}
\usepackage{xparse,enumitem}
\usepackage[x11names]{xcolor}

\ExplSyntaxOn
\NewDocumentCommand \gamediff { m }
 { \textcolor { Tomato3 } { #1 } }
\NewDocumentCommand \newcryptolist { m }
 {
  \prop_new:c { g_cryptolist_#1_prop }
  \int_new:c  { g_cryptolist_#1_int  }
  \seq_new:c  { g_cryptolist_modifieditems_#1_seq  }
 }
\NewDocumentEnvironment { cryptolist } { O{default} }
 {
  \tl_set:Nn \l_cryptolist_name_tl { #1 }
  \int_gzero:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int }
  \prop_gclear:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
  \enumerate[noitemsep]
   \cs_set_eq:NN \normalitem \item
   \cs_set_eq:NN \item \cryptoitem
 }
 { \endenumerate }
\NewDocumentCommand \cryptoitem { o m }
 {
  \int_gincr:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int }
  \tl_set:Nx \l_cryptolist_item_tl
   { \int_use:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int } }
  \prop_gput:con { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
   { \l_cryptolist_item_tl }
   { #2 }
  \IfValueTF { #1 } { \normalitem [ #1 ] } { \normalitem }
  #2
 }
\NewDocumentCommand \printcryptolist { O{default} }
 { \cc_printitems:n { #1 } }
\NewDocumentCommand \replacecryptoitems { O{default} m }
 { \cc_replaceitems:nn { #1 } { #2 } }

\tl_new:N \l_cryptolist_name_tl
\tl_new:N \l_cryptolist_item_tl
\prop_new:N \g_cryptolist_default_prop
\seq_new:N \g_cryptolist_modifieditems_default_seq
\int_new:N  \g_cryptolist_default_int
\keys_define:nn { cryptolist }
 {
  unknown .code:n =
   \seq_gput_right:cV
    { g_cryptolist_modifieditems_ \tl_use:N \l_cryptolist_name_tl _seq }
    \l_keys_key_tl
   \prop_gput:cVn { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
    \l_keys_key_tl { #1 }
 }
\cs_new_protected:Npn \cc_printitems:n #1
 {
  \begin{enumerate}[noitemsep]
    \tl_set:Nn \l_cryptolist_name_tl { #1 }
    \int_step_inline:nnnn { 1 } { 1 }
     { \int_use:c { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _int } }
     {
      \item
      \group_begin:
      \seq_if_in:cnF
       { g_cryptolist_modifieditems_ \tl_use:N \l_cryptolist_name_tl _seq }
       { ##1 }
       { \cs_set_eq:NN \gamediff \prg_do_nothing: }
      {
       \prop_item:cn { g_cryptolist_ \tl_use:N \l_cryptolist_name_tl _prop }
        { ##1 }
      }
      \group_end:
     }
  \end{enumerate}
  \seq_gclear:c
   { g_cryptolist_modifieditems_ \tl_use:N \l_cryptolist_name_tl _seq }
 }
\cs_new_protected:Npn \cc_replaceitems:nn #1 #2
 {
  \tl_set:Nn \l_cryptolist_name_tl { #1 }
  \keys_set:nn { cryptolist } { #2 }
 }
\ExplSyntaxOff

\newcryptolist{anotherlist}

\begin{document}

\begin{cryptolist}
  \item{First item}
  \item{Second item}
  \item{Third item}
  \item{Last item}
\end{cryptolist}

\replacecryptoitems{2 = Second \gamediff{(modified)} item, 4 = Last modified \gamediff{item}.}
\printcryptolist

And this next time they are not highlighted.
\printcryptolist

\end{document}

Respuesta2

\documentclass{article}
\usepackage{color}
\usepackage{expl3}

\newcommand\gamediff[2][red]{\color{#1}{\underline{\color{black}{#2}}}\color{black}{}}
\newsavebox\MBox
\newcommand\gamediffeq[2][red]{{\sbox\MBox{$#2$}\rlap{\usebox\MBox}\color{#1}\rule[-1.2\dp\MBox]{\wd\MBox}{0.5pt}}}

\ExplSyntaxOn
\seq_new:N \g_crypto__gameseq_seq
\tl_new:N \g_crypto__gameseq_tl
\int_new:N \g_crypto__gameseq_i
\cs_new:Npn \crypto__gameseq_move:ccn #1#2#3
  {
    \int_step_inline:nnnn { 1 } { 1 } { #3 }
      {
        \seq_gpop_left:cN { #1 } \g_crypto__gameseq_tl
        \seq_gput_left:cV { #2 } \g_crypto__gameseq_tl
      }
  }
\cs_new:Npn \crypto__gameseq_store:cn #1#2
  {
    \crypto__gameseq_move:ccn { #1 } { g_crypto__gameseq_seq } { #2 }
  }
\cs_new:Npn \crypto__gameseq_load:cn #1#2
  {
    \crypto__gameseq_move:ccn { g_crypto__gameseq_seq } { #1 } { #2 }
  }
\cs_new:Npn \crypto__gameseq_out:N #1
  {
    \item \tl_use:N #1
  }

\cs_new:Npn \crypto_gameseq_new:c #1
  {
    \seq_gclear_new:c { g_crypto_gameseq_#1 }
    \int_gzero_new:c { g_crypto_gameseq_#1_num }
  }
\cs_new:Npn \crypto_gameseq_add:cnn #1#2#3
  {
    \crypto__gameseq_store:cn { g_crypto_gameseq_#1 } { \int_eval:n { #2 - 1 } }
    \seq_gput_left:cn { g_crypto_gameseq_#1 } { #3 }
    \crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { \int_eval:n { #2 - 1 } }
  }
\cs_new:Npn \crypto_gameseq_del:cnn #1#2#3
  {
    \crypto__gameseq_store:cn { g_crypto_gameseq_#1 } { \int_eval:n { #2 - 1 } }
    \seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
    \crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { \int_eval:n { #2 - 1 } }
  }
\cs_new:Npn \crypto_gameseq_mod:cnn #1#2#3
  {
    \crypto__gameseq_store:cn { g_crypto_gameseq_#1 } { \int_eval:n { #2 - 1 } }
    \seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
    \seq_gput_left:cn { g_crypto_gameseq_#1 } { #3 }
    \crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { \int_eval:n { #2 - 1 } }
  }
\cs_new:Npn \crypto_gameseq_get:c #1
  {
    \int_gincr:c { g_crypto_gameseq_#1_num }
    \item[Game~\int_use:c { g_crypto_gameseq_#1_num }.]
    \begin{enumerate}
    \seq_map_function:cN { g_crypto_gameseq_#1 } \crypto__gameseq_out:N
    \end{enumerate}
  }

\cs_new_eq:NN \seqnew \crypto_gameseq_new:c
\cs_new_eq:NN \seqout \crypto_gameseq_get:c
\cs_new_eq:NN \seqadd \crypto_gameseq_add:cnn
\cs_new_eq:NN \seqdel \crypto_gameseq_del:cnn
\cs_new_eq:NN \seqmod \crypto_gameseq_mod:cnn
\ExplSyntaxOff

\begin{document}
\begin{itemize}
\seqnew{cc}
\seqadd{cc}{1}{first item}
\seqadd{cc}{2}{third item}
\seqadd{cc}{2}{fourth item}
\seqout{cc}
\seqmod{cc}{2}{\gamediff{second} item}
\seqout{cc}
\seqout{cc}
\end{itemize}
\end{document}

Para resolver el primer problema, cambié para usar seqen lugar de prop. Y el resultado es ingrese la descripción de la imagen aquí

Pero no descubrí cómo podría resolver el segundo problema. Tengo dos ideas:

  1. Cada vez que se imprime un juego, revisa todos los elementos y elimina todas las llamadas a gamediff. Es posible que el obstáculo gamediffno esté en el nivel más alto. Puede ser {{gamediff}}o $gamediff$.

  2. Cuando se almacena un elemento en la lista, el usuario no llama gamediffdirectamente, sino que llama a una función que generará gamediff[i]dónde iestá el juego actual. Y cuando se imprime un juego, gamediffse evalúa y solo aquellos con el primer parámetro igual al juego actual resaltarán su contenido.


Con la idea de Manuel también se maneja el problema 2.

\documentclass{article}
\usepackage{color}
\usepackage{expl3}

\newcommand\highlight[2][red]{\color{#1}{\underline{\color{black}{#2}}}\color{black}{}}
\newsavebox\MBox
\newcommand\highlighteq[2][red]{{\sbox\MBox{$#2$}\rlap{\usebox\MBox}\color{#1}\rule[-1.2\dp\MBox]{\wd\MBox}{0.5pt}}}

\ExplSyntaxOn
\seq_new:N \g_crypto__gameseq_seq
\tl_new:N \g_crypto__gameseq_tl
\int_new:N \g_crypto__gameseq_i
\cs_new:Npn \crypto__gameseq_move:ccn #1#2#3
  {
    \int_step_inline:nnnn { 1 } { 1 } { \int_eval:n { \int_eval:n { #3 } * 2 } }
      {
        \seq_gpop_left:cN { #1 } \g_crypto__gameseq_tl
        \seq_gput_left:cV { #2 } \g_crypto__gameseq_tl
      }
  }
\cs_new:Npn \crypto__gameseq_store:cn #1#2
  {
    \crypto__gameseq_move:ccn { #1 } { g_crypto__gameseq_seq } { #2 }
  }
\cs_new:Npn \crypto__gameseq_load:cn #1#2
  {
    \crypto__gameseq_move:ccn { g_crypto__gameseq_seq } { #1 } { #2 }
  }

\cs_new:Npn \crypto_gameseq_new:c #1
  {
    \seq_gclear_new:c { g_crypto_gameseq_#1 }
    \int_gzero_new:c { g_crypto_gameseq_#1_num }
  }
\cs_new:Npn \crypto_gameseq_add:cnn #1#2#3
  {
    \crypto__gameseq_store:cn { g_crypto_gameseq_#1 } { #2 - 1 }
    \seq_gput_left:cn { g_crypto_gameseq_#1 } { #3 }
    \seq_gput_left:cn { g_crypto_gameseq_#1 } { 1 }
    \crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { #2 - 1 }
  }
\cs_new:Npn \crypto_gameseq_del:cnn #1#2
  {
    \crypto__gameseq_store:cn { g_crypto_gameseq_#1 } { #2 - 1 }
    \seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
    \seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
    \crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { #2 - 1 }
  }
\cs_new:Npn \crypto_gameseq_mod:cnn #1#2#3
  {
    \crypto__gameseq_store:cn { g_crypto_gameseq_#1 } { #2 - 1 }
    \seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
    \seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
    \seq_gput_left:cn { g_crypto_gameseq_#1 } { #3 }
    \seq_gput_left:cn { g_crypto_gameseq_#1 } { 1 }
    \crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { #2 - 1 }
  }
\cs_new:Npn \crypto_gameseq_get:c #1
  {
    \int_gincr:c { g_crypto_gameseq_#1_num }
    \item[Game~\int_use:c { g_crypto_gameseq_#1_num }.]
    \begin{enumerate}
    \int_step_variable:nnnNn { 1 } { 1 } { \seq_count:c { g_crypto_gameseq_#1 } } \g_crypto__gameseq_i
      {
        \seq_gpop_left:cN { g_crypto_gameseq_#1 } \g_crypto__gameseq_tl
        \int_if_odd:nTF \g_crypto__gameseq_i
          {
            \tl_if_empty:NTF { \g_crypto__gameseq_tl }
              {
                \cs_set_eq:NN \gamediff \prg_do_nothing:
                \cs_set_eq:NN \gamediffeq \prg_do_nothing:
              }
              {
                \cs_set_eq:NN \gamediff \highlight
                \cs_set_eq:NN \gamediffeq \highlighteq
              }
            \seq_gput_left:Nn \g_crypto__gameseq_seq {}
          }
          {
            \item \tl_use:N \g_crypto__gameseq_tl
            \seq_gput_left:cV { g_crypto__gameseq_seq } \g_crypto__gameseq_tl
          }
      }
    \crypto__gameseq_load:cn { g_crypto_gameseq_#1 } { \int_eval:n { \seq_count:c { g_crypto__gameseq_seq } / 2 } }
    \end{enumerate}
  }

\cs_new_eq:NN \seqnew \crypto_gameseq_new:c
\cs_new_eq:NN \seqout \crypto_gameseq_get:c
\cs_new_eq:NN \seqadd \crypto_gameseq_add:cnn
\cs_new_eq:NN \seqdel \crypto_gameseq_del:cnn
\cs_new_eq:NN \seqmod \crypto_gameseq_mod:cnn
\cs_new_eq:NN \gamediff \highlight
\cs_new_eq:NN \gamediffeq \highlighteq
\ExplSyntaxOff

\begin{document}
\begin{itemize}
\seqnew{cc}
\seqadd{cc}{1}{first item}
\seqout{cc}
\seqadd{cc}{2}{\gamediff{third} item}
\seqout{cc}
\seqadd{cc}{2}{fourth item}
\seqout{cc}
\seqmod{cc}{2}{\gamediff{second} item}
\seqout{cc}
\seqout{cc}
\seqdel{cc}{2}
\seqout{cc}
\end{itemize}
\end{document}

El resultado esingrese la descripción de la imagen aquí

información relacionada