我正在尝试创建一个宏,在输入string
(其中的n
长度为string
)时,它将创建一个数组,该数组将手动由
\begin{array}{ccc... % n c's here}
string[0] & string[1] & string[2] & ... & string[n-1]
\end{array}
例如,输入12345
应该给出
\begin{array}{ccccc}
1 & 2 & 3 & 4 & 5
\end{array}
我尽了最大努力,做出了以下尝试
\documentclass{article}
\usepackage{xstring, etoolbox, pgffor}
\newcommand{\cycle}[1]{%
\def\mystring{{#1}}
\StrLen{\mystring}[\mystringlen]
\def\columns{c}
\def\content{\empty}
\foreach \x in {0,...,\mystringlen - 1} {%
\appto\columns{c}
\appto\content{\StrMid{\mystring}{\x}{\x + 1} \& }
}
\appto\content{\StrMid{\mystring}{\mystringlen - 1}{\mystringlen}}
\begin{array}{\columns} \content \end{array}
}
\begin{document}
$\cycle{12345}$
\end{document}
以及大量错误。我对这种深度的 LaTeX 还不熟悉,所以如果有人能告诉我这个特定示例有什么问题、更好的方法和/或我应该查看的相关资料,我将不胜感激。提前致谢。
答案1
\documentclass{article}
\makeatletter
\def\cycle#1{\xcycle{}{\@gobble}#1\relax}
\def\xcycle#1#2#3{%
\ifx\relax#3%
\begin{array}{#1}#2\end{array}%
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
{\xcycle{#1c}{#2}}}
\makeatother
\begin{document}
$\cycle{12345}$
\end{document}
或者使用egreg的扩展要求:
\documentclass{article}
\makeatletter
\def\cycle#1{\xcycle{}{\@gobble}#1\relax}
\def\xcycle#1#2#3{%
\ifx\relax#3%
\begin{array}{@(#1@)}#2\end{array}%
\expandafter\@gobble
\else
\expandafter\@firstofone
\fi
{\xcycle{#1c}{#2}}}
\def\permutation#1{\xpermutation{}{\@gobble}#1\relax}
\def\xpermutation#1#2#3{%
\ifx\relax#3%
\begin{array}{@(#1@)}#2\end{array}%
\expandafter\@gobbletwo
\else
\ifx;#3%
\expandafter\expandafter\expandafter\@secondoftwo
\else
\expandafter\expandafter\expandafter\@firstoftwo
\fi\fi
{\xpermutation{#1c}{#2}}{\xpermutation{#1@{}c@{}}{#2&)(}}%
}
\makeatother
\begin{document}
$\cycle{12345}$
$\permutation{12;34;567}$
\end{document}
答案2
我建议采用基于expl3
和的方法xparse
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\cycle}{m}
{
% split at "nothing"
\seq_set_split:Nnn \l_egreg_cycle_seq { } { #1 }
% the sequence length can be used to set the number of columns
\begin{array}{* { \seq_count:N \l_egreg_cycle_seq } { c } }
% use the sequence
\seq_use:Nn \l_egreg_cycle_seq { & }
\end{array}
}
\seq_new:N \l_egreg_cycle_seq
\ExplSyntaxOff
\begin{document}
X$\cycle{12345}$X
\end{document}
您可以轻松地改进这一点,使用舒适的语法将排列打印为不相交的循环:
\documentclass{article}
\usepackage{xparse}
\usepackage{amsmath}
\ExplSyntaxOn
\NewDocumentCommand{\cycle}{m}
{
\egreg_cycle:n { #1 }
}
\NewDocumentCommand{\permutation}{m}
{
\egreg_permutation:n { #1 }
}
\seq_new:N \l_egreg_permutation_seq
\seq_new:N \l_egreg_cycle_seq
\cs_new_protected:Nn \egreg_permutation:n
{
% split the input at semicolons
\seq_set_split:Nnn \l_egreg_permutation_seq { ; } { #1 }
% map the obtained sequence passing each item to \egreg_cycle:n
\seq_map_inline:Nn \l_egreg_permutation_seq
{
\egreg_cycle:n { ##1 }
}
}
\cs_new_protected:Nn \egreg_cycle:n
{
% split at "nothing"
\seq_set_split:Nnn \l_egreg_cycle_seq { } { #1 }
% use the sequence; no array needed, just spacing in the middle
(\seq_use:Nn \l_egreg_cycle_seq { \mspace{6mu} })
}
\ExplSyntaxOff
\begin{document}
$\cycle{12345}$
$\permutation{12;34;567}$
\end{document}