Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I try to create a table with random entries... By browsing the tag, I found some help on random number generators and I tried using lcg.

Surprisingly I seem to create the same random number over and over again, whatever I choose as seed... does anyone have a clue?

Code for a 5x5 table:

\chgrand[first=0, last=4, counter=kids]
\begin{tabular}{rrrrr}
\forloop{row_number}{1}{\value{row_number} < 6}{%%
    \forloop{col_number}{1}{\value{col_number} < 5}{%%%
       \rand\arabic{kids} & 
    }%%%
    \rand\arabic{kids}
    \\ }%%
\end{tabular}

creates:

4 4 4 4 4
4 4 4 4 4
4 4 4 4 4
4 4 4 4 4
4 4 4 4 4

doesn't look random to me...

I tried changing \rand to \rand\rand and all entries changed to '3'. So I presume every time I call \rand it starts back from the same seed, but I don't see why, as the seed is declared before the \forloop. Or isn't it?

share|improve this question
10  
This seems appropriate, while looking for an answer dilbert.com/dyn/str_strip/000000000/00000000/0000000/000000/… –  egreg Oct 24 '12 at 21:22
    
Probably your \forloop puts a group around the body. Package lcg uses local assignments, thus the internal state is reset after the group. –  Heiko Oberdiek Oct 24 '12 at 21:28
    
i could add something like \chgrand[seed=\value{rand}] inside the \forloop, but that hardly seems a workaround to me (i guess that would lead to the same re-occuring sequence over and over again) –  long tom Oct 24 '12 at 21:28
    
@HeikoOberdiek: so i'd have to change to \foreach? or to another random number generator? –  long tom Oct 24 '12 at 21:30
    
\foreach of pgf also puts a group around the loop body. –  Heiko Oberdiek Oct 24 '12 at 21:32

2 Answers 2

up vote 10 down vote accepted

The problem is that you're doing that inside a table cell and TeX doesn't like it very much. It's better to build up the token list before doing the table:

\documentclass{article}
\usepackage{lcg,forloop}
\newtoks\dierckxtoks
\newcounter{row_number}\newcounter{col_number}

\begin{document}

\chgrand[first=0, last=4, counter=kids]
\dierckxtoks={}

\forloop{row_number}{1}{\value{row_number} < 6}{% 
  \forloop{col_number}{1}{\value{col_number} < 5}{%  
     \rand
     \edef\x{\the\dierckxtoks\arabic{kids} &}
     \dierckxtoks\expandafter{\x}%
  }%  
  \rand
  \edef\x{\the\dierckxtoks\arabic{kids} \noexpand\\}
  \dierckxtoks\expandafter{\x}%
}  

\begin{tabular}{rrrrr}
\the\dierckxtoks
\end{tabular}

\end{document}

enter image description here

On the other hand, as shown in my first comment, also 444444444 can be a sequence of random numbers. :-)


The mandatory expl3 solution.

