我有一份名单,你说:
\newcommand{\names}{Fred, Barry, Joe, Jack, Zach}
我只是想在我的文档中以随机顺序显示列表几次。
就像是:
Barry, Zach, Joe, Jack, Fred
一开始
Joe, Zach, Barry, Fred, Jack
靠近文档的中间。
我发现最接近的简单解决方案是使用包
\usepackage{probsoln}
\PSNrandseed{\time}
并在文档中调用:
\doforrandN{5}{\who}{\studentsnames}{
\who
}
但问题是,每次编译只创建一次随机化的种子。因此,在我的文档中两次调用随机列表将得到两个相同的列表。还有其他简单的方法吗?
答案1
您可以使用 L3 及其\seq_shuffle:N
功能。下面将其包装在一些方便的宏中:
\documentclass{article}
\ExplSyntaxOn
\NewDocumentCommand \setNameList { m m }
{
\seq_clear_new:c { l__andrew_namelist_#1_seq }
\seq_set_from_clist:cn { l__andrew_namelist_#1_seq } {#2}
}
\msg_new:nnn { andrew } { unknown-list } { Unknown~ list~ #1 }
\NewDocumentCommand \useNameListShuffled { m O{,~} }
{
\seq_if_exist:cTF { l__andrew_namelist_#1_seq }
{
\group_begin:
\seq_shuffle:c { l__andrew_namelist_#1_seq }
\seq_use:cn { l__andrew_namelist_#1_seq } {#2}
\group_end:
}
{ \msg_error:nnn { andrew } { unknown-list } {#1} }
}
\ExplSyntaxOff
\setNameList{names}{Fred, Barry, Joe, Jack, Zach}
\begin{document}
\useNameListShuffled{names}
\useNameListShuffled{names}[ and ]
\end{document}
答案2
这是(潜在的)糟糕的代码,但它能起作用(可能更多是出于偶然而非设计)。
\documentclass{article}
\usepackage{expl3}
\begin{document}
\ExplSyntaxOn
\clist_new:N \l__andrew_students
\clist_set:Nn \l__andrew_students{Zack, Barry, Fred, Jack, Joe}
\cs_new:Nn \print_students: {\clist_use:Nnnn \l__andrew_students {~and~} {,~} {,~ and~} }
\cs_new:Nn \randomise_students: {
\clist_sort:Nn \l__andrew_students {
\fp_compare:nNnTF {rand()} > {0.5}
{ \sort_return_swapped: }
{ \sort_return_same: }
}
}
\cs_new_eq:NN \randomisestudents\randomise_students:
\cs_new_eq:NN \printstudents\print_students:
\ExplSyntaxOff
\printstudents
\randomisestudents
\printstudents
\randomisestudents
\printstudents
\end{document}
设置初始列表可能需要另一个命令,这取决于您需要更改列表的次数。
编辑:我现在有更多的时间,所以做一点解释。
我选择了clist
而不是seq
(像@Skillmon 的答案),但它们的行为(至少从用户的角度来看)非常相似(在我测试的版本上)。我确实查看了interface3.pdf
“shuffle”,但没有找到。我怀疑这是由于安装时间太长造成的 - 它是我的(不是全新的)Linux 包管理器提供的(我认为它是 TeX Live 2018,但我现在不在那台电脑上)。但我可以看到(在更现代的 TeX Live 上)seq
有 shuffle,但clist
没有。
我对风格做了一些修改,但我认为它仍然不是很棒。
代码解释:
\clist_set:Nn
将命名变量设置为提供的逗号分隔列表- 排序算法根据随机浮点数(从 0 到 1)是否大于 .5(而不是列表的固有特征)来决定交换列表的两个成员
- 将
\clist_use:Nnnn
在项目之间打印逗号(最后两个除外,它们将是一个逗号和单词“and”) - 此版本将保持顺序,除非调用,这与其他答案略有不同。这可以通过在方法中
\randomisestudents
调用来更改(在之前或之后)\randomise_students:
\print_students:
clist_use
正如@DavidCarlisle提到的那样,如果排序算法假设然后,rand > 0.5
则在排序中使用可能会导致排序永不终止。 因此,除了一次性项目外,我不会将此方法或代码用于任何其他项目,在一次性项目中,如果它看起来不会终止,我可以停止运行并重新启动。a>b
b>c
a>c
因为它在测试期间发挥了作用,所以我没有过多考虑潜在的陷阱。