如何在命令中拥有固定值

如何在命令中拥有固定值

我有一个命令,它的定义是随机给出的。每次我调用它时,它都会被重新定义,随机的。我希望它只在我需要时才被重新定义。

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}

相关内容