\documentclass{article}
\usepackage{lcg}
\newcounter{randnumb}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\randomtabular}{ O{randnumb} m m m m }
% #1 = counter name (optional default randnumb)
% #2 = lowest value
% #3 = highest value
% #4 = rows
% #5 = columns
 {
  \chgrand[first=#2, last=#3, counter=#1]
  \dierckx_random_tabular:nnn {#1}{#4}{#5}
 }
\tl_new:N \l_dierckx_tabular_tl
\cs_new_protected:Npn \dierckx_random_tabular:nnn #1 #2 #3
 {
  \tl_clear:N \l_dierckx_tabular_tl
  \prg_replicate:nn { #2 }
   {
    \prg_replicate:nn { #3 - 1 }
     {
      \rand
      \tl_put_right:Nx \l_dierckx_tabular_tl { \arabic{#1} & }
     }
    \rand
    \tl_put_right:Nx \l_dierckx_tabular_tl { \arabic{#1} }
    \tl_put_right:Nn \l_dierckx_tabular_tl { \\ }
   }
  \begin{tabular}{*{#3}{r}}
  \l_dierckx_tabular_tl
  \end{tabular}
 }
\ExplSyntaxOff

\begin{document}

\randomtabular{0}{9}{6}{4}

\randomtabular[kids]{0}{4}{5}{5}

\end{document}

enter image description here


A different solution using the random number facility of pgf:

\documentclass{article}
\usepackage{pgf}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\randomtabular}{ m m m m }
% #1 = lowest value
% #2 = highest value
% #3 = rows
% #4 = columns
 {
  \dierckx_random_tabular:nnnn {#1}{#2}{#3}{#4}
 }
\tl_new:N \l__dierckx_tabular_tl
\int_new:N \l__dierckx_random_number_int
\cs_new_protected:Npn \dierckx_random_tabular:nnnn #1 #2 #3 #4
 {
  \tl_clear:N \l_dierckx_tabular_tl
  \prg_replicate:nn { #3 }
   {
    \prg_replicate:nn { #4 - 1 }
     {
      \dierckx_get_rand:nn { #1 } { #2 }
      \tl_put_right:Nx \l_dierckx_tabular_tl { \int_to_arabic:n { \l__dierckx_random_number_int } & }
     }
    \dierckx_get_rand:nn { #1 } { #2 }
    \tl_put_right:Nx \l_dierckx_tabular_tl { \int_to_arabic:n { \l__dierckx_random_number_int } }
    \tl_put_right:Nn \l_dierckx_tabular_tl { \\ }
   }
  \begin{tabular}{*{#3}{r}}
  \l_dierckx_tabular_tl
  \end{tabular}
 }
\cs_new_protected:Npn \dierckx_get_rand:nn #1 #2
 {
  \pgfmathrandominteger{ \l__dierckx_random_number_int } { #1 } { #2 }
 }
\ExplSyntaxOff

\begin{document}

\randomtabular{0}{9}{6}{4}

\bigskip

\randomtabular{0}{4}{5}{5}

\end{document}

There is no optional argument any more, but it doesn't seem to be really necessary.


A variant of the first expl3 solution that pads the number with zeros to have the same length as the highest possible chosen number.

\documentclass{article}
\usepackage{lcg}
\newcounter{randnumb}
\usepackage{xparse}
\ExplSyntaxOn
\NewDocumentCommand{\randomtabular}{ O{randnumb} m m m m }
% #1 = counter name (optional default randnumb)
% #2 = lowest value
% #3 = highest value
% #4 = rows
% #5 = columns
 {
  \int_set:Nn \l_dierckx_padto_int { \tl_count:n { #3 } }
  \chgrand[first=#2, last=#3, counter=#1]
  \dierckx_random_tabular:nnn {#1}{#4}{#5}
 }
\tl_new:N \l_dierckx_tabular_tl
\tl_new:N \l_dierckx_temp_tl
\int_new:N \l_dierckx_padto_int

\cs_new_protected:Npn \__dierckx_padnumber:nn #1 #2
 {
  \tl_set:Nx \l_dierckx_temp_tl { \arabic{#1} }
  \tl_set:Nx \l_dierckx_temp_tl
   {
    \prg_replicate:nn { \l_dierckx_padto_int - \tl_count:N \l_dierckx_temp_tl } { 0 }
    \l_dierckx_temp_tl
   }
  \tl_put_right:Nx \l_dierckx_tabular_tl { \l_dierckx_temp_tl #2 }
 }

\cs_new_protected:Npn \dierckx_random_tabular:nnn #1 #2 #3
 {
  \tl_clear:N \l_dierckx_tabular_tl
  \prg_replicate:nn { #2 }
   {
    \prg_replicate:nn { #3 - 1 }
     {
      \rand
      \__dierckx_padnumber:nn { #1 } { & }
     }
    \rand
    \__dierckx_padnumber:nn { #1 } { }
    \tl_put_right:Nn \l_dierckx_tabular_tl { \\ }
   }
  \begin{tabular}{*{#3}{r}}
  \l_dierckx_tabular_tl
  \end{tabular}
 }
\ExplSyntaxOff

\begin{document}

\randomtabular{0}{100000}{6}{4}

\end{document}

enter image description here

share|improve this answer
    
I do accept 4444...4 to be a possible random sequence... but... with a 2^31 space for seed the odds to get this sequence with a random seed are about 0.3E-8. And i tried different seeds... besides, as \rand\rand changed the complete table, one can be pretty sure something was wrong. But I'm glad someone pointed me on what exactly was wrong... –  long tom Oct 25 '12 at 8:34
    
i dropped the second part of code in a .sty file. so i'm able to reuse them from now on. –  long tom Oct 25 '12 at 9:18
    
If you choose the max number as, say 100 000, how can you get the random numbers to print zeros for numbers like 00257 and 03498? –  azetina Apr 20 at 19:40
    
@azetina There should be a question about padding a number with zeros. –  egreg Apr 20 at 19:41
    
@egreg Let me search and see what I can find about padding with zeros. I was about to ask about how to create a random number table for a statistics class I am teaching and I stumbled upon your answer. Am amazed as to how you achieved it. I am still a little puzzled as to some parts of the expl3 coding but I will look into it before I make further comments. Thanks :) –  azetina Apr 20 at 19:44

I made a quick tikz solution. You may use \pgfmathsetseed{} for repeatable results.

\documentclass{article}

\usepackage{tikz}

\begin{document}
\begin{tikzpicture}
    \foreach \x in {1,...,5}{
        \foreach \y in {1,...,5}{
        \pgfmathrandominteger{\a}{0}{4}
            \node at (\x/2,\y/2){\a};
        }
    }
\end{tikzpicture}


\end{document}

result:

screenshot

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.