下面的 LaTeX 文件按自然顺序输出数字 1、2...、20
\documentclass[12pt]{article}
\usepackage{multido}
\begin{document}
\multido{\i=1+1}{20}{\i\ }
\end{document}
输出为
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
这是我的问题:有没有一种简单的方法可以输出相同的数字,但随机(并且没有重复,每个数字应该出现一次)?当然,文档的每个组成都应该产生随机输出。
我的问题不完全是这样的:我有 20 个文件,分别名为file1
、file2
、... file20
,我想随机输入它们(20 个文件中的每一个都必须在流程的某一时刻输入,并且不应输入任何文件两次)。但回答上述更简单的问题对我来说已经很完美了。
答案1
我们可以调整我的解决方案用 LaTeX 编写较长的程序代码是否方便?生成一个排列,然后使用该序列输入具有公共前缀的文件:
\documentclass{article}
\usepackage{amsmath,xparse}
\input{random}
\ExplSyntaxOn
\cs_new_eq:NN \knuthshuffle_get_random:Nnn \setrannum
\tl_new:N \l_knuthshuffle_tempa_tl
\tl_new:N \l_knuthshuffle_tempb_tl
\int_new:N \l_knuthshuffle_random_int
\seq_new:N \l_knuthshuffle_permutation_seq
\NewDocumentCommand{\inputpermutation}{mm}
{% #1 is the number of files, #2 is the common prefix
\knuthshuffle_generate:n { #1 }
\ferrard_input:n { #2 }
}
\cs_new_protected:Nn \knuthshuffle_generate:n
{
\int_step_inline:nnnn { 1 } { 1 } { #1 }
{
\tl_clear_new:c { l_knuthshuffle_##1_element_tl }
\tl_set:cn { l_knuthshuffle_##1_element_tl } { ##1 }
}
\prop_set_eq:NN \l_knuthshuffle_newperm_prop \g_knuthshuffle_identity_prop
\int_step_inline:nnnn { #1 } { -1 } { 2 }
{
\knuthshuffle_get_random:Nnn \l_knuthshuffle_random_int { 1 } { ##1 }
\tl_set_eq:Nc \l_knuthshuffle_tempa_tl
{ l_knuthshuffle_##1_element_tl }
\tl_set_eq:Nc \l_knuthshuffle_tempb_tl
{ l_knuthshuffle_ \int_to_arabic:n \l_knuthshuffle_random_int _element_tl }
\tl_set_eq:cN { l_knuthshuffle_##1_element_tl }
\l_knuthshuffle_tempb_tl
\tl_set_eq:cN { l_knuthshuffle_ \int_to_arabic:n \l_knuthshuffle_random_int _element_tl }
\l_knuthshuffle_tempa_tl
}
\seq_clear:N \l_knuthshuffle_permutation_seq
\int_step_inline:nnnn { 1 } { 1 } { #1 }
{
\seq_put_right:Nv \l_knuthshuffle_permutation_seq { l_knuthshuffle_##1_element_tl }
}
% \seq_show:N \l_knuthshuffle_permutation_seq % for debugging
}
\cs_new_protected:Npn \ferrard_input:n #1
{
\seq_map_inline:Nn \l_knuthshuffle_permutation_seq
{
\input{#1##1}\par
}
}
\ExplSyntaxOff
\begin{document}
\inputpermutation{9}{file}
\end{document}
我写了九个文件,每个文件的名称都file<i>.tex
包含文本This is <i>
(<i>
从 1 到 9)。当然,您可以拥有任意数量的文件;file
这是传递给宏的通用前缀。
这是应用程序的结果
答案2
这是一个expl3
解决方案,使用clist
(逗号分隔列表)数据类型:
\documentclass[12pt]{article}
\usepackage{expl3}
%create 20 files containing some text
\ExplSyntaxOn
\iow_new:N\forinput
\int_step_inline:nnnn{1}{1}{20}{
\iow_open:Nn\forinput{file#1.tex}
\iow_now:Nn\forinput{This~is~file~#1.}
\iow_close:N\forinput
}
\ExplSyntaxOff
\begin{document}
\ExplSyntaxOn
%fill clist variable with 20 file names file1.tex ... file20.tex
\clist_clear_new:N\g_files_clist
\int_step_inline:nnnn{1}{1}{20}{
\clist_put_right:Nx\g_files_clist{file#1.tex}
}
%print file names and input them in random order
\bool_until_do:nn{\clist_if_empty_p:N\g_files_clist}{
%choose random file from clist
\tl_set:Nx\l_current_tl{\clist_item:Nn\g_files_clist{
\int_eval:n{1+\pdfuniformdeviate\clist_count:N\g_files_clist}}}
%move current to front and remove it from clist
\clist_put_left:Nx\g_files_clist{\l_current_tl}
\clist_remove_duplicates:N\g_files_clist\clist_pop:NN\g_files_clist\l_current_tl
%print current file name
\l_current_tl :~
%and input it
{\catcode`\ =10\input{\l_current_tl}}\par
}
\ExplSyntaxOff
\end{document}
在expl3
环境中,读取文件时必须将空格字符的 catcode 设置为其标准值 10。否则,从输入中读取的空格将被忽略。
答案3
谢谢 AlexG。您的解决方案可以打印文件名,但不能输入文件名。
我找到了自己的解决方案,它依赖于包“python”。
工作原理如下:
1) 我创建一个文本文件(名为“temp.tex”)
2) 我将范围从 1 打乱到 20(包括 1 和 20)
3) 对于这个随机列表中的每个 i,我在“temp.tex”中写入“\input{file#i}”
4) 我关闭文件“temp.tex”
5) 我输入文件“temp.tex”
\documentclass{article}
\usepackage{python}
\begin{document}
\begin{python}
temp = open('temp.tex','w')
from random import shuffle
numbers = range(1,21)
shuffle(numbers)
for i in numbers:
temp.write('\input{file'+str(i)+'}\n')
temp.close()
\end{python}
\input{temp.tex}
\end{document}