我有一个命令,它的定义是随机给出的。每次我调用它时,它都会被重新定义,随机的。我希望它只在我需要时才被重新定义。
MWE 如下。请注意,\ExplSyntaxOn
和之间的部分\ExplSyntaxOff
是从给定列表中获取随机元素所必需的。它定义了\selectNrandom
和\htguse
\name 命令中使用的从逗号分隔的列表中选择随机元素。
\documentclass[11pt, a4paper]{article}
\usepackage[italian]{babel}
\usepackage[utf8]{inputenc}
\usepackage{ifthen}
\usepackage{calc}
\usepackage{pgffor}
\usepackage{xparse}
\usepackage{lcg}
\input{random}
\newcommand{\name}{\selectNrandom{1}{Francesco, Alessandro, Mattia, Lorenzo, Leonardo, Andrea, Gabriele, Matteo, Tommaso, Riccardo, Davide, Giuseppe, Edoardo, Antonio, Federico, Giovanni, Marco, Diego, Samuele, Pietro, Christian, Nicolò, Luca, Simone, Filippo, Alessio, Gabriele, Michele, Emanuele, Jacopo}\htguse{1}}
% The following part, up to \ExplSyntaxOff, is needed to take random elements from a given list. It defines the \selectNrandom and \htguse commands, used in the \name command. I found it in https://tex.stackexchange.com/questions/86165/selecting-random-elements-from-a-comma-separated-list/86168#86168
\ExplSyntaxOn
\NewDocumentCommand{\htguse}{ m }
{
\use:c { htg_arg_#1: }
}
\NewDocumentCommand{\selectNrandom}{ m m m }
{
\htg_select_n_random:nnn { #1 } { #2 } { #3 }
}
\cs_new_protected:Npn \htg_select_n_random:nnn #1 #2 #3
{
\seq_clear:N \l_htg_used_seq
\int_set:Nn \l_htg_length_int { \clist_count:n { #2 } }
\int_compare:nTF { #1 > \l_htg_length_int }
{
\msg_error:nnxx { randomchoice } { too-many } { #1 } { \int_to_arabic:n { \l_htg_length_int } }
}
{
\int_step_inline:nnnn { 1 } { 1 } { #1 }
{
\htg_get_random:
\cs_set:cpx { htg_arg_##1: }
{ \clist_item:nn { #2 } { \l_htg_random_int } }
}
#3
}
}
\cs_new_protected:Npn \htg_get_random:
{
\setrannum { \l_htg_random_int } { 1 } { \l_htg_length_int }
\seq_if_in:NxTF \l_htg_used_seq { \int_to_arabic:n { \l_htg_random_int } }
{ \htg_get_random: }
{ \seq_put_right:Nx \l_htg_used_seq { \int_to_arabic:n { \l_htg_random_int } } }
}
\seq_new:N \l_htg_used_seq
\int_new:N \l_htg_length_int
\int_new:N \l_htg_random_int
\msg_new:nnnn { randomchoice } { too-many }
{ Too~ many~choices }
{ You~want~to~select~#1~elements,~but~you~have~only~#2 }
\ExplSyntaxOff
\begin{document}
\foreach \pagenum in {1,...,5}{
\name
\name
\name
\pagebreak
}
\end{document}
现在,此代码的工作是从该列表中随机取一个名称。每次都会取一个新的随机名称。假设我希望它仅在创建新页面时才取一个新名称 - 这样这 5 个页面中的每一页都会显示三次相同的名称,每个页面的名称都不同(除非随机函数给出完全相同的结果)。我该怎么做?
答案1
在纯 TeX 中,您可以使用\input random
. Define\preprandom
来更改结果并\result
打印随机选择的结果:
\input random
\newcount\rann
\newcount\tmpnum
\def\preprandom{\setrannum\rann{1}{30}}
\def\result{\ifcase\rann\or
Francesco\or Alessandro\or Mattia\or Lorenzo\or Leonardo\or
Andrea\or Gabriele\or Matteo\or Tommaso\or Riccardo\or Davide\or
Giuseppe\or Edoardo\or Antonio\or Federico\or Giovanni\or Marco\or
Diego\or Samuele\or Pietro\or Christian\or Nicolò\or Luca\or Simone\or
Filippo\or Alessio\or Gabriele\or Michele\or Emanuele\or Jacopo\fi
}
\tmpnum=0
\loop
\preprandom
\result\endgraf \result\endgraf \result\endgraf \medskip\hrule\medskip
\advance\tmpnum by1
\ifnum\tmpnum<5 \repeat
\bye
答案2
如何先将完整的名称列表预先存储在变量中\seq
,然后使用\seq_rand_item:N
它是一个“新”功能(于 2016/12/06 推出)并且是可扩展的,即它的扩展值可以存储到其他宏中,比如说\edef\namestored{\name}
\documentclass[11pt, a4paper]{article}
\usepackage[italian]{babel}
\usepackage[utf8]{inputenc}
\usepackage{pgffor}
\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \l_candidates_name_seq
\NewDocumentCommand{\StoreNames}{m}{%
\seq_set_from_clist:Nn \l_candidates_name_seq {#1}
}
\cs_new:Npn \selectNrandom #1 {%
\seq_rand_item:N \l_candidates_name_seq
}
\newcommand{\name}{\selectNrandom{1}}
\ExplSyntaxOff
\StoreNames{Francesco, Alessandro, Mattia, Lorenzo, Leonardo, Andrea, Gabriele, Matteo, Tommaso, Riccardo, Davide, Giuseppe, Edoardo, Antonio, Federico, Giovanni, Marco, Diego, Samuele, Pietro, Christian, Nicolò, Luca, Simone, Filippo, Alessio, Gabriele, Michele, Emanuele, Jacopo}
\begin{document}
\foreach \pagenum in {1,...,5}{
\edef\namestored{\name}
\namestored
\namestored
\namestored
\medskip
\hrule
\medskip
%\pagebreak
}
\end{document}
由于其随机性,运行的输出将会改变(除非随机种子是固定的)
存储\cs_new:Npx \namestored
:
\documentclass[11pt, a4paper]{article}
\usepackage[T1]{fontenc}
\usepackage[utf8]{inputenc}
\usepackage[italian]{babel}
\usepackage{pgffor}
\usepackage{xparse}
\ExplSyntaxOn
\seq_new:N \l_candidates_name_seq
\NewDocumentCommand{\StoreNames}{m}{%
\seq_set_from_clist:Nn \l_candidates_name_seq {#1}
}
\cs_new:Npn \selectNrandom #1 {%
\seq_rand_item:N \l_candidates_name_seq
}
\cs_new:Npn \namex {
\cs_set:Npx \namestored {\seq_rand_item:N \l_candidates_name_seq }
}
\newcommand{\name}{\selectNrandom{1}}
\ExplSyntaxOff
\StoreNames{Francesco, Alessandro, Mattia, Lorenzo, Leonardo, Andrea, Gabriele, Matteo, Tommaso, Riccardo, Davide, Giuseppe, Edoardo, Antonio, Federico, Giovanni, Marco, Diego, Samuele, Pietro, Christian, Nicolò, Luca, Simone, Filippo, Alessio, Gabriele, Michele, Emanuele, Jacopo}
\begin{document}
\foreach \pagenum in {1,...,5}{
\namex
\namestored
\namestored
\namestored
\medskip
\hrule
\medskip
}
\end{document}