% \begin{meta-comment}
%
% $Id: exercise.dtx,v 1.2 2003/09/05 16:10:41 mdw Exp $
%
% Exercises
%
% (c) 2003 Mark Wooding
%
% \end{meta-comment}
%
% \begin{meta-comment} <general public licence>
%%
%% exercise package -- useful macros for setting exercises with answers
%% Copyright (c) 2003 Mark Wooding
%%
%% This program is free software; you can redistribute it and/or modify
%% it under the terms of the GNU General Public License as published by
%% the Free Software Foundation; either version 2 of the License, or
%% (at your option) any later version.
%%
%% This program is distributed in the hope that it will be useful,
%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
%% GNU General Public License for more details.
%%
%% You should have received a copy of the GNU General Public License
%% along with this program; if not, write to the Free Software Foundation,
%% Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
% \end{meta-comment}
%
% \begin{meta-comment} <Package preambles>
%<+package>\NeedsTeXFormat{LaTeX2e}
%<+package>\ProvidesPackage{exercise}
%<+package>                [2003/08/25 1.1 Exercies with answers]
% \end{meta-comment}
%
% \CheckSum{271}
%% \CharacterTable
%%  {Upper-case    \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z
%%   Lower-case    \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z
%%   Digits        \0\1\2\3\4\5\6\7\8\9
%%   Exclamation   \!     Double quote  \"     Hash (number) \#
%%   Dollar        \$     Percent       \%     Ampersand     \&
%%   Acute accent  \'     Left paren    \(     Right paren   \)
%%   Asterisk      \*     Plus          \+     Comma         \,
%%   Minus         \-     Point         \.     Solidus       \/
%%   Colon         \:     Semicolon     \;     Less than     \<
%%   Equals        \=     Greater than  \>     Question mark \?
%%   Commercial at \@     Left bracket  \[     Backslash     \\
%%   Right bracket \]     Circumflex    \^     Underscore    \_
%%   Grave accent  \`     Left brace    \{     Vertical bar  \|
%%   Right brace   \}     Tilde         \~}
%%
%
% \begin{meta-comment}
%
%<*driver>
\input{mdwtools}
\describespackage{exercise}
\let\epsilon\varepsilon
\errorcontextlines\maxdimen
\mdwdoc
%</driver>
%
% \end{meta-comment}
%
%^^A-------------------------------------------------------------------------
% \section{User guide}
%
% The \package{exercise} package allows you to typeset exercises and keep the
% answers together with the questions in your source (so they don't get
% lost) but typeset them all together at the end of your document.
%
% \subsection{Exercises and answers}
%
% \DescribeEnv{exercise}
% Exercises are typset in an \env{exercise} environment.  This takes no
% arguments.  There's a counter for exercises, named |exercise|, and you can
% cross-reference exercises in the usual way.
%
% \DescribeMacro\answer
% If you want to include an answer for your exercise, just say |\answer|
% followed by your answer.  The rest of the text up to the end of the
% \env{exercise} environment is considered to be the answer, and is stored
% away until asked for.  This material can contain anything you like.  It
% \emph{isn't} a moving argument.
%
% \begin{figure}
%\begin{demo}[w]{The \env{exercise} environment}
%\begin{exercise}
%Show that if $F\colon \{0, 1\}^k \times \{0, 1\}^* \to \{0, 1\}^L$
%is a $(t, q + 1, \epsilon)$-secure PRF, then $F$~is also a
%$(t, q, \epsilon + 2^{-L})$-secure MAC.
%\answer
%Let~$A$ be an adversary attacking~$F$ as a MAC.  Consider the
%adversary~$B$ \ldots
%\end{exercise}
%\end{demo}
% \end{figure}
%
% \DescribeMacro\skipanswer
% The |\skipanswer| command is similar, but just skips over the answer rather
% than writing it to the output file.  It does nothing at all with counters
% -- it's as if there was no answer given at all.
%
% It's OK to use commands like |\answer| and |\skipanswer| in your own
% macros as long as they're the \emph{last} token.  You can therefore say
% something like
%\begin{verbatim}
%\newcommand{\evenanswer}{%
%  \ifthenelse%
%    {\isodd{\value{exercise}}}%
%    {\answer}%
%    {\skipanswer}%
%}
%\end{verbatim}
% to get just the answers to the odd-numbered problems.  (If you don't like
% \package{ifthen} then you'll need to play with |\expandafter| for a bit.)
%
% \subsection{The answers file}
%
% \DescribeMacro\answrite
% Answers are accumulated into a file, to be read later.  Additional material
% can be added to the file using the |\answrite| macro, which just writes its
% argument.  Note that this is a \emph{moving} argument, so fragile commands
% need |\protect|ing.
%
% \DescribeMacro\exctrcheck
% It's common to divide up the answers by section.  You can tell the package
% to check a collection of counters and perform actions if they've changed
% since last time, giving you a chance to write the correct decorations to
% the answers file.  This is done by saying
% \syntax{"\\exctrcheck{"<counter>"}{"<action>"}"}.  Then, each |\answer|
% command checks to see if \<counter> has changed since last time, and if it
% has, it does \<action>,  For example,
%\begin{verbatim}
%\exctrcheck{section}
%  {\answrite{\protect\subsection*{Section \thesection}}}
%\end{verbatim}
% starts a new (unnumbered) subsection in the answers for each section in the
% main document.
%
% \subsection{Style tweaks}
%
% The \env{exercise} environment is very simple, and can be easily rewritten
% to fit in with your style preferences.  If you like exercises to look like
% theorems, the easiest thing to do is say something like
%\begin{verbatim}
%\newtheorem{doexercise}[exercise]{\exercisename}
%\renewenvironment{exercise}{\exfix\doexercise}{\enddoexercise}
%\end{verbatim}
% This makes the environment use the existing exercise counter.  If you don't
% want that, say
%\begin{verbatim}
%\newtheorem{doexercise}[othercounter]{\exercisename}
%\renewenvironment{exercise}{\exfix\doexercise}{\enddoexercise}
%\let\theexercise\theothercounter
%\end{verbatim}
% and all will be well.
%
% \DescribeEnv{doanswer}
% Answers are typeset in a \env{doanswer} environment, which is given one
% argument: the exercise number (as set by |\theexercise|).  This can be
% modified to do whatever you like.
%
% \DescribeMacro\exfix
% The |\exfix| is a convenient hook which is run both in the \env{exercise}
% and \env{doanswer} environments by default.  The current implementation
% just skips a level of \env{enumerate} depth, which usually means that
% \env{enumerate} lists will go (a), (b), (c), \ldots\ rather than 1, 2, 3,
% \ldots
%
% \subsection{Lists in paragraphs}
%
% \DescribeEnv{parenum}
% Answers to subparts tend to be compressed together into a single
% paragraph.  It's nice, when you do this, not to have to worry about losing
% your numbering of subparts.  The \env{parenum} environment provides an
% enumerated list in a paragraph.  So, for example, you can say something
% like this.
%\begin{demo}[w]{Example of \env{parenum}}
%\begin{exercise}
%A PRG $g\colon \{0, 1\}^k \to \{0, 1\}^L$ is \emph{trivial} if
%$k \ge L$.
%\begin{enumerate}
%\item Show that trivial PRGs exist.
%\item Show that a non-trivial $(t, \epsilon)$-secure PRG is a
%  $(t, \epsilon + 2^{k-L})$-secure one-way function.
%\end{enumerate}
%\answer
%\begin{parenum}
%\item The identity function is a trivial PRG: the real and random
%  games are identically distributed.
%\item Let~$A$ be an adversary attempting to invert~$g$: then we
%  can construct a distinguisher~$B$ as follows \ldots
%\end{parenum}
%\end{exercise}
%\end{demo}
%
% \subsection{And finally}
%
% \DescribeMacro\answers
% In order to extract your answers, say |\answers|.
%\begin{demo}[w]{The \texttt{\string\answers} command}
%\section*{Answers}
%\answers
%\end{demo}
%
% The |\answers| command has an optional argument, which is the file to read
% in.  This allows you to make `answer booklet' documents, by saying
% something like
%\begin{verbatim}
%\answers[otherdoc]
%\end{verbatim}
% If you don't give a file extension, then |.ans| is appended automatically.
%
% \implementation
%
%
%^^A-------------------------------------------------------------------------
% \section{Implementation}
%
%    \begin{macrocode}
%<*package>
%    \end{macrocode}
%
% \subsection{Initialization}
%
% The \textsf{within} option is handled by the \package{mdwkey} package.
%
%    \begin{macrocode}
\RequirePackage{mdwkey}
%    \end{macrocode}
%
% \begin{macro}{\ex@within}
%
% When the \textsf{within} option is seen, we set a command |\ex@within| to
% the correct code, to be executed later when we've made our minds up.
%
%    \begin{macrocode}
\let\ex@within\relax
\mkdef{exercise:opts}{within}{%
  \def\ex@within{%
    \@addtoreset{exercise}{#1}%
    \toks@\expandafter{\csname the#1\expandafter\endcsname%
                       \expandafter.\theexercise}%
    \edef\theexercise{\the\toks@}%
  }%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ex@opts}
%
% The |\ex@opts| macro just runs the \package{mdwkey} kit to parse an option
% string.
%
%    \begin{macrocode}
\def\ex@opts{\mkparse{exercise:opts}}
%    \end{macrocode}
% \end{macro}
%
% Now do the options thing.
%
%    \begin{macrocode}
\DeclareOption*{\expandafter\ex@opts\expandafter{\CurrentOption}}
\ProcessOptions*
%    \end{macrocode}
%
% Set up the |exercise| counter, and number it within some other sort of
% counter as appropriate.
%
%    \begin{macrocode}
\newcounter{exercise}\ex@within
%    \end{macrocode}
%
% We also need the \package{sverb} package in order to do the delaying of the
% answers.
%
%    \begin{macrocode}
\RequirePackage{sverb}
%    \end{macrocode}
%
% \subsection{Checking for counter changes}
%
% \begin{macro}{\ex@ctrcheck}
%
% The counter checking state is stored here.  It's initially empty.
%
%    \begin{macrocode}
\def\ex@ctrcheck{}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\exctrcheck}
%
% Adding a counter to the check list is relatively easy.  We expand the
% current list into a token register, add the new material to the end, and
% put the list back in our macro using |\edef|.  The `last' value of the
% counter is set to |\relax|, to force out the change on the next |\answer|.
%
%    \begin{macrocode}
\def\exctrcheck#1#2{%
  \toks@\expandafter{\ex@ctrcheck\ex@ctrdo{#1}{#2}}%
  \edef\ex@ctrcheck{\the\toks@}%
  \global\expandafter\let\csname ex@ctrlast@#1\endcsname\relax%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\ex@ctrdo}
%
% Here we actually check to see whether a counter has changed and execute the
% appropriate code.
%
%    \begin{macrocode}
\def\ex@ctrdo#1#2{%
  \edef\@tempa{\csname the#1\endcsname}%
  \expandafter\ifx\csname ex@ctrlast@#1\endcsname\@tempa\else%
    #2%
    \global\expandafter\let\csname ex@ctrlast@#1\endcsname\@tempa%
  \fi%
}
%    \end{macrocode}
% \end{macro}
%
% \subsection{The \env{exercise} environment}
%
% \begin{macro}{\exercisename}
%
% We store the string to print for each exercise in |\exercisename| as a
% half-hearted attempt at internationalization.
%
%    \begin{macrocode}
\providecommand\exercisename{Exercise}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\exfix}
%
% This is a dumping ground for style fixing common to both exercises and
% answers.  Here, we bump on the \env{enum} depth counter, so that it skips
% labelling with digits.
%
%    \begin{macrocode}
\def\exfix{\advance\@enumdepth\@ne}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{exercise}
%
% This is pretty simple.  The environment is list-based, with the number set
% in bold in a label.
%
%    \begin{macrocode}
\def\exercise{%
  \refstepcounter{exercise}%
  \exfix%
  \trivlist\advance\itemindent\labelsep%
  \item[\textbf{\exercisename\ \theexercise}]%
}
\let\endexercise\endtrivlist
%    \end{macrocode}
% \end{environment}
%
% \subsection{Answers}
%
% We need a file in which to store our answers.
%
%    \begin{macrocode}
\newwrite\ex@ansfile
%    \end{macrocode}
%
% \begin{macro}{\ex@ansfilename}
%
% In case anyone has a better idea for a filename than our default, we
% provide a hook.
%
%    \begin{macrocode}
\def\ex@ansfilename{\jobname.ans}
%    \end{macrocode}
% \end{macro}
%
% We open the file at the end of the preamble, to give the user a chance to
% say |\nofiles|, or change |\ex@ansfilename|.
%
%    \begin{macrocode}
\AtBeginDocument{%
  \if@filesw%
    \immediate\openout\ex@ansfile=\ex@ansfilename\relax%
    \answrite\relax%
  \fi%
}
%    \end{macrocode}
%
% \begin{macro}{\answrite}
%
% This writes stuff to the answers file.  We make sure that it's
% appropriately protected, so that you can insert section headings and so on.
%
%    \begin{macrocode}
\def\answrite#1{%
  \if@filesw%
    \begingroup%
    \let\protect\@unexpandable@protect%
    \immediate\write\ex@ansfile{#1}%
    \endgroup%
  \fi%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\answer}
%
% The |\answer| macro needs to read until the end of the enclosing
% \env{exercise} environment (or whatever).
%
%    \begin{macrocode}
\def\answer{\sv@readenv\ex@answer}
%    \end{macrocode}
%
% Now for the main guts.
%
%    \begin{macrocode}
\def\ex@answer#1#2{%
  \begingroup%
  \@bsphack%
%    \end{macrocode}
%
% First of all, check to see whether any counters have changed.
%
%    \begin{macrocode}
  \ex@ctrcheck%
%    \end{macrocode}
%
% Start a \env{doanswer} environment in the file.
%
%    \begin{macrocode}
  \answrite{\noexpand\begin{doanswer}{\theexercise}}%
%    \end{macrocode}
%
% Set catcodes to be strange, and read lines one-at-a-time, writing them to
% the file.  When finished, continue at |\ex@endanswer|.
%
%    \begin{macrocode}
  \let\do\@makeother\dospecials%
  \sv@safespc%
  \sv@read{#1}\answrite{\ex@endanswer#2}%
}
%    \end{macrocode}
%
% When that's done, we wind up here.
%
%    \begin{macrocode}
\def\ex@endanswer{%
  \@esphack%
  \answrite{\noexpand\end{doanswer}}%
  \endgroup%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\skipanswer}
%
% This is much simpler.
%
%    \begin{macrocode}
\let\skipanswer\ignore
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\answers}
%
% The |\answers| macro closes the file, makes sure that future
% \env{exercise}s with answers cause an error, and reads in the file.
%
%    \begin{macrocode}
\def\answers{%
  \@ifnextchar[{\answers@i\input}{\answers@i\@input[\ex@ansfilename]}%
}
\def\answers@i#1[#2]{%
  \immediate\closeout\ex@ansfile%
  \global\let\answrite\exerr@toolate%
  \ex@withext{#1}{#2}{ans}%
}
\def\q@delim{\q@delim}
\def\ex@withext#1#2#3{%
  \edef\next@##1{\noexpand\ex@ext@i{##1}{#2}{#3}#2.\noexpand\q@delim}%
  \next@{#1}%
}
\def\ex@ext@i#1#2#3#4.#5\q@delim{%
  \ifx\q@delim#5\q@delim\def\next@{#1{#2.#3}}%
  \else\def\next@{#1{#2}}\fi%
  \next@%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{doanswer}
%
% A very simple environment.  We set the exercise number in bold and then
% just write the text.
%
%    \begin{macrocode}
\def\doanswer#1{%
  \exfix%
  \trivlist\advance\itemindent\labelsep%
  \item[\textbf{#1}]%
}
\let\enddoanswer\endtrivlist
%    \end{macrocode}
% \end{environment}
%
% \subsection{Lists inside paragraphs}
%
% \begin{environment}{parlist}
%
% The \env{parlist} environment is a trimmed-down version of a normal list.
% We todge the |\item| command, make |\list| and |\trivlist| make errors, and
% do various normal list things.
%
%    \begin{macrocode}
\def\parlist#1#2{%
  \let\@trivlist\exerr@parlist%
  \def\@itemlabel{#1}%
  \let\makelabel\relax%
  \@nmbrlistfalse%
  #2%
  \let\item\pl@item%
  \ignorespaces%
}
%    \end{macrocode}
% \end{environment}
%
% \begin{macro}{\pl@item}
%
% This is the implementation of |\item| within a \env{parlist}.  The main
% interesting point is the game with boxes, which has the objective of
% extracting the text of the item, together with any style changes set by
% |\makelabel|, but without any stupid bits of glue, or |\llap| or anything
% like that.
%
%    \begin{macrocode}
\def\pl@item{\@ifnextchar[\pl@item@i{\pl@item@i[\@itemlabel]}}
\def\pl@item@i[#1]{%
  \if@nmbrlist\refstepcounter{\@listctr}\fi%
  \setbox\z@\hbox{\makelabel{\global\setbox\@ne\hbox{#1}}}%
  \ifvmode\leavevmode\else\unskip\hskip1em\fi\box\@ne~\ignorespaces%
}
%    \end{macrocode}
% \end{macro}
%
% \begin{macro}{\useparlist}
%
% We just set the \env{list} environment to use \env{parlist}.
%
%    \begin{macrocode}
\def\useparlist{\let\list\parlist\let\endlist\relax}
%    \end{macrocode}
% \end{macro}
%
% \begin{environment}{parenum}
%
% Very simple, this.  Note that we don't run |\endenumerate|, because that's
% |\let| to |\endlist|.
%
%    \begin{macrocode}
\def\parenum{\useparlist\enumerate}
\let\endparenum\endparlist
%    \end{macrocode}
% \end{environment}
%
% \subsection{Errors}
%
%    \begin{macrocode}
\def\exerr@toolate{%
  \PackageError{exercise}{Too late now for \string\answrite}{%
    You can't write answers after you've read the file in.  I've^^J%
    ignored the text you attempted to write.  This is why answers^^J%
    go at the end of a book!%
  }%
}
\def\exerr@parlist{%
  \PackageError{exercise}{You can't nest a `list' inside a `parlist'.}{%
    I've found a `list' or `trivlist' environment nested inside^^J%
    a `parlist'.  This isn't allowed.  You're probably doomed now.%
  }%
}
%</package>
%    \end{macrocode}
%
% Done.
%
% \hfill Mark Wooding, \today
%
% \Finale
%
\endinput
