Я работаю над макросом, который должен сэкономить мне много времени в будущем. В настоящее время у меня работает одна из команд, которую я хотел, но у меня возникли проблемы с тем, чтобы заставить работать вторую часть. Первая команда определена следующим образом:
\NewDocumentCommand\x
{
s
>{\SplitList{,}}o
>{\SplitList{,}}o
>{\SplitList{,}}o
>{\SplitList{,}}o
>{\SplitList{,}}o
>{\SplitList{,}}o
>{\SplitList{,}}o
>{\SplitList{,}}o
}{
% Full definition of the command
}
Эта команда принимает восемь необязательных аргументов, каждый из которых представляет собой список, разделенный запятыми, обычно это числа, хотя это не обязательно. Я мог бы назвать его как \x[-3,0][0,-2]
или \x[1,2,3,0][4,5,6,0][7,8,9,0]
. Каждый список всегда будет иметь одинаковую длину.
Я пытаюсь создать вторую команду, которая действует немного как транспонирование. Так что она также занимает до восьми списков, но эти списки разделены звездочками, а элементы — это списки из команды \x
. Проще всего показать на примере, как это работает:
\mxm
[ [3,2]*[-3, 0]*[ 1,-2] ]
[ [1,1]*[ 0,-2]*[-1, 3] ]
будет эквивалентно:
\x[3,2][1,1]
\x[-3,0][0,-2]
\x[1,-2][-1,3]
Каждый из этих списков звезд будет иметь одинаковое количество элементов. Если бы у них было разное количество элементов или элементов, которые не были бы аргументами команды, \x
то могло бы произойти что угодно: ошибка, вставка какого-то нулевого элемента, усечение до самого короткого списка и т. д. Он не будет так называться, так что это не имеет значения.
Длина этих списков — это количество \x
вызовов. В этом примере длина равна трем, поэтому есть три вызова, \x
но если бы длина была больше или меньше, было бы другое число. Количество списков — это количество аргументов для каждого вызова \x
. В этом примере их два, но их может быть до 8.
Если возможно, я бы хотел иметь возможность передавать звезду от \mxm*
к, \x*
но если это слишком сложно, то у меня есть альтернативное решение, поскольку это не должно встречаться очень часто. Вот как это будет выглядеть:
\mxm[[1,3,1]*[-1, 0,3]]
[[2,2,1]*[ 0,-2,2]]
[[3,1,2]*[ 1,-2,1]]
будет эквивалентно:
\x*[1,3,1]
[2,2,1]
[3,1,2]
\x*[-1, 0,3]
[ 0,-2,2]
[ 1,-2,1]
Вот MWEс примером \x
(просто заглушка, может не называться \x
). Он также включает в себя то, как далеко я продвинулся, хотя я не могу себе представить, что это сильно поможет.
решение1
Хвостовая рекурсия, т. е. макросы, которые вызывают сами себя снова, и большой обмен аргументами заранее, могут помочь. ;-)
Если я правильно понимаю, \mxm
это обработка списка необязательных аргументов, каждый из которых содержит *
разделенный -списка необязательных аргументов.
Вы не указали, что делать, если не все *
разделенные -списки необязательных аргументов содержат одинаковое количество элементов.
Поэтому я взял на себя смелость реализовать вещи так, чтобы [NULL]
это было предусмотрено везде, где *
отсутствуют элементы, разделенные -, из-за того, что списки имеют разную длину или аргументы между *
ними указаны как пустые.
\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}
Один из вариантов этого можно использовать для создания матриц:
\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}
решение2
Если вы хотите создать \mxm
:
\mxm
[ [3,2]*[-3, 0]*[ 1,-2] ]
[ [1,1]*[ 0,-2]*[-1, 3] ]
делать
\x[3,2][1,1]
\x[-3,0][0,-2]
\x[1,-2][-1,3]
тогда вы можете определить
\def\mxm [ [#1]*[#2]*[#3] ] [ [#4]*[#5]*[#6] ]{%
\x[#1][#4]
\x[#2][#5]
\x[#3][#6]
}
Редактировать:Если я правильно понял ваш запрос, то вам нужно транспонировать параметры. Когда \mxm
дано с произвольными строками и столбцами, то вам нужно преобразовать
\mxm
[ [A1]*[A2]*[A3]*[A4] ]
[ [B1]*[B2]*[B3]*[B4] ]
[ [C1]*[C2]*[C3]*[C4] ]
в серию звонков:
\x[A1][B1][C1]
\x[A2][B2][C2]
\x[A3][B3][C3]
\x[A4][B4][C4]
Вы можете протестировать следующий код:
\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
Результат сообщения этого кода (после \pdftex testfile
) следующий:
running \x[A1][B1][C1] running \x[A2][B2][C2]
running \x[A3][B3][C3] running \x[A4][B4][C4]
решение3
Я не думаю, что это хороший подход, особенно в восьми необязательных аргументах. Но клиент всегда прав.
\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}
решение4
Все было бы намного проще, если бы вы не возражали против использования брекетов.
\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}