TikZ / foreach:创建一个随机排列的数字列表,不重复

TikZ / foreach:创建一个随机排列的数字列表,不重复

我需要一个列表,其中数字 1, 2, ..., 52 是随机排列- 但无重复
有一个简单的实现方法吗?我该怎么做?

在下面的 MWE 中,我将使用数字 1,2,...,11(而不是 52)来更好地观察问题:

在此处输入图片描述

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

\begin{document}
\foreach \No in {1,...,11}{%%
\noindent No\No: \pgfmathparse{random(1,11)}\pgfmathresult \\ % Test
}%%
\end{document}

答案1

我需要一个列表,其中数字 1、2、...、52 随机排列 - 但不重复!

您需要进行随机播放。一个已实现的随机播放宏是\seq_shuffle:Nfrom expl3。因此,此答案提供了一个非pgffor解决方案:

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

一种可能的输出

在此处输入图片描述

更新部分改组

这与 John Kormylo 的答案非常相似https://tex.stackexchange.com/a/346285,仅调用部分洗牌。

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

在此处输入图片描述

答案2

这是直接、手动的方法。尝试从重复系列中创建不带重复的系列是一种折磨。除非你有时间,否则不要尝试:R 就是为此而生的。

使用我的代码需要:

  • 复制粘贴

创建其他示例所需的内容:

  • 在你的系统上安装 R,除非你已经
  • 例如以命令行/终端 (Rterm) 形式运行 R
  • n<-sample(1:52,52,replace=F); paste(n,collapse=",")
  • 从那里复制:[1] "48,20,50,26,1,6,30,17,22, ..."

解码:

  • n<-sample(1:52,52,replace=F)从范围 1:52 创建 52 个不重复的样本,并将其存储在n(作为列表)中
  • paste(n,collapse=",")插入,在中间,因为这是 tikz 喜欢的(1,2,3而不是1 2 3

在你的 Latex 环境中运行...

您将需要软件包iexecshellesc。请参阅其文档。

也可以看看标签 r在这个网站上。


结果

代码的作用:

  • 常规\foreach命令,通过计数变量[count=\i](列表内的索引)进行增强
  • 画一些水平笔画\draw (\i,\r) -- +(2,0);
  • 请注意样本数量的均匀分布
\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"

相关内容