3

I need a list in which the numbers 1, 2, ..., 52 are randomly arranged - but without repetitions!
Is there a simple implementation for this? How can I do that?

In the following MWE I will use the numbers 1,2,...,11 (not 52) to have a better look onto the problem:

enter image description here

\documentclass[a4paper]{article}
\usepackage{tikz}

\begin{document}
\foreach \No in {1,...,11}{%%
\noindent No\No: \pgfmathparse{random(1,11)}\pgfmathresult \\ % Test
}%%
\end{document}
7
  • You rounded random numbers. Consequently difference between them quickly vanish ... Compare width \documentclass[a4paper]{article} \usepackage{tikz} \begin{document} \foreach \No in {1,...,11}{\noindent No\No: \pgfmathparse{rnd}\pgfmathresult\\}} \end{document}.
    – Zarko
    Jun 6 at 15:26
  • Import from R. sample(1:52,52,replace=F)
    – MS-SPO
    Jun 6 at 15:32
  • @Rmano This looks interesting, but I would have to type \pgfmathdeclarerandomlist{mynum}{{1}{2}{3}{4} ....... {52}}
    – cis
    Jun 6 at 16:53
  • 1
    But I think, this solution is the thing: tex.stackexchange.com/a/346285/46023
    – cis
    Jun 6 at 17:12

2 Answers 2

3

I need a list in which the numbers 1, 2, ..., 52 are randomly arranged - but without repetitions!

You need a shuffle. One implemented shuffle macro is the \seq_shuffle:N from expl3. Thus this answer provides a non-pgffor solution:

\documentclass{article}
\ExplSyntaxOn

\seq_clear:N \l_tmpa_seq
\clist_map_inline:nn { $\clubsuit$, $\diamondsuit$, $\heartsuit$, $\spadesuit$ }
  {
    \int_step_inline:nnn {1} {14}
      { \seq_put_right:Nn \l_tmpa_seq {#1##1} }
  }

\seq_new:N \c_cards_seq
\seq_set_eq:NN \c_cards_seq \l_tmpa_seq

\tl_new:N \l_card_tl
\tl_new:N \l_card_count_tl

\cs_new_protected:Nn \cards_new:N
  {
    \seq_new:N #1
    \seq_set_eq:NN #1 \c_cards_seq
  }

\cs_new_protected:Nn \cards_shuffle:N
  { \seq_shuffle:N #1 }

\cs_new_protected:Nn \cards_take_n:Nnn
  {
    \int_step_variable:nnNn {1} {#2} \l_card_count_tl
      {
        \seq_pop_left:NN #1 \l_card_tl
        #3
      }
  }
\ExplSyntaxOff

\begin{document}
\parindent=0pt

\ExplSyntaxOn
\cards_new:N \l_cards_tmpa_seq
\cards_shuffle:N \l_cards_tmpa_seq
\cards_take_n:Nnn \l_cards_tmpa_seq {12}
  { No\l_card_count_tl. ~ \l_card_tl \\ }
\ExplSyntaxOff
\end{document}

One possible output

enter image description here

Update Partial shuffle

This one is highly similar to John Kormylo's answer https://tex.stackexchange.com/a/346285, only a partial shuffle is invoked.

\documentclass{article}
\usepackage{pgffor}
\usepackage{etoolbox}

% init n items
\newcommand\initCards[1]{%
  \foreach \i in {1,...,#1} {%
    \csxdef{shuffle@\i}{\i}%
  }%
}

% shuffle and use the first m items, m <= n
\newcommand\getRandomN[2]{% #1 = m, #2 = n
  \foreach \i in {1,...,#1} {%                  % for i in 1..12
    \pgfmathparse{random(\i,#2)}%               %     for j in random(i, 12)
    \letcs\tempa{shuffle@\i}%                   %     exchange a[i] and a[j]
    \global\csletcs{shuffle@\i}{shuffle@\pgfmathresult}%
    \global\cslet{shuffle@\pgfmathresult}\tempa
    No\i. \csuse{shuffle@\i}\\                  %     use a[i]
  }
}

\begin{document}
\parindent=0pt

\pgfmathsetseed{125}

\initCards{12}
\getRandomN{12}{12}
\end{document}

enter image description here

2

Here's a direct, manual way to do it. Trying to create a series WITHOUT repetition from a repeating series is a torment. Don't try it, unless you have time: R is made for this.

What you need to use my code:

  • copy&paste

What you need to create other samples:

  • install R on your system, unless you have
  • run e.g. R as commandline/terminal (Rterm)
  • n<-sample(1:52,52,replace=F); paste(n,collapse=",")
  • copy from there: [1] "48,20,50,26,1,6,30,17,22, ..."

Decoded:

  • n<-sample(1:52,52,replace=F) creates 52 samples from range 1:52 WITHOUT repetition, storing it in n (as list)
  • paste(n,collapse=",") inserts , inbetween, as that's what tikz likes (1,2,3 instead of 1 2 3)

To run within your Latex environment ...

You'll need packages iexec and shellesc . See their documentation.

See also tag r on this site.


result

What the code does:

  • regular \foreach command, augmented by a counting variable [count=\i] (index within the list)
  • drawing some horizontal strokes \draw (\i,\r) -- +(2,0);
  • kindly recognize the uniform distribution of the sampled numbers
\documentclass[10pt,border=1cm,tikz]{standalone}
\usepackage{tikz}

\begin{document}
 \begin{tikzpicture}
    \foreach \r [count=\i] in { 48,20,50,26,1,6,30,17,22,8,42,35,45,21,39,44,49,7,31,40,19,47,3,18,5,12,52,38,13,41,15,9,16,29,27,43,37,23,4,51,32,36,25,28,34,10,24,14,46,33,11,2}
     \draw (\i,\r) -- +(2,0);
 \end{tikzpicture}
\end{document}

From Rterm:
> n<-sample(1:52,52,replace=F); paste(n,collapse=",")
[1] "48,20,50,26,1,6,30,17,22,8,42,35,45,21,39,44,49,7,31,40,19,47,3,18,5,12,52,38,13,41,15,9,16,29,27,43,37,23,4,51,32,36,25,28,34,10,24,14,46,33,11,2"

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .