Monday, February 25, 2008

Deferred printing in LaTeX

Ever written a textbook? Ever written any document that has questions/problems and answers to those problems? Usually when you do this, you want to have questions printed in one place (or questions in each section of the document), and answers printed at the end of the document (so your readers, which are usually students, would try to actually solve the problem rather than just look at the solution which is right under the problem).
Now, I don't know how most of you usually do this, but up until now the only way I knew to do this is the "brute force" approach---I would simply write the questions and then, at the end of the document, I would write the answers. The obvious drawback of this approach is that you have to look up each individual question when writing the answers (just to see what it was) and this can quickly become very boring. Or, if you have the questions/answers on paper, they are usually written in pairs question/answer so you have to first type all the questions (ignoring the answers), and then go back to the begining of the paper and type all the answers (ignoring the questions). Anyway, I hope you get the picture why I hate doing this.
Wouldn't it be great if I could somehow have the question and its answer in the same place in the source of the document (notice that we are not talking about WYSIWYG text processors here), but then defer the printing of answers in the output document (that is, print the answers at the end of the document)? The solution to my problem comes in a form of the LaTeX box mechanism. Just take a look at this minimal example:


\documentclass{article}

\newbox\answerscollect
\newcounter{problem}
\setcounter{problem}{0}
\renewcommand{\theproblem}{\textit{Problem \arabic{problem}.}\,}

\def\answer#1{\par\setbox\answerscollect=\vbox{\unvbox\answerscollect\vspace{5mm}\theproblem\,#1\par}}
\def\printanswers{\unvbox\answerscollect\setbox\answerscollect=\vbox{}}
\def\initbox{\setbox\answerscollect=\vbox{Answers:\par}}

\newcommand{\problem}[1]{\addtocounter{problem}{1}\par\theproblem\textit{#1}}

\begin{document}

\initbox

\section{Intro}
Some text before...

\problem{What is the capital of the US?}
\answer{Washington, D.~C.}

\problem{What is 2+2?}
\answer{4}

\section{Foo}

Some other text goes here...

\section{Answers}

\printanswers

\end{document}

Now I know it looks a bit complicated, but it really isn't. What we are doing is creating a box and storing all the answers in it, and then, when the time is write, we simply print all the contents of that box using the \printanswers command. This way, we can simply have the problem and its solution (answer) in the same place in the source of the document, but have the answers appear in a totally different place in the output pdf (or postscript or whatever). Now, I'm not going to go into details of the LaTeX code itself here. Those who know LaTeX will pretty much understand the code, and those who don't should first learn the basics before trying to get this. Anyway, the code can be used out-of-the-box; if someone would like to change something but doesn't know how, you can contact me. Last, but not least, here is how the output pdf looks like:


UPDATE: As Evan noted, if you are going to use multiple files, don't use \include. Instead, use the \input command which does not create new .aux files.