Aufrufen eines Befehls mit einem generierten optionalen Argument

Aufrufen eines Befehls mit einem generierten optionalen Argument

Ich arbeite an einem Makro, das mir in Zukunft viel Zeit sparen soll. Einer der Befehle funktioniert derzeit, aber ich habe Probleme, den zweiten Teil zum Laufen zu bringen. Der erste Befehl ist wie folgt definiert:

\NewDocumentCommand\x
{
    s
    >{\SplitList{,}}o
    >{\SplitList{,}}o
    >{\SplitList{,}}o
    >{\SplitList{,}}o
    >{\SplitList{,}}o
    >{\SplitList{,}}o
    >{\SplitList{,}}o
    >{\SplitList{,}}o
}{
  % Full definition of the command
}

Dieser Befehl akzeptiert acht optionale Argumente, jedes davon ist eine durch Kommas getrennte Liste, normalerweise Zahlen, obwohl das nicht erforderlich ist. Ich könnte es wie \x[-3,0][0,-2]oder nennen \x[1,2,3,0][4,5,6,0][7,8,9,0]. Jede Liste wird immer dieselbe Länge haben.

Ich versuche, einen zweiten Befehl zu erstellen, der ein bisschen wie eine Transponierung funktioniert. Er nimmt also ebenfalls bis zu acht Listen an, aber diese Listen sind durch Sterne getrennt und die Elemente sind Listen aus dem \xBefehl. Am einfachsten lässt sich anhand eines Beispiels zeigen, wie es funktioniert:

\mxm
   [ [3,2]*[-3, 0]*[ 1,-2] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]

wäre gleichbedeutend mit:

\x[3,2][1,1]
\x[-3,0][0,-2]
\x[1,-2][-1,3]

Jede dieser Sternlisten hätte die gleiche Anzahl von Elementen. Wenn sie unterschiedliche Anzahlen von Elementen oder Elemente hätten, die keine Argumente des \xBefehls wären, könnte alles passieren: ein Fehler, das Einfügen einer Art Nullelement, das Abschneiden auf die kürzeste Liste usw. Es wird nicht so aufgerufen, also spielt es keine Rolle.

Die Länge dieser Listen gibt an, wie viele \xAufrufe es gibt. In diesem Beispiel beträgt die Länge drei, es gibt also drei Aufrufe von , \xaber wenn die Länge länger oder kürzer wäre, würde es eine andere Anzahl geben. Die Anzahl der Listen gibt an, wie viele Argumente es für jeden Aufruf von gibt \x. In diesem Beispiel gibt es zwei, aber es könnten bis zu 8 sein.

\mxm*Wenn möglich, würde ich gerne einen Stern von bis weitergeben können, \x*aber wenn das zu schwierig ist, habe ich eine alternative Lösung, da das nicht sehr oft vorkommen sollte. So würde das aussehen:

\mxm[[1,3,1]*[-1, 0,3]]
    [[2,2,1]*[ 0,-2,2]]
    [[3,1,2]*[ 1,-2,1]]

wäre gleichbedeutend mit:

\x*[1,3,1]
   [2,2,1]
   [3,1,2]
\x*[-1, 0,3]
   [ 0,-2,2]
   [ 1,-2,1]

Hier ist ein MWEmit einem Beispiel \x(nur ein Platzhalter, darf nicht aufgerufen werden \x). Es enthält auch, wie weit ich gekommen bin, obwohl ich mir nicht vorstellen kann, dass es viel hilft.

Antwort1

Endrekursion, also Makros, die sich selbst erneut aufrufen, und ein häufiger Austausch von Argumenten im Vorfeld, könnten die Lösung sein. ;-)

Wenn ich es richtig verstehe, \mxmgeht es darum, eine Liste optionaler Argumente zu verarbeiten, wobei jedes optionale Argument selbst eine *durch -getrennte Liste optionaler Argumente enthält.

Sie haben nicht angegeben, was zu tun ist, wenn nicht alle *durch -getrennten Listen optionaler Argumente die gleiche Anzahl an Elementen enthalten.

Daher habe ich mir die Freiheit genommen, die Dinge so zu implementieren, dass [NULL]überall dort, wo *-getrennte Elemente fehlen, weil die Listen unterschiedlich lang sind oder die Argumente dazwischen *leer angegeben sind, eine entsprechende Vorgabe gemacht wird.

\documentclass{article}
\usepackage{xparse}

