Introduction

Conditional boxes of text can be very useful with LaTeX. I have been making use of them at least in two different ways in the past few years:

Here, we will focus on the latter which is more difficult.

Automatic generation of exams and solutions

As a teacher, it so happens that often I have to write exams. For that I use the powerful LaTeX, but even though there are already quite a few exam classes out there, I usually find them to bloated.

That is why I came up with my own solution to write exams. In my solution, you write only one source file, containing both questions and solutions, and you get two outputs automatically: the teacher's version with the solution, and the students' version without the solution but with empty boxes instead so they can fill in their answers directly on the document.

The environment that does it all

First of all, for the new environment to work, you have to include one extra package, the ifthen package. This package makes it possible to distinguish between the teacher's and the students' versions of the document.

Now the new environment that you have to define at the beginning of the document (i.e. before the \begin{document}) is as follows:

\newenvironment{solution}[1]{%
    \ifthenelse{\isundefined{\teacher}}{%
        \fbox{\begin{minipage}{\linewidth}\hfill\vspace*{#1}\end{minipage}}%
    }{}%
    \newbox\tempbox%
    \begin{lrbox}{\tempbox}\begin{minipage}{\linewidth}%
}{%
    \end{minipage}\end{lrbox}%
    \ifthenelse{\not\isundefined{\teacher}}{%
        \medskip%
        \fbox{\usebox{\tempbox}}%
        \medskip%
    }{}%
}

Basically, everything that is contained between \begin{solution} and \end{solution} commands, will only be displayed in the teacher's version. In the students' version, the environment takes an argument, which is the vertical space that the empty box should take on the document (so that students can write down their answer).

Usage

Here is an example of using this new environment (extracted from a real test):

\paragraph{Question #1 (1 point)} What are the three general-purpose
registers of a MIPS32 processor that the kernel does not have to save when
context switching?

\begin{solution}{5cm}
    $26, $27 et $0.
\end{solution}

In the teacher's version, we will see the solution in a box that fits the answer. But in the students' version, they just have an empty box of 5cm in height to propose their answer.

Makefile

Now we have to write a Makefile that will automatically generate both the teacher's and the students' versions.

Assuming that the document is called exam.tex, here is a simple Makefile that would work:

SRC_BASE=exam

all: $(SRC_BASE)_students.pdf $(SRC_BASE)_teacher.pdf

%_students.pdf: %.tex
    pdflatex -jobname $*_students $<

%_teacher.pdf: %.tex
    pdflatex -jobname $*_teacher "\def\teacher{true} \include{$*}"

Enjoy!

Under the hood

Let us look further at the definition of this new environment. As explained on the LaTeX wikibook, a newenvironment command receives several arguments:

\newenvironment{name}[num]{before}{after}

Understanding the teacher's version

When in teacher's version, meaning \teacher is defined (see Makefile above to understand how), the environment macro will be expanded as follows (notice that since \isdefined does not seem to exist, we had to use \not\isundefined to perform the same condition):

\newenvironment{solution}[1]{%
    \newbox\tempbox%
    \begin{lrbox}{\tempbox}\begin{minipage}{\linewidth}%
}{%
    \end{minipage}\end{lrbox}%
    \medskip%
    \fbox{\usebox{\tempbox}}%
    \medskip%
}

Basically, when encountering a \begin{solution}, we will create a lrbox (save box) in which we define a minipage. The minipage occupies a full line in width (linewidth). In the after part, we close the minipage and the lrbox. Now the interesting thing is that lrbox actually saves all the text that is between our \begin{solution} and \end{solution} in the temporary object, \tempbox, that was defined with \newbox.

The lrbox environment does not print anything until invoked. And this is exactly what we do when declaring a \fbox, in which we finally print the content of the saved lrbox by calling \usebox with the corresponding name.

If we recall the example above, the environment would be fully expanded as follows:

\medskip
\fbox{
    \begin{minipage}{\linewidth}
        $26, $27 et $0.
    \end{minipage}
}
\medskip

Understanding the students' version

When in students' version, meaning \teacher is not defined, the environment macro will be expanded as follow:

\newenvironment{solution}[1]{%
    \fbox{\begin{minipage}{\linewidth}\hfill\vspace*{#1}\end{minipage}}%
    \newbox\tempbox%
    \begin{lrbox}{\tempbox}\begin{minipage}{\linewidth}%
}{%
    \end{minipage}\end{lrbox}%
}

So now, when encountering a \begin{solution}, we will create a fbox (framed box) in which we define a minipage. The minipage takes a full line in width (linewidth), and contains a vertical space specified by the argument (\vspace*{#1}).

The second line creates a lrbox that saves all the text that is between our \begin{solution} and \end{solution}. Contrarily to the teacher's version though, in the after part, we just close the minipage and the lrbox but we do not invoke what we saved in the lrbox which means the solution is not displayed.

If we recall the example above, the environment would be fully expanded as follows:

\fbox{
    \begin{minipage}{\linewidth}
        \hfill
        \vspace*{5cm}
    \end{minipage}
}