语境
我正在尝试制作一个自动考试,我可以使用pgfmathrandominteger
AMC 包中的 生成随机数(使用 )来使用代码(listings
)创建不同的问题,并将这些随机数输入到代码中。例如,更改变量将获得的值,或更改循环的迭代次数等。
问题
然而,该listing
包在 AMC 环境中并不容易使用(参见如何扩展宏以在 AMC 的问题中使用它?)。而且,添加应该出现在代码中的随机数,以及从问题中生成该数字也成为一个挑战。
例如,在下面的代码中,我可以生成数字(\pgfmathrandominteger{\mynum}{1}{8}
),但是当使用更多问题时它不起作用(使用多个副本时也会发生同样的情况)。
理想情况下,我应该在问题中生成随机数,这样每次 AMC 解析问题时都会生成一个新数字,然后框应该会解析它。但是,框在声明时已经排版(据我所知)。因此,当我在代码上使用它时lstlisting
(如果我可以访问\mynum
宏),我仍然需要能够一次又一次地重新调整该环境。
如何实现该行为?
\documentclass{article}
\usepackage[box]{automultiplechoice}
\usepackage{listings}
\usepackage{tikz}
\lstset{ escapeinside={@*}{*@}}
% a simple wrapper to create boxes automatically
\makeatletter
\newcounter{myboxcounter}
\newenvironment{mybox}{%
\stepcounter{myboxcounter}%
\expandafter\newsavebox\csname foobox\roman{myboxcounter}\endcsname
\global\expandafter\setbox\csname foobox\roman{myboxcounter}\endcsname\hbox\bgroup\color@setgroup\ignorespaces
}{%
\color@endgroup\egroup
}
\newcommand{\insertbox}{\stepcounter{myboxcounter}%
\edef\name{foobox\roman{myboxcounter}}\edef\x{%
\expandafter\usebox\csname\name\endcsname}\x}
\makeatother
\begin{document}
%%% preparation of the groups
\pgfmathrandominteger{\mynum}{1}{8}
\begin{mybox}
\begin{lstlisting}[language=C++]
int a = @*\mynum*@;
a = a + 10;
\end{lstlisting}
\end{mybox}
\element{code}{
\begin{question}{code 1}
Which is the result of \texttt{a} \mynum?
\insertbox
\begin{choices}
\correctchoice{\pgfmathparse{\mynum+10}\pgfmathresult}
\wrongchoice{20}
\wrongchoice{0}
\wrongchoice{30}
\end{choices}
\end{question}
}
%%% copies
\setcounter{myboxcounter}{0}
\onecopy{1}{% when changed the number of copies to more than one it won't work
\insertgroup{code}
}
\end{document}
答案1
您不应该在参数中使用列表,但如果您在自找麻烦,另一个实验性解决方法(在文档中解释)是^^J
在每行末尾添加换行符( ),转义\{}%
字符和空格。不幸的是,您无法在这样的列表中转义到 LaTeX(根据包文档),因此您几乎没有机会在此处包含随机值。
但是,无需列表(或仅将其用于不可变代码),使用该包可以轻松在 AMC 中使用随机值进行数学运算fp
。一个简单的例子:
\documentclass{article}
\usepackage[box]{automultiplechoice}
\usepackage{fp}
\usepackage{amsmath}
\usepackage{listings}
\element{code}{
\begin{question}{sum}
\FPeval\Ra{trunc(1+random*8,0)}
\FPeval\Rb{trunc(4+random*5,0)}
\FPeval\RnoA{clip((Ra+1)/Rb)}
\FPeval\RnoB{clip(Ra*Rb+100)}
\FPeval\RnoC{clip(Ra-Rb+1)}
\FPeval\Ryes{clip(Ra+Rb)}
\begin{lstlisting}^^J
a ? b = c ^^J
\end{lstlisting}
Check the equation with correct result ($c$) when $a = \Ra{}$ and $b = \Rb{}$?
\begin{choices}
\wrongchoice{ $\dfrac{\Ra{}}{\Rb{}} = \RnoA$}
\wrongchoice{ $\Ra{}^{\Rb{}} = \RnoB$}
\wrongchoice{ $\Ra{} - \Rb{} = \RnoC$}
\correctchoice{ $\Ra{} + \Rb{} = \Ryes$}
\end{choices}
\end{question}}
\lstset{basicstyle=\color{red!50!black}\bfseries\sffamily,frame=none}
\begin{document}
\onecopy{2}{\insertgroup{code}}
\end{document}
编辑:好的,好的,你希望一切都是最好的,无论它有多复杂。
解决此问题的一个肮脏技巧是使用\input{}
包含宏的代码。我不确定这种方法有多安全,因此请自行承担风险。逐步修改上述示例:
1)包含转义字符
\lstset{escapechar=!, ....}
2)剪切lstlisting
环境,将其另存为 chunk.tex
,删除换行符(^^J
)并插入转义的随机值:
\begin{lstlisting}
!\Ra\ ? \Rb\ = c
\end{lstlisting}
3)然后插入\input{chunk}
考试。
4)编译并检查结果:
编辑2:
另一个选择是尝试其他代码列表方法。检查CTAN 中的主题列表。您的里程可能会因您对格式和与 AMC 兼容性的目标而异。例如,该包minted
算法适合代码列表,但似乎也与上述 MWE 不兼容,而该包algpseudocode
允许使用 algorithmic
似乎在问题内部运行良好的环境,包括变量\Ra
和\Rb
:
\begin{algorithmic}[1]
\State $sum\gets \Ra$
\State $i\gets \Rb $
\While{$i\le n$}
\State $sum\gets sum+i$
\State $i\gets i+1$
\EndWhile
\end{algorithmic}