\makeatletter
%%=============================================================================
%% Little helpers:
%%.............................................................................
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\z@\@secondoftwo}%
  {\expandafter\z@\@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%.............................................................................
%%   \romannumeral\UD@ExtractFirstArgLoop{<argument>\UD@SelDOm}%
%%   yields <argument>'s 1st undelimited argument.
%%   <argument> must not be blank, i.e., must neither be empty nor consist
%%   only of explicit character tokens of catcode 10 and charcode 32.
%%
%%   \UD@SelDOm must not be defined in terms of \outer !
%%.............................................................................
\@ifdefinable\UD@RemoveTillUD@SelDOm{%
  \long\def\UD@RemoveTillUD@SelDOm#1#2\UD@SelDOm{{#1}}%
}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
  {\expandafter\z@\@secondoftwo{}#1}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillUD@SelDOm#1}}%
}%


%%=============================================================================
%% \mxm starts a loop for collecting an arbitrary amount of optional arguments.
%%.............................................................................
\NewDocumentCommand\mxm{}{\innermxm{}}%
%%-----------------------------------------------------------------------------
%% \innermxm checks if another optional argument is present.
%% If so it will be collected and \innermxm is called again.
%% Otherwise the loop for forming the calls to \x is started.
%%.............................................................................
\NewDocumentCommand\innermxm{m >{\SplitList{*}}o}{%
  % #1 - list of brace-nested optional arguments collected so far.
  % #2 - either the no-value-marker or the next optional argument:
  \IfNoValueTF{#2}{%
    % Start the loop for forming the calls to \x/for re-arranging things:
    %   \romannumeral is not really needed here, but while writing
    %   this I wanted the missing-number-error in case of messing up
    %   the tail-recursive \mxmloop's  flipping-around/exchanging
    %   of arguments. ;-)
    \romannumeral\mxmloop{\x}{}{}{#1}{}%
  }{%
    % Add the current optional argument to the list #1 and check if
    % another optional argument is present...
    \innermxm{#1{#2}}%
  }%
}%

\newcommand\mxmloop[5]{%
  %#1 - token-list produced so far forming current new call to \x
  %#2 - new list of lists
  %#3 - indicator if all elements of current list of lists were empty. 
  %#4 - current list of lists
  %#5 - list of calls to \x
  \UD@CheckWhetherNull{#4}{%
    \UD@CheckWhetherNull{#3}{%
      \z@#5% <- this \z@ terminates the (actually not needed)
           %   \romannumeral-expansion started by \innermxm. 
           %   It denotes a non-positive number and therefore
           %   gets removed silently.
    }{%
      \mxmloop{\x}{}{}{#2}{#5#1}%
    }%
  }{%
    \UD@PassFirstToSecond{#5}{%
      \expandafter\UD@PassFirstToSecond\expandafter{\@firstoftwo{}#4}{%
        \expandafter\UD@CheckWhetherNull\expandafter{\romannumeral\UD@ExtractFirstArgLoop{#4\UD@SelDOm}}{%
          \UD@PassFirstToSecond{#3}{%
            \UD@PassFirstToSecond{#2{}}{%
              \UD@PassFirstToSecond{#1[NULL]}{\mxmloop}%
            }%
          }%
        }{%
          \UD@PassFirstToSecond{m}{%
            \expandafter\UD@PassFirstToSecond\expandafter{%
              \romannumeral
              \expandafter\expandafter\expandafter\UD@PassFirstToSecond
              \expandafter\expandafter\expandafter{%
              \expandafter\@firstoftwo\expandafter{\expandafter}%
              \romannumeral\UD@ExtractFirstArgLoop{#4\UD@SelDOm}}{\z@#2}%
            }{%
              \expandafter\UD@CheckWhetherNull\expandafter{%
                \romannumeral\expandafter
                \UD@ExtractFirstArgLoop\expandafter{%
                  \romannumeral\UD@ExtractFirstArgLoop{#4\UD@SelDOm}%
                \UD@SelDOm}%
              }{%
                \UD@PassFirstToSecond{#1[NULL]}{\mxmloop}%
              }{%
                \expandafter\UD@PassFirstToSecond\expandafter{%
                  \romannumeral
                  \expandafter\UD@Exchange\expandafter{%
                    \romannumeral\expandafter
                    \UD@ExtractFirstArgLoop\expandafter{%
                      \romannumeral\UD@ExtractFirstArgLoop{#4\UD@SelDOm}%
                    \UD@SelDOm}%
                  }{\z@#1}%
                }{\mxmloop}%
              }%
            }%
          }%
        }%
      }%
    }%
  }%
}%

%%=============================================================================
% Let's define \x to collect an arbitrary amount of optional arguments and to display them:
\NewDocumentCommand\x{}{\innerx{}}%
\NewDocumentCommand\innerx{mo}{%
  \IfNoValueTF{#2}{\par\noindent\texttt{\detokenize\expandafter{\string\x#1}}}{\innerx{#1[#2]}}%
}%
\makeatother

\begin{document}

\footnotesize

\noindent Test 1:

\mxm
   [ [3,2]*[-3, 0]*[ 1,-2] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]
   [ [3,5]*[ 6,-7]*[-8, 9] ]

\bigskip\hrule\bigskip

\noindent Test 2:

\mxm
   [ [3,2]*[-3, 0] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]
   [ [3,5]*[ 6,-7]*[-8, 9] ]

\bigskip\hrule\bigskip

\noindent Test 3:

\mxm
   [ [3,2]*[-3, 0]*[ 1,-2]*[2,8] ]
   [ [1,1]*[ 0,-2]* * ]
   [ [3,5]*[ 6,-7]*[-8, 9]* ]

\bigskip\hrule\bigskip

\noindent Test 4:

\mxm
   [ [1,1]*[ 0,-2]]
   [ [3,2]*[-3, 0]*[ 1,-2]*[2,8]*[17,4] ]
   [ [3,5]*[ 6,-7]*[-8, 9]* ]

\bigskip\hrule\bigskip

\noindent Test 5:

\mxm
   [ [3,2]*[-3, 0]*[ 1,-2]*[2,8] ]
   [ ]
   [ [3,5]*[ 6,-7]*[-8, 9]* ]

\bigskip\hrule\bigskip

\noindent Test 6:

\mxm
   [ [3,2]*[-3, 0] ]
   [ [1,1]*[ 0,-2] ]
   [ [3,5]*[ 6,-7] ]
   [ [2,7]*[ 7,-0] ]
   [ [8,4]*[ 6,-0] ]

\bigskip\hrule\bigskip

\noindent Test 7:

\mxm
   [ [3,2]*[-3, 0]*[1,1]*[ 0,-2]*[3,5]*[ 6,-7] ]

\bigskip\hrule\bigskip

\noindent Test 8:

\mxm
   [ [3,2] ]

\bigskip\hrule\bigskip

\noindent Test 9:

\mxm
   [  ]

\bigskip\hrule\bigskip

\noindent Test 10:

\mxm

\noindent bla

\end{document}

Bildbeschreibung hier eingeben



Eine Variante hiervon kann zum Erstellen von Matrizen verwendet werden:

\documentclass{article}
\usepackage{xparse}
\usepackage{amsmath}

\makeatletter
%%=============================================================================
%% Little helpers:
%%.............................................................................
\newcommand\UD@PassFirstToSecond[2]{#2{#1}}%
\newcommand\UD@Exchange[2]{#2#1}%
%%-----------------------------------------------------------------------------
%% Check whether argument is empty:
%%.............................................................................
%% \UD@CheckWhetherNull{<Argument which is to be checked>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is empty>}%
%%                     {<Tokens to be delivered in case that argument
%%                       which is to be checked is not empty>}%
\newcommand\UD@CheckWhetherNull[1]{%
  \romannumeral\expandafter\@secondoftwo\string{\expandafter
  \@secondoftwo\expandafter{\expandafter{\string#1}\expandafter
  \@secondoftwo\string}\expandafter\@firstoftwo\expandafter{\expandafter
  \@secondoftwo\string}\expandafter\z@\@secondoftwo}%
  {\expandafter\z@\@firstoftwo}%
}%
%%-----------------------------------------------------------------------------
%% Extract first inner undelimited argument:
%%.............................................................................
%%   \romannumeral\UD@ExtractFirstArgLoop{<argument>\UD@SelDOm}%
%%   yields <argument>'s 1st undlimited argument.
%%   <argument> must not be blank, i.e., must neither be empty nor consist
%%   only of explicit character tokens of catcode 10 and charcode 32.
%%
%%   \UD@SelDOm must not be defined in terms of \outer !
%%.............................................................................
\@ifdefinable\UD@RemoveTillUD@SelDOm{%
  \long\def\UD@RemoveTillUD@SelDOm#1#2\UD@SelDOm{{#1}}%
}%
\newcommand\UD@ExtractFirstArgLoop[1]{%
  \expandafter\UD@CheckWhetherNull\expandafter{\@firstoftwo{}#1}%
  {\expandafter\z@\@secondoftwo{}#1}%
  {\expandafter\UD@ExtractFirstArgLoop\expandafter{\UD@RemoveTillUD@SelDOm#1}}%
}%


%%=============================================================================
%% \mxm starts a loop for collecting an arbitrary amount of optional arguments.
%%.............................................................................
\NewDocumentCommand\mxm{s}{%
  \IfBooleanTF{#1}{\innermxm{\x*}{}}{\innermxm{\x}{}}%
}%
%%-----------------------------------------------------------------------------
%% \innermxm checks if another optional argument is present.
%% If so it will be collected and \innermxm is called again.
%% Otherwise the loop for forming the calls to \x is started.
%%.............................................................................
\NewDocumentCommand\innermxm{mm >{\SplitList{*}}o}{%
  % #1 - command for creating matrices
  % #2 - list of brace-nested optional arguments collected so far.
  % #3 - either the no-value-marker or the next optional argument:
  \IfNoValueTF{#3}{%
    % Start the loop for forming the calls to \x/for re-arranging things:
    %   \romannumeral is not really needed here, but while writing
    %   this I wanted the missing-number-error in case of messing up
    %   the tail-recursive \mxmloop's  flipping-around/exchanging
    %   of arguments. ;-)
    \romannumeral\mxmloop{#1}{}{}{}{#2}{}%
  }{%
    % Add the current optional argument to the list #2 and check if
    % another optional argument is present...
    \innermxm{#1}{#2{#3}}%
  }%
}%

\newcommand\mxmloop[6]{%
  %#1 - command for creating matrices
  %#2 - token-list produced so far forming current command for creating matrices
  %#3 - new list of lists
  %#4 - indicator if all elements of current list of lists were empty. 
  %#5 - current list of lists
  %#6 - list of calls for creating matrices
  \UD@CheckWhetherNull{#5}{%
    \UD@CheckWhetherNull{#4}{%
      \z@#6% <- this \z@ terminates the (actually not needed)
           %   \romannumeral-expansion started by \innermxm. 
           %   It denotes a non-positive number and therefore
           %   gets removed silently.
    }{%
      \mxmloop{#1}{}{}{}{#3}{#6#1#2}%
    }%
  }{%
    \UD@PassFirstToSecond{#6}{%
      \expandafter\UD@PassFirstToSecond\expandafter{\@firstoftwo{}#5}{%
        \expandafter\UD@CheckWhetherNull\expandafter{\romannumeral\UD@ExtractFirstArgLoop{#5\UD@SelDOm}}{%
          \UD@PassFirstToSecond{#4}{%
            \UD@PassFirstToSecond{#3{}}{%
              \UD@PassFirstToSecond{#2%[NULL]
                                      }{\mxmloop{#1}}%
            }%
          }%
        }{%
          \UD@PassFirstToSecond{m}{%
            \expandafter\UD@PassFirstToSecond\expandafter{%
              \romannumeral
              \expandafter\expandafter\expandafter\UD@PassFirstToSecond
              \expandafter\expandafter\expandafter{%
              \expandafter\@firstoftwo\expandafter{\expandafter}%
              \romannumeral\UD@ExtractFirstArgLoop{#5\UD@SelDOm}}{\z@#3}%
            }{%
              \expandafter\UD@CheckWhetherNull\expandafter{%
                \romannumeral\expandafter
                \UD@ExtractFirstArgLoop\expandafter{%
                  \romannumeral\UD@ExtractFirstArgLoop{#5\UD@SelDOm}%
                \UD@SelDOm}%
              }{%
                \UD@PassFirstToSecond{#2%[NULL]
                                        }{\mxmloop{#1}}%
              }{%
                \expandafter\UD@PassFirstToSecond\expandafter{%
                  \romannumeral
                  \expandafter\UD@Exchange\expandafter{%
                    \romannumeral\expandafter
                    \UD@ExtractFirstArgLoop\expandafter{%
                      \romannumeral\UD@ExtractFirstArgLoop{#5\UD@SelDOm}%
                    \UD@SelDOm}%
                  }{\z@#2}%
                }{\mxmloop{#1}}%
              }%
            }%
          }%
        }%
      }%
    }%
  }%
}%

%%=============================================================================
% Let's define \x to collect an arbitrary amount of optional arguments and to create a matrix of them:
\NewDocumentCommand\x{s}{%
  \IfBooleanTF{#1}{\innerx{}{}{pmatrix}}{\innerx{}{}{bmatrix}}%
}%
\NewDocumentCommand\innerx{mmm >{\SplitList{,}}o}{%
  % #1 - matrix-content created so far
  % #2 - things to prepend to matrix-row to create (empty with 1st row, \\ otherwise)
  % #3 - name of matrix-environment
  % #4 - optional argument from which next matrix-row is to be created
  \IfNoValueTF{#4}%
  {\UD@CheckWhetherNull{#1}{}{\begin{#3}#1\end{#3}}}%
  {%
    \expandafter\innerx
    \expandafter{\romannumeral\expandafter\UD@Exchange\expandafter{\romannumeral\intersperseloop{#4}{}{}}{\z@#1#2}}%
    {\\}%
    {#3}%
  }%
}%
\newcommand\intersperseloop[3]{%
  %#1 - argument list
  %#2 - interspersed list
  %#3 - token to prepend (empty with 1st element, & otherwise)
  \UD@CheckWhetherNull{#1}{\z@#2}{%
    \UD@PassFirstToSecond{&}{%
      \expandafter\UD@PassFirstToSecond\expandafter{%
        \romannumeral\expandafter\UD@Exchange\expandafter{\romannumeral\UD@ExtractFirstArgLoop{#1\UD@SelDOm}}{\z@#2#3}%
      }{%
        \expandafter\UD@PassFirstToSecond\expandafter{\@firstoftwo{}#1}{%
          \intersperseloop
        }%
      }%
    }%
  }%
}%

\makeatother

\begin{document}

\footnotesize

\noindent Test 1:

$$\mxm
     [ [3,2]*[-3, 0]*[ 1,-2] ]
     [ [1,1]*[ 0,-2]*[-1, 3] ]
     [ [3,5]*[ 6,-7]*[-8, 9] ]$$

\bigskip\hrule\bigskip

\noindent Test 2:

$$\mxm*
     [ [3,2]*[-3, 0]         ]
     [ [1,1]*[ 0,-2]*[-1, 3] ]
     [ [3,5]*[ 6,-7]*[-8, 9] ]$$

\bigskip\hrule\bigskip

\noindent Test 2a:

$$\mxm
     [ [3,2]*       *[-3, 0] ]
     [ [1,1]*[ 0,-2]*[-1, 3] ]
     [ [3,5]*[ 6,-7]*[-8, 9] ]$$



\bigskip\hrule\bigskip

\noindent Test 3:

$$\mxm
     [ [3,2] * [-3, 0] * [ 1,-2] * [2,8] ]
     [ [1,1] * [ 0,-2] *         *       ]
     [ [3,5] * [ 6,-7] * [-8, 9] *       ]$$

\bigskip\hrule\bigskip

\noindent Test 4:

$$\mxm
     [ [1,1]*[ 0,-2]]
     [ [3,2]*[-3, 0]*[ 1,-2]*[2,8]*[17,4] ]
     [ [3,5]*[ 6,-7]*[-8, 9]* ]$$

\bigskip\hrule\bigskip

\noindent Test 5:

$$\mxm
     [ [3,2]*[-3, 0]*[ 1,-2]*[2,8] ]
     [ ]
     [ [3,5]*[ 6,-7]*[-8, 9]* ]$$

\bigskip\hrule\bigskip

\noindent Test 6:

$$\mxm*
     [ [3,2]*[-3, 0] ]
     [ [1,1]*[ 0,-2] ]
     [ [3,5]*[ 6,-7] ]
     [ [2,7]*[ 7,-0] ]
     [ [8,4]*[ 6,-0] ]
     [ [3,2]*[-3, 0] ]
     [ [1,1]*[ 0,-2] ]
     [ [3,5]*[ 6,-7] ]
     [ [2,7]*[ 7,-0] ]
     [ [8,4]*[ 6,-0] ]
     [ [3,2]*[-3, 0] ]
     [ [1,1]*[ 0,-2] ]
     [ [3,5]*[ 6,-7] ]
     [ [2,7]*[ 7,-0] ]
     [ [8,4]*[ 6,-0] ]$$

\bigskip\hrule\bigskip

\noindent Test 6b:

$$\mxm
     [ [3,2] * [-3, 0]   *         ]
     [ [1,1] *           * [ 0,-2] ]
     [ [3,5] *           * [ 6,-7] ]
     [ [2,7] *           * [ 7,-0] ]
     [ [8,4] *           * [ 6,-0] ]
     [       *           * [ 6,-0] ]$$


\bigskip\hrule\bigskip

\noindent Test 7:

$$\mxm
     [ [3,2]*[-3, 0]*[1,1]*[ 0,-2]*[3,5]*[ 6,-7] ]$$

\bigskip\hrule\bigskip

\noindent Test 8:

$$\mxm
     [ [3,2] ]$$

\bigskip\hrule\bigskip

\noindent Test 9:

$$\mxm
     [  ]$$

\bigskip\hrule\bigskip

\noindent Test 10:

$$\mxm$$

\noindent bla

\end{document}

Bildbeschreibung hier eingeben Bildbeschreibung hier eingeben

Antwort2

Wenn Sie Folgendes erstellen möchten \mxm:

\mxm
   [ [3,2]*[-3, 0]*[ 1,-2] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]

machen

\x[3,2][1,1]
\x[-3,0][0,-2]
\x[1,-2][-1,3]

dann können Sie definieren

\def\mxm [ [#1]*[#2]*[#3] ] [ [#4]*[#5]*[#6] ]{%
   \x[#1][#4]
   \x[#2][#5]
   \x[#3][#6]
}

Bearbeiten:Wenn ich Ihre Forderung richtig verstehe, müssen Sie die Parameter transponieren. Wenn die \mxmmit beliebigen Zeilen und Spalten angegeben ist, müssen Sie die

\mxm
   [ [A1]*[A2]*[A3]*[A4] ]
   [ [B1]*[B2]*[B3]*[B4] ]
   [ [C1]*[C2]*[C3]*[C4] ]

in eine Reihe von Anrufen:

\x[A1][B1][C1]
\x[A2][B2][C2]
\x[A3][B3][C3]
\x[A4][B4][C4]

Sie können den folgenden Code testen:

\newcount\numrows \newcount\tmpnum
\def\mxm {\numrows=0 \mxmA}
\def\mxmA [ #1 ] {\advance\numrows by1 \sdef{r:\the\numrows}{#1}%
   \futurelet\next\mxmB}
\def\mxmB {\ifx\next[\expandafter\mxmA \else \expandafter \mxmC\fi}
\def\mxmC {\expandafter\ifx \csname r:1\endcsname \empty \else
   \tmpnum=0 \def\xparams{}%
   \loop
      \advance\tmpnum by1
      \expandafter \expandafter \expandafter \mxmD
           \csname r:\the\tmpnum\endcsname \end
      \ifnum\tmpnum<\numrows \repeat
   \expandafter \x \xparams \relax
   \expandafter \mxmC \fi
}
\def\mxmD #1[#2]#3\end{\sdef{r:\the\tmpnum}{#3}\addto\xparams{[#2]}}

\long\def\addto#1#2{\expandafter\def\expandafter#1\expandafter{#1#2}}
\def\sdef#1{\expandafter\def\csname#1\endcsname}

% Just for testing:
\def\x #1\relax{\message{running \string\x #1}}

\mxm
     [ [A1]*[A2]*[A3]*[A4] ]
     [ [B1]*[B2]*[B3]*[B4] ]
     [ [C1]*[C2]*[C3]*[C4] ]

\bye

Die Ergebnismeldung dieses Codes (nach \pdftex testfile) lautet:

running \x[A1][B1][C1] running \x[A2][B2][C2]
running \x[A3][B3][C3] running \x[A4][B4][C4]

Antwort3

Ich halte das nicht für einen guten Ansatz, insbesondere bei den acht optionalen Argumenten. Aber der Kunde hat immer Recht.

\documentclass{article}
\usepackage{amsmath}

\ExplSyntaxOn

\NewDocumentCommand\makematrix{ s o o o o o o o o }
 {
  \begin{ \IfBooleanTF { #1 } { p } { b } matrix }
  \bryce_make_matrix:nnnnnnnn { #2 } { #3 } { #4 } { #5 } { #6 } { #7 } { #8 } { #9 }
  \end{ \IfBooleanTF { #1 } { p } { b } matrix }
 }
\NewDocumentCommand{\mxm} { s o o o o o o o o }
 {
  \group_begin: % localize the setting of the sequences
  \IfValueT{#2}
   {
    \seq_set_split:Nnn \l__bryce_mxm_i_seq { * } { #2 }
   }
  \IfValueT{#3}
   {
    \seq_set_split:Nnn \l__bryce_mxm_ii_seq { * } { #3 }
   }
  \IfValueT{#4}
   {
    \seq_set_split:Nnn \l__bryce_mxm_iii_seq { * } { #4 }
   }
  \IfValueT{#5}
   {
    \seq_set_split:Nnn \l__bryce_mxm_iv_seq { * } { #5 }
   }
  \IfValueT{#6}
   {
    \seq_set_split:Nnn \l__bryce_mxm_v_seq { * } { #6 }
   }
  \IfValueT{#7}
   {
    \seq_set_split:Nnn \l__bryce_mxm_vi_seq { * } { #7 }
   }
  \IfValueT{#8}
   {
    \seq_set_split:Nnn \l__bryce_mxm_vii_seq { * } { #8 }
   }
  \IfValueT{#9}
   {
    \seq_set_split:Nnn \l__bryce_mxm_viii_seq { * } { #9 }
   }
  \cs_set_protected:Nx \__bryce_mxm:
   {
    \makematrix \IfBooleanT { #1 } { * }
   }
  \__bryce_mxm_do:
  \group_end:
 }

\cs_new_protected:Nn \bryce_make_matrix:nnnnnnnn
 {
  \tl_if_novalue:nF { #1 } { \__bryce_make_row:n { #1 } }
  \tl_if_novalue:nF { #2 } { \__bryce_make_row:n { #2 } }
  \tl_if_novalue:nF { #3 } { \__bryce_make_row:n { #3 } }
  \tl_if_novalue:nF { #4 } { \__bryce_make_row:n { #4 } }
  \tl_if_novalue:nF { #5 } { \__bryce_make_row:n { #5 } }
  \tl_if_novalue:nF { #6 } { \__bryce_make_row:n { #6 } }
  \tl_if_novalue:nF { #7 } { \__bryce_make_row:n { #7 } }
  \tl_if_novalue:nF { #8 } { \__bryce_make_row:n { #8 } }
 }

\cs_new_protected:Nn \__bryce_make_row:n
 {
  \clist_set:Nn \l__bryce_row_clist { #1 }
  \clist_use:Nn \l__bryce_row_clist { & }
  \\
 }


\seq_new:N \l__bryce_mxm_i_seq
\seq_new:N \l__bryce_mxm_ii_seq
\seq_new:N \l__bryce_mxm_iii_seq
\seq_new:N \l__bryce_mxm_iv_seq
\seq_new:N \l__bryce_mxm_v_seq
\seq_new:N \l__bryce_mxm_vi_seq
\seq_new:N \l__bryce_mxm_vii_seq
\seq_new:N \l__bryce_mxm_viii_seq
\int_new:N \l__bryce_mxm_int

\cs_new_protected:Nn \__bryce_mxm_do:
 {
  \int_step_inline:nn { \seq_count:N \l__bryce_mxm_i_seq }
   {
    \int_set:Nn \l__bryce_mxm_int { ##1 }
    \exp_last_unbraced:Ne \__bryce_mxm: \__bryce_mxm_args:
   }
 }
\cs_new:Nn \__bryce_mxm_args:
 {
  \int_step_function:nN { 8 } \__bryce_mxm_args_aux:n
 }
\cs_new:Nn \__bryce_mxm_args_aux:n
 {
  \seq_item:cn { l__bryce_mxm_\int_to_roman:n { #1 }_seq } { \l__bryce_mxm_int }
 }

\ExplSyntaxOff

\begin{document}

\[
\makematrix[3,2][1,1]
\makematrix[-3, 0][ 0,-2]
\makematrix[ 1,-2][-1, 3]
\]

\[
\mxm
   [ [3,2]*[-3, 0]*[ 1,-2] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]
\]

\[
\makematrix*[3,2][1,1]
\makematrix*[-3, 0][ 0,-2]
\makematrix*[ 1,-2][-1, 3]
\]

\[
\mxm*
   [ [3,2]*[-3, 0]*[ 1,-2] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]
\]

\end{document}

Bildbeschreibung hier eingeben

Antwort4

Es wäre viel einfacher, wenn Ihnen die Verwendung einer Zahnspange nichts ausmachen würde.

Bildbeschreibung hier eingeben

\documentclass{article}
\usepackage[T1]{fontenc}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{amsmath}

\ExplSyntaxOn

\tl_new:N \l_doc_tmpa_tl
\tl_new:N \l_doc_tmpb_tl
\tl_new:N \l_doc_tmpc_tl

\int_new:N \l_doc_tmpa_int
\int_new:N \l_doc_tmpb_int
\int_new:N \l_doc_tmpc_int
\clist_new:N \l_doc_tmpa_clist

\seq_new:N \l_doc_tmpa_seq
\seq_new:N \l_doc_tmpb_seq
\seq_new:N \l_doc_tmpc_seq
\seq_new:N \l_doc_tmpd_seq
\seq_new:N \l_doc_tmpe_seq

\cs_set:Npn \doc_extract_square_bracket:nN #1#2 {
  \tl_set:Nn \l_doc_tmpa_tl {#1}
  \seq_clear:N #2
  \int_set:Nn \l_doc_tmpa_int {0}
  \tl_clear:N \l_doc_tmpc_tl
  
  \bool_do_until:nn {\tl_if_empty_p:N \l_doc_tmpa_tl} {
    \tl_set:Nx \l_doc_tmpb_tl {\tl_head:N \l_doc_tmpa_tl}
    \tl_set:Nx \l_doc_tmpa_tl {\tl_tail:N \l_doc_tmpa_tl}
    
    \exp_args:NV \str_case:nnF \l_doc_tmpb_tl {
      {[} {
        \int_compare:nNnT {\l_doc_tmpa_int} > {0} {
          \tl_put_right:NV \l_doc_tmpc_tl \l_doc_tmpb_tl
        }
        \int_incr:N \l_doc_tmpa_int
      }
      {]} {
        \int_decr:N \l_doc_tmpa_int
        \int_compare:nNnTF {\l_doc_tmpa_int} > {0} {
          \tl_put_right:NV \l_doc_tmpc_tl \l_doc_tmpb_tl
        }{
          \seq_put_right:NV #2 \l_doc_tmpc_tl
          \tl_clear:N \l_doc_tmpc_tl
        }
      }
    } {
      \int_compare:nNnT {\l_doc_tmpa_int} > {0} {
        \tl_put_right:NV \l_doc_tmpc_tl \l_doc_tmpb_tl
      }
    }
  }
}

\newcommand{\x}[1]{
  \seq_clear:N \l_doc_tmpc_seq
  \doc_extract_square_bracket:nN {#1} \l_doc_tmpb_seq
  \seq_map_variable:NNn \l_doc_tmpb_seq \l_doc_tmpa_tl {
    \clist_set:NV \l_doc_tmpa_clist \l_doc_tmpa_tl
    \seq_put_right:Nx \l_doc_tmpc_seq {\clist_use:Nn \l_doc_tmpa_clist {\c_alignment_token}}
  }
  \begin{bmatrix}
    \seq_use:Nn \l_doc_tmpc_seq {\\}
  \end{bmatrix}
}

\cs_set:Npn \doc_temp_seq_name:n #1 {
  l__doc_mat_\int_to_alph:n {#1}_seq
}

\newcommand{\mxm}[1]{
  \doc_extract_square_bracket:nN {#1} \l_doc_tmpd_seq
  
  \seq_get_left:NN \l_doc_tmpd_seq \l_doc_tmpa_tl
  \exp_args:NV \doc_extract_square_bracket:nN \l_doc_tmpa_tl \l_doc_tmpe_seq
  \int_set:Nn \l_doc_tmpb_int {\seq_count:N \l_doc_tmpe_seq}
  \seq_show:N \l_doc_tmpd_seq
  \int_step_inline:nn {\l_doc_tmpb_int} {
    \seq_clear:c {\doc_temp_seq_name:n {##1}}
  }
  
  \seq_map_variable:NNn \l_doc_tmpd_seq \l_doc_tmpa_tl {
    \exp_args:NV \doc_extract_square_bracket:nN \l_doc_tmpa_tl \l_doc_tmpe_seq
    \int_set:Nn \l_doc_tmpc_int {1}
    \seq_map_variable:NNn \l_doc_tmpe_seq \l_doc_tmpb_tl {
      \tl_clear:N \l_doc_tmpc_tl
      \tl_put_right:Nn \l_doc_tmpc_tl {[}
      \tl_put_right:NV \l_doc_tmpc_tl \l_doc_tmpb_tl
      \tl_put_right:Nn \l_doc_tmpc_tl {]}
      \seq_put_right:cV {\doc_temp_seq_name:n {\l_doc_tmpc_int}} \l_doc_tmpc_tl
      \int_incr:N \l_doc_tmpc_int
    }
  }
  
  \int_step_inline:nn {\l_doc_tmpb_int} {
    \tl_set:Nx \l_doc_tmpa_tl {\exp_not:N\x{\seq_use:cn {\doc_temp_seq_name:n {##1}} {}}}
    \tl_use:N \l_doc_tmpa_tl
  }
}

\ExplSyntaxOff

\begin{document}
$$\x{[1,2,3][4,5,6][7,8,9]}$$
$$\x{[1,2,3,4,5,6][a,b,c,d,e,f][6,5,4,3,2,1]}$$
$$\x{[1,2][3,4][5,6][7,8][9,10][11,12]}$$
$$
\mxm{
   [ [3,2]*[-3, 0]*[ 1,-2] ]
   [ [1,1]*[ 0,-2]*[-1, 3] ]
}
$$
$$
\mxm{
   [ [3,2]+[-3, 0]+[ 1,-2] ]
   [ [1,1]+[ 0,-2]+[-1, 3] ]
}
$$
$$
\mxm{
   [ [3,2][-3, \alpha][ 1,-2][5,6] ]
   [ [1,1][ 0,-2][-1, 3][5,6] ]
   [ [1,1][ 0,-2][-1, 3][5,6] ]
   [ [1,1][ 0,-2][-1, 3][5,6] ]
   [ [1,1][ 0,-2][-1, 3][5,6] ]
   [ [1,1][ 0,-2][\frac{3}{2}, 3][5,6] ]
}
$$
\end{document}

verwandte Informationen