3

The LaTeX file below outputs the numbers 1,2...,20, in natural order

\documentclass[12pt]{article}

\usepackage{multido}

\begin{document}

\multido{\i=1+1}{20}{\i\ }

\end{document}

The output is

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20

This is my question: Is there a simple way to output the same numbers, but randomly (and without repetitions, each of the numbers should appear once)? Of course each composition of the document should produce random outputs.

My problem is not exactly that one: I have 20 files named file1, file2, ..., file20, and I would like to input them randomly (each of the 20 files must be input at one moment of the process, and no file should be input twice). But answering the simpler question above would be perfect for me.

jm.ferrard
  • 213
  • 1
  • 7

3 Answers3

2

Here is an expl3 solution, using the clist (comma separated list) data type:

\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}

In an expl3 environment, the catcode of the space character must be set to its standard value of 10 when reading a file. Otherwise spaces read from the input are ignored.

AlexG
  • 54,894
2

We can adapt my solution to Is it a convenient way to write longer program codes in LaTeX? to generate a permutation and then use the sequence for inputting files with a common prefix:

\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}

I have written nine files, named file<i>.tex containing the text This is <i> (for <i> from 1 to 9). Of course you can have as many files as you want; file is the common prefix to be passed to the macro.

Here's a result of the application

enter image description here

egreg
  • 1,121,712
  • OK it works. But it's definitily less readable than my python solution. I have the same effect as you with the code below.
    \documentclass{article}  
    
    \usepackage{python}  
    
    \begin{document} 
    
    \begin{python}  
    
    temp = open('temp.tex','w')  
    
    from random import shuffle  
    
    numbers = range(1,8)  
    
    shuffle(numbers)  
    for i in numbers:  
        temp.write('\input{file'+str(i)+'}')  
    temp.close()  
    \end{python}  
    

    \input{temp.tex}
    \end{document}

    – jm.ferrard Mar 03 '15 at 05:21
  • @jm.ferrard The largest part of the code is implementing the shuffle. Which doesn't require external programs. – egreg Mar 03 '15 at 08:39
1

Thank you AlexG. Your solution works for printing filenames, but not for inputing them.

I found my own solution, which rely on the package"python".

This is how it works:

1) I create a text file (name 'temp.tex')
2) I shuffle the range from 1 to 20 (both included)
3) for each i in this randomized list, I write "\input{file#i}" in 'temp.tex'
4) I close the file 'temp.tex'
5) I input the file '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}
jm.ferrard
  • 213
  • 1
  • 7
  • I had no problem with \input-ing files. Of course, all files must exist. See my updated answer. – AlexG Mar 03 '15 at 09:13
  • Hm, I get No pages of output. although python is installed and I run pdflatex -shell-escape on the file. (TeXLive-2014). A pure LaTeX solution seems to be preferable to me. – AlexG Mar 03 '15 at 09:22
  • Running python on the generated py-file directly gives an error: IndentationError: unexpected indent. – AlexG Mar 03 '15 at 09:32