如何随机输入指定范围的文件?

如何随机输入指定范围的文件?

下面的 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 个文件,分别名为file1file2、... 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}

相关内容