% \begin{meta-comment} % % $Id: exercise.dtx,v 1.1 2002/02/03 20:49:03 mdw Exp $ % % Exercises % % (c) 2001 Mark Wooding % %----- Revision history ----------------------------------------------------- % % $Log: exercise.dtx,v $ % Revision 1.1 2002/02/03 20:49:03 mdw % Checkin for new build system. % % % \end{meta-comment} % % \begin{meta-comment} %% %% exercise package -- useful macros for setting exercises with answers %% Copyright (c) 2001 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>\NeedsTeXFormat{LaTeX2e} %<+package>\ProvidesPackage{exercise} %<+package> [2001/09/21 1.0 Exercies with answers] % \end{meta-comment} % % \CheckSum{236} %% \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 \mdwdoc % % % \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} % % \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{""}{""}"}. Then, each |\answer| % command checks to see if \ has changed since last time, and if it % has, it does \, 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} % % \implementation % % %^^A------------------------------------------------------------------------- % \section{Implementation} % % \begin{macrocode} %<*package> % \end{macrocode} % % \subsection{Initialization} % % The \textsf{within} option is handled by the \package{keyval} package. % % \begin{macrocode} \RequirePackage{keyval} % \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 \define@key{ex}{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{keyval} kit to parse an option % string. % % \begin{macrocode} \def\ex@opts{\setkeys{ex}} % \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}{\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{% \immediate\closeout\ex@ansfile% \global\let\answrite\exerr@toolate% \input{\ex@ansfilename}% } % \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.% }% } % % \end{macrocode} % % Done. % % \hfill Mark Wooding, \today % % \Finale % \endinput