考虑以下代码。这样的随机化可能吗?我有许多不同的表格,每个表格中的字母数量可能不同。但是,在每个表格中,字母始终对应于字母表的第一个字母。
\documentclass[english]{article}
\usepackage[T1]{fontenc}
\usepackage[latin9]{inputenc}
\makeatletter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands.
%% Because html converters don't know tabularnewline
\providecommand{\tabularnewline}{\\}
\makeatother
\usepackage{babel}
\begin{document}
\begin{tabular}{|c|c|c|}
\hline
\fbox{A} & 4 & \fbox{C}\tabularnewline
\hline
2 & \fbox{B} & 3\tabularnewline
\hline
\end{tabular}
\bigskip{}
\fbox{A} 5 \fbox{B} 6 \fbox{C} 7
\bigskip{}
I want to randomize A, B and C in different versions of this document.
For instance, one possible randomization is the following:
\bigskip{}
\begin{tabular}{|c|c|c|}
\hline
\fbox{B} & 4 & \fbox{A}\tabularnewline
\hline
2 & \fbox{C} & 3\tabularnewline
\hline
\end{tabular}
\bigskip{}
\fbox{A} 7 \fbox{B} 5 \fbox{C} 6 (Please, notice that now A, B
and C correspond to 7, 5 and 6.)
\bigskip{}
\end{document}
答案1
我希望以下内容能满足您的要求。它创建一个名为的环境,randomhidetable
其中tabular
每个字段都\hide
被字母表前 $n$ 个字符序列的随机元素替换(每个元素仅使用一次)。该表被评估两次,第一次评估计算元素数量\hide
,第二次对其进行排版。您可以\hide
使用环境的第二个可选参数(位于强制参数之后)更改为任意宏。
\__paul_hide_output_format:n
可以通过改变 的定义(当前定义为)来定制隐藏标签的格式\fbox{#1}
。
您可以使用带有四个参数的宏输出隐藏的单元格\hiddencells
:
- 标签和值之间的分隔符
- 如果只有两个标签,则不同标签之间的分隔符
- 如果有两个以上的标签,则使用不同标签之间的分隔符(最后两个除外)
- 如果有两个以上的标签,则在最后两个标签之间添加分隔符
\documentclass[]{article}
\usepackage{xparse}
\ExplSyntaxOn
\tl_new:N \l__paul_reveal_separator_tl
\int_new:N \g__paul_hide_count_int
\seq_new:N \g__paul_hide_seq
\seq_new:N \g__paul_hidden_seq
\seq_new:N \g__paul_reveal_seq
\NewDocumentEnvironment { randomhidetable } { O{c} +m O{\hide} +b }
{
\group_begin:
\int_gzero:N \g__paul_hide_count_int
\cs_set:Npn #3 ##1 { \int_gincr:N \g__paul_hide_count_int }
\hbox_set:Nn \l_tmpa_box { \begin { tabular } { #2 } #4 \end { tabular } }
\group_end:
\seq_gclear:N \g__paul_hide_seq
\seq_gclear:N \g__paul_hidden_seq
\int_step_inline:nn \g__paul_hide_count_int { \seq_gpush:Nn \g__paul_hide_seq { ##1 } }
\seq_gshuffle:N \g__paul_hide_seq
\cs_set:Npn #3 ##1
{
\seq_gpop:NN \g__paul_hide_seq \l_tmpa_tl
\__paul_hide_output_format:x { \char_generate:nn { 64 + \l_tmpa_tl } { 11 } }
\seq_gpush:Nx \g__paul_hidden_seq { { \l_tmpa_tl } { ##1 } }
}
\begin { tabular } [ #1 ] { #2 } #4 \end { tabular }
\seq_gsort:Nn \g__paul_hidden_seq
{
\int_compare:nNnTF { \use_i:nn ##1 } > { \use_i:nn ##2 }
{ \sort_return_swapped: }
{ \sort_return_same: }
}
\seq_gclear:N \g__paul_reveal_seq
\seq_map_inline:Nn \g__paul_hidden_seq
{
\__paul_hide_output_hidden_values:nn ##1
}
}
{}
\cs_new:Npn \__paul_hide_output_hidden_values:nn #1 #2
{
\seq_gput_right:Nx \g__paul_reveal_seq
{
\exp_not:N \__paul_hide_output_format:n
{ \char_generate:nn { 64 + #1 } { 11 } }
\exp_not:n { \l__paul_reveal_separator_tl #2 }
}
}
\cs_new:Npn \__paul_hide_output_format:n #1
{
\fbox { #1 }
}
\cs_generate_variant:Nn \__paul_hide_output_format:n { x }
\NewDocumentCommand \hiddencells { m m m m }
{
\group_begin:
\tl_set:Nn \l__paul_reveal_separator_tl { #1 }
\seq_use:Nnnn \g__paul_reveal_seq { #2 } { #3 } { #4 }
\group_end:
}
\ExplSyntaxOff
\begin{document}
\makebox[2cm][l]{First call:}
\begin{randomhidetable}[b]{ccc}
\hide{5} & 4 & \hide{7} \\
2 & \hide{6} & 3
\end{randomhidetable}
The hidden fields were: \hiddencells{~}{, }{, }{, and }
\makebox[2cm][l]{Second call:}
\begin{randomhidetable}[t]{ccc}[\foo]
\foo{5} & 4 & \foo{7} \\
2 & \foo{6} & 3
\end{randomhidetable}
The hidden fields were: \hiddencells{~}{ and }{, }{, and }
\end{document}
编辑:environ
如果您没有足够新的版本,可以使用该包作为替代版本xparse
。environ
调用基础环境randomhidetable*
,不支持第二个可选参数。为了仍然能够设置使用的宏,\sethidemacro
引入了新的宏(旧环境仍然有效):
\documentclass[]{article}
\usepackage{xparse}
\usepackage{environ}
\ExplSyntaxOn
\tl_new:N \l__paul_reveal_separator_tl
\tl_new:N \l__paul_hide_macro_name_tl
\tl_set:Nn \l__paul_hide_macro_name_tl { \hide }
\int_new:N \g__paul_hide_count_int
\seq_new:N \g__paul_hide_seq
\seq_new:N \g__paul_hidden_seq
\seq_new:N \g__paul_reveal_seq
%\NewDocumentEnvironment { randomhidetable } { O{c} +m o +b }
% {
% \IfValueTF { #3 }
% { \__paul_randomhidetable_code:nnnn { #1 } { #2 } { #3 } { #4 } }
% {
% \__paul_randomhidetable_code:nnVn
% { #1 } { #2 } \l__paul_hide_macro_name_tl { #4 }
% }
% }
% {}
\cs_new:Npn \__paul_randomhidetable_code:nnnn #1 #2 #3 #4
{
\group_begin:
\int_gzero:N \g__paul_hide_count_int
\cs_set:Npn #3 ##1 { \int_gincr:N \g__paul_hide_count_int }
\hbox_set:Nn \l_tmpa_box { \begin { tabular } { #2 } #4 \end { tabular } }
\group_end:
\seq_gclear:N \g__paul_hide_seq
\seq_gclear:N \g__paul_hidden_seq
\int_step_inline:nn \g__paul_hide_count_int { \seq_gpush:Nn \g__paul_hide_seq { ##1 } }
\seq_gshuffle:N \g__paul_hide_seq
\cs_set:Npn #3 ##1
{
\seq_gpop:NN \g__paul_hide_seq \l_tmpa_tl
\__paul_hide_output_format:x { \char_generate:nn { 64 + \l_tmpa_tl } { 11 } }
\seq_gpush:Nx \g__paul_hidden_seq { { \l_tmpa_tl } { ##1 } }
}
\begin { tabular } [ #1 ] { #2 } #4 \end { tabular }
\seq_gsort:Nn \g__paul_hidden_seq
{
\int_compare:nNnTF { \use_i:nn ##1 } > { \use_i:nn ##2 }
{ \sort_return_swapped: }
{ \sort_return_same: }
}
\seq_gclear:N \g__paul_reveal_seq
\seq_map_inline:Nn \g__paul_hidden_seq
{
\__paul_hide_output_hidden_values:nn ##1
}
}
\cs_generate_variant:Nn \__paul_randomhidetable_code:nnnn { nnVV }
\cs_generate_variant:Nn \__paul_randomhidetable_code:nnnn { nnVn }
\cs_new:Npn \__paul_hide_output_hidden_values:nn #1 #2
{
\seq_gput_right:Nx \g__paul_reveal_seq
{
\exp_not:N \__paul_hide_output_format:n
{ \char_generate:nn { 64 + #1 } { 11 } }
\exp_not:n { \l__paul_reveal_separator_tl #2 }
}
}
\cs_new:Npn \__paul_hide_output_format:n #1
{
\fbox { #1 }
}
\cs_generate_variant:Nn \__paul_hide_output_format:n { x }
\NewDocumentCommand \hiddencells { m m m m }
{
\group_begin:
\tl_set:Nn \l__paul_reveal_separator_tl { #1 }
\seq_use:Nnnn \g__paul_reveal_seq { #2 } { #3 } { #4 }
\group_end:
}
\NewDocumentCommand \sethidemacro { m }
{
\tl_set:Nn \l__paul_hide_macro_name_tl { #1 }
}
\NewEnviron{randomhidetable*}[2][c]
{
\__paul_randomhidetable_code:nnVV
{ #1 } { #2 } \l__paul_hide_macro_name_tl \BODY
}
\ExplSyntaxOff
\begin{document}
\makebox[2cm][l]{First call:}
\begin{randomhidetable*}[b]{ccc}
\hide{5} & 4 & \hide{7} \\
2 & \hide{6} & 3
\end{randomhidetable*}
The hidden fields were: \hiddencells{~}{ and }{, }{, and }
\makebox[2cm][l]{Second call:}
\begingroup
\sethidemacro{\foo}
\begin{randomhidetable*}[t]{ccc}
\foo{5} & 4 & \foo{7} \\
2 & \foo{6} & 3
\end{randomhidetable*}
\endgroup
The hidden fields were: \hiddencells{~}{ and }{, }{, and }
\end{document}
答案2
由于 Skillmon 的解决方案无法在我的 LaTeX 发行版上编译(Fedora Linux 仍然使用 TexLive 2018),我不得不寻找其他解决方案。我找到了以下解决方案,它使用R
via knitr
。
\documentclass[english]{article}
\usepackage[T1]{fontenc}
\usepackage[latin9]{inputenc}
\usepackage{geometry}
\geometry{verbose,tmargin=2cm,bmargin=2cm,lmargin=2cm,rmargin=2cm}
\makeatletter
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% LyX specific LaTeX commands.
%% Because html converters don't know tabularnewline
\providecommand{\tabularnewline}{\\}
\makeatother
\usepackage{babel}
\begin{document}
<<echo=F>>=
v <- c("A","B","C")
w <- c(10,20,30)
order <- sample(1:3)
v <- v[order]
@
\noindent \begin{center}
\begin{tabular}{|c|c|c|}
\hline
\fbox{\Sexpr{v[1]}} & 4 & \fbox{\Sexpr{v[3]}}\tabularnewline
\hline
2 & \fbox{\Sexpr{v[2]}} & 6\tabularnewline
\hline
\end{tabular}
\par\end{center}
This time, we have: A=\Sexpr{w[which(v == "A")]}, B=\Sexpr{w[which(v == "B")]}
e C=\Sexpr{w[which(v == "C")]}.
<<echo=F>>=
ordem <- sample(1:3)
v <- v[ordem]
@
\noindent \begin{center}
\begin{tabular}{|c|c|c|}
\hline
\fbox{\Sexpr{v[1]}} & 4 & \fbox{\Sexpr{v[3]}}\tabularnewline
\hline
2 & \fbox{\Sexpr{v[2]}} & 6\tabularnewline
\hline
\end{tabular}
\par\end{center}
This time, we have: A=\Sexpr{w[which(v == "A")]}, B=\Sexpr{w[which(v == "B")]}
e C=\Sexpr{w[which(v == "C")]}.
\end{document}