是否可以在 LaTeX 中创建一个类似表格的结构,表示对各个单元进行模 10 的连续模 10 加法和环绕式?这称为链式添加。
例如,从 123456 开始,链式添加,我们有
┌────────── 转移 ── ──────────┐ | | | 五 1┌2┌3┌4┌5┌6┌1 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ 3 5 7 9 1 7
(模 10 加法)得到 357917。再次进行链式加法,我们得到
┌────────── 转移 ── ──────────┐ | | | 五 3 ┌ 5 ┌ 7 ┌ 9 ┌ 1 ┌ 7 ┌ 3 │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ │ 8 2 6 0 8 0
(对 10 进行模加)得到 826080。将其制成表格,我们得到:
1 2 3 4 5 6
3 5 7 9 1 7
8 2 6 0 8 0
0 8 6 8 8 8
. . . . . .
等等等等。
您会注意到它的添加没有进位,因此对 10 进行取模。
我希望能够只输入起始数字并生成包含其他数字的表格
我知道你可以在 LaTeX 中进行数学计算,但我不知道从哪里开始才能选择初始输入。
答案1
电子表格的作业:
\documentclass{article}
\usepackage{spreadtab}
\begin{document}
\begin{spreadtab}{{tabular}{*6{c}}}
\SThiderow 1 & 2 & 3 & 4 & 5 & 6\\
\STcopy{>5,v}{a1+b1-10*trunc((a1+b1)/10,0)}&&&&&\STcopy{v}{a1+f1-10*trunc((a1+f1)/10,0)}\\
&&&&&\\
&&&&&\\
&&&&&\\
&&&&&\\
&&&&&\\
\end{spreadtab}
\end{document}
答案2
第二次更新增加了最终循环的自动确定功能。添加在答案底部。
第一次更新添加表格:我不确定 的具体含义table
,因此第一个版本只是将数字链输出为连续的段落。带有表格的版本位于答案的底部。
\documentclass{article}
\newcommand*{\modten}[1]{\the\numexpr #1+10-((#1+5)/10)*10\relax}
\makeatletter
% expandable implementation
% #1 = initial string
% #2 number of reps
\newcommand*{\chainadd}[2]{#1\endgraf\chainadd@i {#2}#1\relax }
\def\chainadd@i #1#2#3\relax {\ifnum #1=0 \expandafter\@gobble\else
\expandafter\@firstofone \fi
{\expandafter\chainadd@ii\expandafter{\the\numexpr #1-1}{}#2#3#2\relax }}
\def\chainadd@ii #1#2#3#4{\ifx\relax #4\expandafter\@firstoftwo\else
\expandafter\@secondoftwo\fi
{#2\endgraf\chainadd@i {#1}#2\relax}%
{\expandafter\expandafter\expandafter\chainadd@iii\modten{#3+#4}{#2}{#1}#4}}
\def\chainadd@iii #1#2#3{\chainadd@ii {#3}{#2#1}}
\makeatother
\begin{document}
\chainadd {123456}{10}
\bigskip
\chainadd {1234567}{10}
\end{document}
将输出显示为表格行的代码:我不确定输入数据是否是输出的第一行。此外,表格中的列数必须由用户提供,如果需要,可以进行修改,不仅可以\chainadd
生成行,还可以\begin{tabular}
使用\end{tabular}
合适的表格模板生成行。
由于核心实现是可扩展的,因此可以\chainadd
最容易地将其自身插入表格中。
与第一个实现一样,\chainadd
它有两个参数,第一个是任意长度的十进制数字链,第二个是该过程必须重复的次数。初始数据构成输出的第一行。然后,根据第二个参数的要求,还有尽可能多的附加行\chainadd
。
\documentclass{article}
\newcommand*{\modten}[1]{\the\numexpr #1+10-((#1+5)/10)*10\relax}
\makeatletter
% expandable implementation
% #1 = initial string
% #2 number of reps
% Update with added \ChainRow to prepare tabular rows
\newcommand*{\chainadd}[2]{\ChainRow{#1}\chainadd@i {#2}#1\relax }
\def\chainadd@stop #1\relax {}
\def\chainadd@i #1#2#3\relax {\ifnum #1=\z@\expandafter\chainadd@stop\fi
\expandafter\chainadd@ii\expandafter{\the\numexpr #1-\@ne}{}#2#3#2\relax }
\def\chainadd@ii #1#2#3#4{\ifx\relax #4\expandafter\@firstoftwo\else
\expandafter\@secondoftwo\fi
{\ChainRow{#2}\chainadd@i {#1}#2\relax}%
{\expandafter\expandafter\expandafter\chainadd@iii\modten{#3+#4}{#2}{#1}#4}}
\def\chainadd@iii #1#2#3{\chainadd@ii {#3}{#2#1}}
\newcommand*{\ChainRow}[1]{\chainrow@i #1\relax}
\def\chainrow@i #1{#1\chainrow@ii }
\def\chainrow@ii #1{\ifx\relax #1\expandafter\@firstoftwo
\else
\expandafter\@secondoftwo\fi
{\\}{\chainrow@ii}}
\makeatother
\begin{document}
\begin{table}[ht]
\centering
\begin{tabular}{cccccc}
\hline
\chainadd {123456}{10}
\hline
\end{tabular}
\end{table}
\begin{table}[ht]
\centering
\begin{tabular}{ccccccc}
\hline
\chainadd {1234567}{10}
\hline
\end{tabular}
\end{table}
\end{document}
现在自动确定迭代过程的周期。
\documentclass{article}
\newcommand*{\modten}[1]{\the\numexpr #1+10-((#1+5)/10)*10\relax}
\makeatletter
% Looking for the cycle.
\def\gobtoexclam #1!{}
\newcommand*{\chainiterate}[1]
{\romannumeral0\expandafter\chainiterate@i\romannumeral-`0#1!}
\def\chainiterate@i #1#2!{\chainiterate@ii {}#1#2#1!}
\def\chainiterate@ii #1#2#3{\gobtoexclam #3\chainiterate@end!%
\expandafter\expandafter\expandafter\chainiterate@iii \modten{#2+#3}#3{#1}}
\def\chainiterate@iii #1#2#3{\chainiterate@ii {#3#1}#2}
\def\chainiterate@end!#1!#2{ #2}
%
\newcommand*{\chainiteratetwice}[1]
{\romannumeral-`0\chainiterate{\chainiterate{#1}}}
\newcommand*{\ChainCycle}{}
\newcommand*{\ChainCycleStart}{}
\newcommand*{\odef}[1]{\expandafter\def\expandafter#1\expandafter}
\newcommand*{\oodef}[1]{\expandafter\expandafter\expandafter
\def\expandafter\expandafter\expandafter
#1\expandafter\expandafter\expandafter }
\def\FindCycle@DefTest #1{%
\def\FindCycle@DoTest ##1,#1,##2##3?%
{\if!##2\expandafter 0\else\expandafter 1\fi }%
}%
\newcommand*{\FindCycle}[1]{%
\odef\FindCycle@X {#1}%
\let\FindCycle@Y\FindCycle@X
\loop
\oodef\FindCycle@X{\chainiterate{\FindCycle@X}}%
\oodef\FindCycle@Y{\chainiteratetwice{\FindCycle@Y}}%
\ifx\FindCycle@X\FindCycle@Y\else
\repeat
\odef\ChainCycle {\expandafter,\FindCycle@X}%
\loop
\oodef\FindCycle@Y{\chainiterate{\FindCycle@Y}}%
\ifx\FindCycle@Y\FindCycle@X\else
\oodef\ChainCycle {\expandafter\ChainCycle\expandafter,\FindCycle@Y}%
\repeat
\count@ \z@
\odef\FindCycle@X {#1}%
\loop
\expandafter\FindCycle@DefTest\expandafter{\FindCycle@X}%
% is this iterate in the cycle ?
\if0\expandafter\expandafter\expandafter\FindCycle@DoTest
\expandafter\ChainCycle\expandafter,\FindCycle@X,!?%
% no, it isn't
\oodef\FindCycle@X {\chainiterate{\FindCycle@X}}%
\advance\count@\@ne
\repeat
The first iterate of #1 which starts the period is obtained after
\the\count@{} iteration{\ifnum\count@>1 s\fi}. It is \FindCycle@X.\par
\count@\z@
\let\FindCycle@Y\FindCycle@X
Here is the period: \FindCycle@X
\loop
\advance\count@\@ne
\oodef\FindCycle@Y {\chainiterate{\FindCycle@Y}}%
\ifx\FindCycle@Y\FindCycle@X
\else
, \FindCycle@Y
\repeat
.\par Its length is \the\count@.\par
}
\makeatother
\begin{document}
\FindCycle {12}
\bigskip
\FindCycle {123}
\bigskip
\FindCycle {1234}
\bigskip
\FindCycle {12345}
\bigskip
\FindCycle {123456}
\bigskip
% SURPRISE !
\FindCycle {1234567}
\end{document}
答案3
和expl3
:
\documentclass{article}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\chain}{mm}
{% #1 is the starting number, #2 is the number of repetitions
\egreg_chain_add:nn { #1 } { #2 }
}
\tl_new:N \l_egreg_chain_tablebody_tl
\seq_new:N \l_egreg_chain_input_seq
\seq_new:N \l_egreg_chain_output_seq
\int_new:N \l_egreg_chain_length_int
\cs_new_protected:Npn \egreg_chain_add:nn #1 #2
{
% form the first input sequence
\seq_set_split:Nnn \l_egreg_chain_input_seq { } { #1 }
% the number of columns for the table
\int_set:Nn \l_egreg_chain_length_int { \seq_count:N \l_egreg_chain_input_seq }
% start building the table body
\tl_clear:N \l_egreg_chain_tablebody_tl
% first row with the input number
\tl_put_right:Nx \l_egreg_chain_tablebody_tl
{
\seq_use:Nn \l_egreg_chain_input_seq { & } \exp_not:N \\
}
% repeat as many times as requested
\prg_replicate:nn { #2 }
{
% clear the output sequence
\seq_clear:N \l_egreg_chain_output_seq
% build the output sequence
\int_step_inline:nnnn { 1 } { 1 } { \seq_count:N \l_egreg_chain_input_seq - 1 }
{
\seq_put_right:Nx \l_egreg_chain_output_seq
{
\int_to_arabic:n
{
\int_mod:nn
{
\seq_item:Nn \l_egreg_chain_input_seq { ##1 } +
\seq_item:Nn \l_egreg_chain_input_seq { ##1 + 1 }
}
{ 10 }
}
}
}
\seq_put_right:Nx \l_egreg_chain_output_seq
{
\int_to_arabic:n
{
\int_mod:nn
{
\seq_item:Nn \l_egreg_chain_input_seq { -1 } +
\seq_item:Nn \l_egreg_chain_input_seq { 1 }
}
{ 10 }
}
}
% fill the next row
\tl_put_right:Nx \l_egreg_chain_tablebody_tl
{
\seq_use:Nn \l_egreg_chain_output_seq { & } \exp_not:N \\
}
% the output sequence becomes the input sequence for the next row
\seq_set_eq:NN \l_egreg_chain_input_seq \l_egreg_chain_output_seq
}
\begin{tabular}{*{\l_egreg_chain_length_int}{c}}
% deliver the table body
\l_egreg_chain_tablebody_tl
\end{tabular}
}
\ExplSyntaxOff
\begin{document}
\chain{123456}{10}
\bigskip
\chain{42}{5}
\end{document}
该表使用两个序列逐步构建;在每个步骤中,输出序列成为下一步的输入序列。
答案4
我正在添加在 LuaTeX 中创建的代码片段和结果预览。
% lualatex mal-cells.tex
\documentclass[a4paper]{article}
\pagestyle{empty}
\usepackage{luacode}
\begin{document}
\begin{luacode*}
function malcompute() -- the core of computations
counter=0 -- number of columns
series={} -- actual values will be stored here
seriesdata=tex.toks[1] -- get data from TeX and parse them:
for entry in unicode.utf8.gmatch(seriesdata, "%d+") do
counter=counter+1 -- move to the column+1
series[counter]=entry -- save data to a Lua table
end -- for, entry
rows=tonumber(tex.toks[2]) -- how many lines is requested?
for row=1,rows do -- we need this number of rows and...
for column=1,#series do -- ... and columns
if column==1 then firstvalue=series[1] end -- repeat the computation from the beginning when you reach the last column
newvalue=(series[column]+(series[column+1] or firstvalue)) % 10 -- get two numbers above the actual one, modulus is a percent sign in Lua
tex.print(newvalue) -- print the result to TeX
series[column]=newvalue -- store a new value instead of an old one
end -- for, column
tex.print("\\par") -- break a line when there is a new row coming
end -- for, row
end -- function, malcompute
\end{luacode*}
\def\malcells#1#2{% pass arguments to Lua
\toks1{#1}% initial values
\toks2{#2}% number of rows
\directlua{malcompute()}% get us to the Lua world
} % End of the \malcells command.
% A small piece of code formatting the results at a TeX level
\ttfamily\Large
% An example as OP asked.
\malcells{1 2 3 4 5 6}{3}
\end{document}