Bucle a través de una matriz de cadenas (en realidad, una matriz de una matriz de cadenas, por ejemplo, `{{black, ab}, {white, cd}}`)

Bucle a través de una matriz de cadenas (en realidad, una matriz de una matriz de cadenas, por ejemplo, `{{black, ab}, {white, cd}}`)

Estoy dibujando piedras en un tablero de Go (juego) conSGFcoordenadas (que solo logré hacer gracias a la ayuda que la gente me dio enesta pregunta) como esto \drawStoneFromSgfCoords{ab}.

Sin embargo, puede haber muchas piedras por diagrama, por lo que sería práctico tener también otra macro como esta: \drawStonesFromSgfCoords{{black, ab}, {white, cd}}(los colores normalmente se alternan, pero a veces es más práctico tener una lista de coordenadas negras y luego blancas).

Esto es lo que estoy intentando ahora, aunque no funciona (quiero decir, funciona, pero no con la nueva macro):

\documentclass{article}

\usepackage{tikz}

% From [this answer by @DavidCarlisle](https://tex.stackexchange.com/a/708876/64441).
\newcommand\notwhite{black}
\newcommand\notblack{white}

% From [this answer by @DavidCarlisle](https://tex.stackexchange.com/a/708893/64441).
\ExplSyntaxOn
  \cs_generate_variant:Nn \int_from_alph:n {e}

  \newcommand\stringToCoordX[1]{
    \int_from_alph:e{\use_i:nn#1}
  }
  \newcommand\stringToCoordY[1]{
    ~\int_from_alph:e{\use_ii:nn#1}
  }
\ExplSyntaxOff

\newcommand{\drawStoneFromSgfCoords}[2]{
  \pgfmathsetmacro{\x}{\stringToCoordX{#2} - 1}
  \pgfmathsetmacro{\y}{\stringToCoordY{#2} - 1}

  \draw[draw = \UseName{not#1}, fill = #1, line width = 0.1mm]
    (\x * 10cm / 18, \y * 10cm / 18)
    circle [radius = 0.2575cm];
    node[color = white] {1};
}

% Example usage: `drawStonesFromSgfCoords{{black, ab}, {white, cd}}`
\newcommand{\drawStonesFromSgfCoords}[1]{
  \foreach \coords in {#1}{
    \drawStoneFromSgfCoords{{\coords}[0]}{{\coords}[1]}
  }
}

\begin{document}
  \begin{tikzpicture}
    \pgfmathsetmacro{\step}{10 / 18}

    \draw[step=\step] (0, 0) grid (10, 10);

    \drawStoneFromSgfCoords{black}{ab}
    \drawStoneFromSgfCoords{white}{cd}
    
    % \drawStonesFromSgfCoords{{black, ab}, {white, cd}}
  \end{tikzpicture}
\end{document}

¿Cuál es la forma correcta de acceder o pasar matrices (dentro de un bucle)?

(Estoy usando PGF \foreachporque eso es lo que sé).

Respuesta1

Creo que es una mejor idea procesar la lista anidada clist(una lista separada por comas) a través de herramientas expl aquí, ya que ya existen herramientas para manejar dichas listas:

\documentclass{article}
\usepackage{tikz}

% From [this answer by @DavidCarlisle](https://tex.stackexchange.com/a/708876/64441).
\newcommand\notwhite{black}
\newcommand\notblack{white}

% From [this answer by @DavidCarlisle](https://tex.stackexchange.com/a/708893/64441).
\ExplSyntaxOn
  \cs_generate_variant:Nn \int_from_alph:n {e}

  \NewExpandableDocumentCommand{\stringToCoordX}{ m }{
    \int_from_alph:e { \use_i:nn #1 }
  }
  \NewExpandableDocumentCommand{\stringToCoordY}{ m }{
    \int_from_alph:e { \use_ii:nn #1 }
  }
\ExplSyntaxOff

\newcommand{\drawStoneFromSgfCoords}[2]{
  \pgfmathsetmacro{\x}{\stringToCoordX{#2} - 1}
  \pgfmathsetmacro{\y}{\stringToCoordY{#2} - 1}

  \draw[draw = \UseName{not#1}, fill = #1, line width = 0.1mm]
    (\x * 10cm / 18, \y * 10cm / 18)
    circle [radius = 0.2575cm];
}

\ExplSyntaxOn
  % Example usage: `drawStonesFromSgfCoords{{black, ab}, {white, cd}}`
  \NewExpandableDocumentCommand{\drawStonesFromSgfCoords}{ m }{
    \clist_set:Nn \l_tmpa_clist { #1 }
    \clist_map_inline:Nn \l_tmpa_clist {
      \clist_set:Nn \l_tmpb_clist { ##1 }
      \clist_pop:NN \l_tmpb_clist \l_tmpa_tl 
      \clist_pop:NN \l_tmpb_clist \l_tmpb_tl 
      \exp_args:Noo \drawStoneFromSgfCoords { \l_tmpa_tl } { \l_tmpb_tl }
      
    }
  }
\ExplSyntaxOff

\begin{document}
  \begin{tikzpicture}
    \pgfmathsetmacro{\step}{10 / 18}

    \draw[step=\step] (0, 0) grid (10, 10);

    %\drawStoneFromSgfCoords{black}{ab}
    %\drawStoneFromSgfCoords{white}{cd}
    \drawStonesFromSgfCoords{{black, ab}, {white, cd}}
    
  \end{tikzpicture}
\end{document}

ingrese la descripción de la imagen aquí


Algunas notas sobre los comandos utilizados (puede encontrar una buena descripción general y una documentación exhaustiva en elInterfaces L3 PDF):

  • \clist_set:Nn \l_tmpa_clist { #1 }almacena una clist(una lista separada por comas) en una variable token para que sea accesible. En el caso de ejemplo, {{black, ab}, {white, cd}}se almacena como clisten la variable token \l_tmpa_clist.
  • \clist_map_inline:Nn \l_tmpa_clist { ... }recorre cada elemento del clist(almacenado en la variable token) y ejecuta el código entre llaves. Se accede al elemento actual a través de #1( ##1en el ejemplo de código, porque está anidado un nivel más profundo).
  • \clist_pop:NN \l_tmpb_clist \l_tmpa_tltoma el primer elemento de clisty lo almacena en una variable token ( l_tmpa_tl). Luego elimina este elemento del archivo clist.
  • \exp_args:Noo \drawStoneFromSgfCoords { \l_tmpa_tl } { \l_tmpb_tl }primero expande las dos variables token e inserta el resultado como argumentos en \drawStoneFromSgfCoords.

Entonces, veamos qué sucede paso a paso si decimos \drawStonesFromSgfCoords{{black, ab}, {white, cd}}:

\NewExpandableDocumentCommand{\drawStonesFromSgfCoords}{ m }{

    % store {{black, ab}, {white, cd}} in \l_tmpa_clist 
    \clist_set:Nn \l_tmpa_clist { #1 }

    % loop over items in \l_tmpa_clist 
    \clist_map_inline:Nn \l_tmpa_clist {

      % store {black, ab} in \l_tmpb_clist
      \clist_set:Nn \l_tmpb_clist { ##1 }

      % store black in \l_tmpa_tl and remove item from clist
      \clist_pop:NN \l_tmpb_clist \l_tmpa_tl 

      % store ab in \l_tmpb_tl and remove item from clist
      \clist_pop:NN \l_tmpb_clist \l_tmpb_tl 

      % expand \l_tmpa_tl and \l_tmpb_tl so that we get
      % \drawStoneFromSgfCoords{black}{ab}
      \exp_args:Noo \drawStoneFromSgfCoords { \l_tmpa_tl } { \l_tmpb_tl }

      % repeat this loop for the next item in the clist in \l_tmpa_clist

    }
}

información relacionada