저는 앞으로 많은 시간을 절약할 수 있는 매크로를 작업 중입니다. 현재 원하는 명령 중 하나가 작동하고 있지만 두 번째 부분을 작동시키는 데 문제가 있습니다. 첫 번째 명령은 다음과 같이 정의됩니다.
\NewDocumentCommand\x
{
s
>{\SplitList{,}}o
>{\SplitList{,}}o
>{\SplitList{,}}o
>{\SplitList{,}}o
>{\SplitList{,}}o
>{\SplitList{,}}o
>{\SplitList{,}}o
>{\SplitList{,}}o
}{
% Full definition of the command
}
이 명령은 8개의 선택적 인수를 사용하며 각 인수는 쉼표로 구분된 목록이며 일반적으로 숫자이지만 필수는 아닙니다. 나는 그것을 \x[-3,0][0,-2]
또는 와 같이 부를 수 있습니다 \x[1,2,3,0][4,5,6,0][7,8,9,0]
. 각 목록의 길이는 항상 동일합니다.
저는 전치와 비슷한 역할을 하는 두 번째 명령을 만들려고 합니다. 따라서 최대 8개의 목록도 필요하지만 이러한 목록은 별표로 구분되어 있으며 요소는 명령의 목록입니다 \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
오류, 일종의 null 요소 삽입, 가장 짧은 목록으로 잘림 등의 문제가 발생할 수 있습니다. 그런 식으로 호출되지 않으므로 그렇게 하지 않습니다. 상관없어.
이 목록의 길이는 \x
통화 횟수입니다. 이 예에서는 길이가 3이므로 3번의 호출이 있지만 \x
길이가 더 길거나 짧으면 다른 숫자가 발생합니다. 목록의 수는 각 호출에 대한 인수 수입니다 \x
. 이 예에서는 2개가 있지만 최대 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
나는 이것이 특히 8개의 선택적 인수에 있어서 좋은 접근 방식이라고 생각하지 않습니다. 하지만 고객의 말은 언제나 옳습니다.
\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}