我经常需要在 ConTeXt 的文档中放置随机元素。例如,我在格式信函中添加了一些随机语言差异。
在每个实例中,都可以选择要显示的项目:
Print
a
Or
b
Or
c
Done
在某些情况下,我需要嵌套随机性:
Print
a
Or
Print
b
Or
c
Done
Or
d
Done
我创建了此代码来实现我需要的功能,但是语法效率不太高:
\starttext
\define[2]\loadrandom{%
\getrandomnumber \randomnumber {#1} {#2}%
}
\loadrandom{1}{10}%
%
\ifnum\randomnumber=1%
This will print the first item.
\fi%
%
\ifnum\randomnumber=2%
This will print the second item.
\fi%
%
\ifnum\randomnumber=3%
This will print the third item.
\fi%
%
\ifnum\randomnumber=4%
This will print the fourth item.
\fi%
%
\ifnum\randomnumber=5%
This will print the fifth item.
\fi%
%
\ifnum\randomnumber=6%
This will print the sixth item.
\fi%
%
\ifnum\randomnumber=7%
This will print the seventh item.
\fi%
%
\ifnum\randomnumber=8%
This will print the eigth item.
\fi%
%
\ifnum\randomnumber=9%
This will print the ninth item.
\fi%
%
\ifnum\randomnumber=10%
This will print the tenth item.
\fi%
\stoptext
有什么方法可以改进此代码,以便更容易快速地在页面中放置随机文本?
答案1
也许你需要这个。我的示例包括嵌套随机打印,如果第一个随机数等于 2。
\getrandomnumber \randomnumber {1} {10}
\ifcase\randomnumber \or
print a
\or
\getrandomnumber \randomnumber {1} {2}
\ifcase\randomnumber \or
print ba
\or
print bb
\fi
\or
print c
\or
print d
\or
print e
\or
print f
\or
print g
\or
print h
\or
print i
\or
print j
\fi
或者你可以定义一个宏\randomtext
:
\newcount\tmpnum
\def\randomtext#1{\def\tmpbuf{}\tmpnum=0\randomtextA#1;;}
\def\randomtextA#1;{\if;#1;\getrandomnumber\randomnumber{1}{\tmpnum}%
\expandafter\ifcase\expandafter\randomnumber\tmpbuf\fi
\else \expandafter\def\expandafter\tmpbuf\expandafter{\tmpbuf\or#1}%
\advance\tmpnum by1
\expandafter\randomtextA
\fi
}
并使用它:
\randomtext{a;b;c;d;e;f}
or nested:
\randomtext{a;\randomtext{ba;bb};c;d;e}
抱歉,我没有测试它,因为我不使用 ConTeXt。但我希望它能工作...因为 ConTeXt 是基于 TeX 的。
编辑:因为 ConTeXt 使用伪随机生成器,所以您需要调用\randomtext
多次才能看到效果:
\newcount\tmpnum
\def\randomtext#1{\def\tmpbuf{}\tmpnum=0\randomtextA#1;;}
\def\randomtextA#1;{\if;#1;\getrandomnumber\randomnumber{1}{\tmpnum}%
\expandafter\ifcase\expandafter\randomnumber\tmpbuf\fi
\else \expandafter\def\expandafter\tmpbuf\expandafter{\tmpbuf\or#1}%
\advance\tmpnum by1
\expandafter\randomtextA
\fi
}
\starttext
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\randomtext{a;\randomtext{(ba);(bb)};c;d;e}
\stoptext
答案2
设置文本的随机值的方法有很多种,第一种是低级\ifacse
宏。
\define\RandomText
{\getrandomnumber\randomnumber{1}{4}%
\ifcase\randomnumber
% 0
\or
First item.% 1
\or
Second item.% 2
\or
Third item.% 3
\else
Another item.% 4+
\fi}
\starttext
\dorecurse{3}{\RandomText\par}
\stoptext
与此等效的 ConTeXt 是\processaction
命令。该命令的第一个参数采用应在列表中搜索的参数,第二个参数采用由带有 的文本分隔的值=>
。您还可以设置当搜索的值不在带有键的列表中时应使用的文本unknown
。
\define\RandomText
{\getrandomnumber\randomnumber{1}{4}%
\processaction
[\randomnumber]
[ 1=>First item.,
2=>Second item.,
3=>Third item.,
unknown=>Another item.]}
\starttext
\dorecurse{3}{\RandomText\par}
\stoptext
当您只想显示文本时,我建议使用另一种方法,这样更容易编写文本。有两种可能的方法非常相似,第一种使用环境setups
(我使用它是rawsetups
因为它保留了输入中每行末尾的空格),第二种buffer
使用环境。
当您的文本不包含任何特殊内容(如逐字等)时,setups
可以毫无问题地使用。
\startrawsetups[randomtext:1]
First item.
\stoprawsetups
\startrawsetups[randomtext:2]
Second item.
\stoprawsetups
\startrawsetups[randomtext:3]
Third item.
\stoprawsetups
\startrawsetups[randomtext:unknown]
Another item.
\stoprawsetups
\define\RandomText
{\getrandomnumber\randomnumber{1}{4}%
\doifsetupselse{randomtext:\randomnumber}
{\directsetup{randomtext:\randomnumber}}
{\directsetup{randomtext:unknown}}}
\starttext
\dorecurse{3}{\RandomText\par}
\stoptext
当您还有逐字文本或其他特殊内容时,TeXbuffers
是更好的解决方案,因为它们不会出现问题。
\startbuffer[randomtext:1]
First item.
\stopbuffer
\startbuffer[randomtext:2]
Second item.
\stopbuffer
\startbuffer[randomtext:3]
Third item.
\stopbuffer
\startbuffer[randomtext:unknown]
Another item.
\stopbuffer
\define\RandomText
{\getrandomnumber\randomnumber{1}{4}%
\doifelsebuffer{randomtext:\randomnumber}
{\getbuffer[randomtext:\randomnumber]}
{\getbuffer[randomtext:unknown]}}
\starttext
\dorecurse{3}{\RandomText\par}
\stoptext
答案3
这是一段用 Lua 编写的代码,可从 LuaLaTeX 运行,只需对 TeX 结构进行少量修改,即可轻松在 ConTeXt 中运行。我们获取表中的元素数量,然后随机挑选一个项目并确定它是否是表类型。如果是,我们会再调用该函数一次,否则我们会打印所选项目。
在此示例中,我们运行该函数十次以检查它是否按预期工作。
% run: lualatex mal-random.tex
\documentclass{article}
\usepackage{luacode}
\begin{luacode*}
-- Some input data...
math.randomseed(0)
randomdata={
"first",
{"second-a", "second-b", "second-c"},
"third",
"fourth",
"fifth",
}
-- Repetition of the function...
function randomme (number)
for i=1,number do -- repetition
randomcall(randomdata)
end --for i
end --function randomme
function randomcall (input)
randompick=math.random(#input)
randomcell=input[randompick]
print(#input, randompick, randomcell)
if type(randomcell)=="table" then
randomcall(randomcell)
else
print("Selected item ("..randompick..".): "..randomcell)
tex.print(randomcell)
end -- if type
end --function randomcall
\end{luacode*}
\begin{document}
\directlua{randomme(10)}
\end{document}
运行后,lualatex mal-random.tex
我们在终端中收到这些消息(它列出了实际级别的大小、所选项目的顺序以及项目本身):
5 2 table: 01524790
3 2 second-b
Selected item (2.): second-b
5 1 first
Selected item (1.): first
5 2 table: 01524790
3 2 second-b
Selected item (2.): second-b
5 2 table: 01524790
3 3 second-c
Selected item (3.): second-c
5 2 table: 01524790
3 3 second-c
Selected item (3.): second-c
5 1 first
Selected item (1.): first
5 5 fifth
Selected item (5.): fifth
5 1 first
Selected item (1.): first
5 1 first
Selected item (1.): first
5 4 fourth
Selected item (4.): fourth
我们将在 PDF 文件中看到选定的非表格项目:second-b first second-b second-c second-c first fifth first first fourth
。