The creation of multiple-choice exam with answer key can be pretty complex when you want multiple sets of the same exam with shuffle questions and choices. This gets increasingly more complex as you want more sets.
Let solve one problem at a time. Generating 2n sets of multiple choice is pretty easy. For example, if you want 8 sets, then you can just divide the question sets into 3 parts, with 2 versions for each part. Combined, you get 8 sets. Easy (?).
Now for the LaTeX code to help with the other part. To be fair, this code still requires you to shuffle things manually. But it 1) auto-number the question and choice so you can just re-arrange them without changing the number and 2) automatically generate answer key based on choice marked as correct.
The Code
First, we need some packages. These should be available on any standard LaTeX installation.
\usepackage{xspace}
\usepackage{listofitems}
\usepackage{tabto}
Then, we define some macro to control how to display the answer key:
\newcommand{\showAns}{1}
\newcommand{\showInlineAns}{1}
The first setting shows the answer key at the end of the question set (useful for distributing the key after the exam, or to give to TA to do the grading), and the second shows the key directly under each question (useful for checking the key correctness).
Now to the meat of the entire operation. This is going to be quite complex:
1\def\ansL{}
2\newcounter{question}
3\newcounter{choice}[question]
4\newcommand{\lquestion}[1][1]{\textbf{Q\the\numexpr\value{question}-#1\relax}\xspace}
5\newcommand{\nquestion}[1][1]{\textbf{Q\the\numexpr\value{question}+#1\relax}\xspace}
6\def\qref #1{\textbf{Q\ref{#1}}}
7\newenvironment{question}[1]%
8{%
9 \filbreak\refstepcounter{question}\textbf{Q\thequestion.} #1
10
11}%
12{%
13 \ifx\correctAns\undefined%
14 \edef\correctAns{NONE}%
15 \fi%
16 \global\edef\ansL{\ansL,\correctAns}%
17 \ifnum\showInlineAns=1
18
19 \vspace{-0.5cm}
20 \emph{Answer.} \correctAns
21 \fi
22}%
23\newcommand{\C}[0]{\stepcounter{choice}\textbf{\thechoice) }}
24\newcommand{\CA}[0]{\stepcounter{choice}\textbf{\thechoice) }\edef\correctAns{\thechoice}}
25\newcommand{\setAns}[1]{\edef\correctAns{#1}}
26\newcommand{\answerList}[1][5]{\setsepchar{,} \ignoreemptyitems \readlist\ans{\ansL}\NumTabs{#1} \foreachitem\item\in\ans{Q\itemcnt{}: \item \tab }}
To break up this chunk of code:
Line 1 defines the macro ansL
, which will store our answer key in a comma-seperated format.
Line 2-3 define the question and choice counter, with the choice counter reset everytime the question counter steps.
Line 4-5 define the \lquestion[n]
and \nquestion[n]
to reference to the previous or next question. The [n]
parameter is optional
and will just be n previous or next question. For example, in the text of Q38, if we write \lquestion[2]
it will show up as Q36.
Line 6 defines the macro \qref{label}
to display the referenced question number in the Qxx format.
Line 7-22 define the main question environment. The header part steps the counter and display the question text. The footer check if \correctAns
exists, if it it isn’t
define the \correctAns
as NONE. It then append the current \correctAns
to the global \ansL
to store them, and also display the \correctAns
if \showInlineAns
is defined.
Line 23-24 define the \C
and \CA
macro for choice. Beside stepping the choice counter, the \CA
will also define \correctAns
to the current choice number.
Line 25 is a \setAns
macro for explicitly set the answer key directly. For example, for bonus question with no real correct answer. You can do \setAns{n/a}
.
Line 26 is the \answerList
macro for displaying all the answer keys. It uses the listofitems
package to read the comma-seperated answer in \ansL
and display them
with spacing provide by tabto
package.
Usage
For each question, use the following templates. \CA
indicate the correct choice. You can also use \label{q:xx}
the same way
you would reference other questions, with \qref
to display the reference. You can also use \lquestion
and \nquestion
as we define above.
\begin{question}{From \lquestion what we should do?}
\C 1 \\
\C 2 \\
\C 4 \\
\CA 3 \\
\end{question}
Finally, at the end of the question set, the following code will output the answer key in a seperated page if required.
\ifnum\showAns=1
\newpage
\textbf{Answer.}
\answerList[5]
\fi