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}

cis
  • 8,073
  • 1
  • 16
  • 45
  • 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 06 '23 at 15:26
  • Import from R. sample(1:52,52,replace=F) – MS-SPO Jun 06 '23 at 15:32
  • https://tex.stackexchange.com/questions/346771/print-random-list-pgfmathdeclarerandomlist-in-sequential-order ? – Rmano Jun 06 '23 at 15:43
  • @Rmano This looks interesting, but I would have to type \pgfmathdeclarerandomlist{mynum}{{1}{2}{3}{4} ....... {52}} – cis Jun 06 '23 at 16:53
  • 1
    But I think, this solution is the thing: https://tex.stackexchange.com/a/346285/46023 – cis Jun 06 '23 at 17:12
  • R is made for this, see my answer below: https://tex.stackexchange.com/a/687878/245790 – MS-SPO Jun 06 '23 at 17:18
  • There are many related Q&As about this: Q113987 – Qrrbrbirlbel Jun 06 '23 at 18:01

2 Answers2

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

muzimuzhi Z
  • 26,474
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"

MS-SPO
  • 11,519