我正在尝试进入 LaTeX 递归并创建了一个命令\tower[2][3][4][2]
返回电力塔,,2^{3^{4^2}}
任意数量的参数。我的尝试:
\documentclass{beamer}
\usepackage{xparse}
\NewDocumentCommand\tower{o}{%
\IfValueT{#1}{\towerstep{#1}}}
\NewDocumentCommand\towerstep{m}{%
#1^\tower}
\begin{document}
\begin{frame}
\tower[2][3][4][2]
\end{frame}
\end{document}
这会产生很多错误,但会给出正确的输出。错误来自不在数学模式下的表达式(添加$
使情况变得更糟)以及缺少括号。我认为这与命令展开的顺序有关。我该如何修复代码?
答案1
本着持续编程精神的解决方案:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand \towerAux { m o }
{
\IfValueTF { #2 }
{ \towerAux {{#1}{#2}} }
{ \__tower:nn {#1} { } }
}
\cs_set:Npn \__tower:nn #1 #2
{
\tl_if_empty:nTF { #1 }
{ #2 }
{ \__tower_i:nnn #1 { #2 } }
}
\cs_set:Npn \__tower_i:nnn #1 #2 #3 { \__tower:nn { #1 } { #2 ^ { #3 } } }
\NewDocumentCommand \tower { } { \towerAux { } }
\ExplSyntaxOff
\begin{document}
$\tower[5][3][4][2]$
\end{document}
使用该程序,$\tower[5][3][4][2]$
将依次替换以下指令:
$\tower[5][3][4][2]$
$\towerAux{}[5][3][4][2]$
$\towerAux{{}{5}}[3][4][2]$
$\towerAux{{{}{5}}{3}}[4][2]$
$\towerAux{{{{}{5}}{3}}{4}}[2]$
$\towerAux{{{{{}{5}}{3}}{4}}{2}}$
如你所见,\towerAux
是递归的。
现在,所有参数(如果我可以这么说)都已构造成一种列表,最后一个参数是第一个可访问的。现在,您可以像在递归编程中一样,在一种辅助参数(末尾)中构造所需的结果。命令\__tower:nn
和\__tower_i:nnn
是相互递归的。
$\__tower:nn{{{{{}{5}}{3}}{4}}{2}}{}$
$\__tower_i:nnn{{{{}{5}}{3}}{4}}{2}{}$
$\__tower:nn{{{{}{5}}{3}}{4}}{2^{}}$
$\__tower_i:nnn{{{}{5}}{3}}{4}{2^{}}$
$\__tower:nn{{{}{5}}{3}}{4^{2^{}}}$
$\__tower_i:nnn{{}{5}}{3}{4^{2^{}}}$
$\__tower:nn{{}{5}}{3^{4^{2^{}}}}$
$\__tower_i:nnn{}{5}{3^{4^{2^{}}}}$
$\__tower_i:nnn{}{5^{3^{4^{2^{}}}}}$
$5^{3^{4^{2^{}}}}$
答案2
\documentclass[border=15pt]{standalone}
\makeatletter
\def\tower{\@ifnextchar[{\def\endtower{}\towerstep}{}}%
\def\towerstep[#1]{#1%
\@ifnextchar[{\edef\endtower{\endtower\egroup}^\bgroup\towerstep}{\endtower}}
\makeatother
\begin{document}
$\tower[2][3][4][2]$
$\tower[2][3][4]$
$\tower[2][3]$
$\tower[2]$
$\tower$
\end{document}
答案3
我建立了两个标记列表,第一个包含
{1^{2^{3^{4^{5^{6^{7
另一个包含
}}}}}}}
实际上,括号存储为\c_group_begin_token
和\c_group_end_token
,因此标记列表是平衡的。
如果[
有,则采取进一步措施。最后,交付两个列表。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\tower}{}
{
\tl_clear:N \l__perner_tower_left_tl
\tl_clear:N \l__perner_tower_right_tl
\perner_tower_build:n { }
}
\tl_new:N \l__perner_tower_left_tl
\tl_new:N \l__perner_tower_right_tl
\cs_new_protected:Nn \perner_tower_build:n
{
\peek_charcode:NTF [
{% there is a [
\__perner_tower_add:nw { #1 }
}
{% no [, end
\__perner_tower_end:
}
}
\cs_new_protected:Npn \__perner_tower_add:nw #1 [#2]
{
\tl_put_right:Nn \l__perner_tower_left_tl { #1 \c_group_begin_token #2 }
\tl_put_right:Nn \l__perner_tower_right_tl { \c_group_end_token }
\perner_tower_build:n { \c_math_superscript_token }
}
\cs_new_protected:Npn \__perner_tower_end:
{
\tl_use:N \l__perner_tower_left_tl
\tl_use:N \l__perner_tower_right_tl
}
\ExplSyntaxOff
\begin{document}
$\tower[1][2][3][4][5][6][7]$
\end{document}
使用不同的语法,更简短。参数以逗号分隔;然后我们输出任意两个项^{
(再次作为隐式标记),最后}
输出正确数量的。
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\tower}{m}
{
\perner_tower_build:n { #1 }
}
\seq_new:N \l__perner_tower_seq
\cs_new_protected:Nn \perner_tower_build:n
{
\seq_set_split:Nnn \l__perner_tower_seq { , } { #1 }
\seq_use:Nn \l__perner_tower_seq { \c_math_superscript_token \c_group_begin_token }
\prg_replicate:nn { \seq_count:N \l__perner_tower_seq - 1 } { \c_group_end_token }
}
\ExplSyntaxOff
\begin{document}
$\tower{1,2,3,4,5,6,7}$
\end{document}
答案4
也许是这样的:
\documentclass{beamer}
\usepackage{xparse}
%-----------------------------------------------------------------------------
% In case there is an optional argument \tower calls \towerreverseloop:
%-----------------------------------------------------------------------------
\NewDocumentCommand\tower{o}{%
\IfValueT{#1}{\towerreverseloop{[{#1}]}}%
}%
%-----------------------------------------------------------------------------
% \towerreverseloop reverses the order of the list of optional arguments.
% #1 holds the reversed list of optional arguments gathered so far.
% #2 is the next optional argument.
% If there are no more optional arguments to put into reversed order,
% then \towerinitializeconstructexpressionloop is applied to the reversed
% list of optional arguments gathered so far.
%-----------------------------------------------------------------------------
\NewDocumentCommand\towerreverseloop{mo}{%
\IfValueTF{#2}{%
\towerreverseloop{[{#2}]#1}%
}{%
\towerinitializeconstructexpressionloop#1%
}%
}%
%-----------------------------------------------------------------------------
% \towerinitializeconstructexpressionloop calls \towerconstructexpressionloop,
% hereby initializing \towerconstructexpressionloop's "expression constructed
% so far"-argument with the first element of the reversed list of optional
% arguments.
%-----------------------------------------------------------------------------
\NewDocumentCommand\towerinitializeconstructexpressionloop{o}{%
\towerconstructexpressionloop{#1}%
}%
%-----------------------------------------------------------------------------
% \towerconstructexpressionloop constructs the desired expression from the
% elements of the reversed list of optional arguments.
% #1 holds the expression constructed so far.
% #2 next optional argument/next element of the reversed list of
% optional arguments.
%-----------------------------------------------------------------------------
\NewDocumentCommand\towerconstructexpressionloop{mo}{%
\IfValueTF{#2}%
{\towerconstructexpressionloop{#2^{#1}}}%
{#1%
%\def\result{#1}\show\result
}%
}%
\begin{document}
\begin{frame}[fragile]
\verb|$\tower[2][3][4][2]$|: $\tower[2][3][4][2]$\\
\verb|$\tower[2][3][4]$|: $\tower[2][3][4]$\\
\verb|$\tower[2][3]$|: $\tower[2][3]$\\
\verb|$\tower[2]$|: $\tower[2]$\\
\verb|$\tower$|: $\tower$
\end{frame}
\end{document}