summaryrefslogtreecommitdiff
path: root/Master/texmf-dist/source/latex/probsoln/probsoln.dtx
diff options
context:
space:
mode:
Diffstat (limited to 'Master/texmf-dist/source/latex/probsoln/probsoln.dtx')
-rw-r--r--Master/texmf-dist/source/latex/probsoln/probsoln.dtx2932
1 files changed, 2316 insertions, 616 deletions
diff --git a/Master/texmf-dist/source/latex/probsoln/probsoln.dtx b/Master/texmf-dist/source/latex/probsoln/probsoln.dtx
index b15dc024005..a92e37f6598 100644
--- a/Master/texmf-dist/source/latex/probsoln/probsoln.dtx
+++ b/Master/texmf-dist/source/latex/probsoln/probsoln.dtx
@@ -1,12 +1,16 @@
%\iffalse
% probsoln.dtx generated using makedtx version 0.94b (c) Nicola Talbot
% Command line args:
-% -src "(.+)\.(sty)=>\1.\2"
-% -doc "manual.tex"
+% -macrocode ".*\.tex"
+% -setambles ".*\.tex=>\nopreamble\nopostamble"
+% -comment ".*\.tex"
+% -src "(.+\.sty)\Z=>\1"
+% -src "(.+\.tex)\Z=>\1"
+% -doc "probsoln-manual.tex"
% -author "Nicola Talbot"
% -dir "source"
% probsoln
-% Created on 2007/8/21 16:58
+% Created on 2008/8/27 14:19
%\fi
%\iffalse
%<*package>
@@ -29,49 +33,96 @@
%\fi
% \iffalse
% Doc-Source file to use with LaTeX2e
-% Copyright (C) 2007 Nicola Talbot, all rights reserved.
+% Copyright (C) 2008 Nicola Talbot, all rights reserved.
% \fi
% \iffalse
%<*driver>
-\documentclass{ltxdoc}
+\documentclass[a4paper]{ltxdoc}
\usepackage[colorlinks,
bookmarks,
hyperindex=false,
- pdfauthor=Nicola Talbot,
- pdftitle={probsoln.sty : a LaTeX2e package to help create problem sheets}]{hyperref}
+ pdfauthor={Nicola L.C. Talbot},
+ pdftitle={probsoln: creating problem sheets optionally with solutions}]{hyperref}
+\usepackage{color}
+\usepackage{probsoln}
+\RecordChanges
+\PageIndex
+\CheckSum{886}
-\newcommand{\sty}[1]{\textsf{#1}}\newcommand{\env}[1]{\textsf{#1}}
-\newcommand{\cmddef}[1]{\hypertarget{#1}{\cmdname{#1}}}
-\newcommand{\cmdlink}[1]{\hyperlink{#1}{\cmdname{#1}}}
-\newcommand{\problabel}[2]{\hypertarget{#1}{\texttt{#2}}}
-\newcommand{\probref}[1]{\hyperlink{#1}{\texttt{#1}}}
-\newcommand{\cmdname}[1]{\cs{#1}}
- %hyperindex conflicts with doc
- %(end up with |usage|hyperpage in indexentry)
\renewcommand{\usage}[1]{\textit{\hyperpage{#1}}}
\renewcommand{\main}[1]{\hyperpage{#1}}
\newcommand{\see}[2]{\emph{see} #1}
\makeatletter
\def\index@prologue{\section*{Index}}
\makeatother
-\CheckSum{499}
-\OnlyDescription
+\CodelineNumbered
+\newcommand{\dq}[1]{``#1''}
+\definecolor{defbackground}{rgb}{0.8,1,1}
+
+\newsavebox\defsbox
+\newlength\defwidth
+\newenvironment{definition}{%
+\setlength{\fboxsep}{4pt}\setlength{\fboxrule}{1.25pt}%
+\begin{lrbox}{\defsbox}%
+\setlength\defwidth\linewidth
+\addtolength\defwidth{-2\fboxrule}%
+\addtolength\defwidth{-2\fboxsep}%
+\begin{minipage}{\defwidth}\flushleft
+}{%
+\end{minipage}
+\end{lrbox}%
+\vskip10pt
+\noindent
+\fcolorbox{black}{defbackground}{\usebox\defsbox}%
+\vskip10pt
+}
+
+\newlength\boxlength
+\newsavebox\importantbox
+\newenvironment{important}{%
+\setlength{\fboxrule}{4pt}%
+\setlength\boxlength{\linewidth}%
+\addtolength\boxlength{-2\fboxsep}%
+\addtolength\boxlength{-2\fboxrule}%
+\begin{lrbox}{\importantbox}%
+\begin{minipage}{\boxlength}%
+}{\end{minipage}\end{lrbox}%
+\par\vskip10pt\noindent
+\fcolorbox{red}{white}{\usebox{\importantbox}}\par\vskip10pt}
-\PageIndex
-\begin{document}
-\DocInput{probsoln.dtx}
+\newcommand*{\ics}[1]{\cs{#1}\SpecialMainIndex{#1}}
+
+\newcommand{\pkgopt}[1]{\textsf{#1}\index{package options>#1=\textsf{#1}|hyperpage}}
+\newcommand*{\sty}[1]{\textsf{#1}}
+\newcommand*{\isty}[1]{\sty{#1}\index{#1 package=\sty{#1} package|hyperpage}}
+\newcommand*{\env}[1]{\textsf{#1}}
+\newcommand{\ienv}[1]{\env{#1}\index{#1 environment=\env{#1} environment|hyperpage}}
+\newcommand*{\bool}[1]{\textsf{#1}\index{#1 boolean variable=\textsf{#1} boolean variable|hyperpage}}
+\newcommand{\csdef}[1]{\cs{#1}}
+
+
+\begin{document}\DocInput{probsoln.dtx}
\end{document}
%</driver>
%\fi
-% \title{probsoln.sty v2.04: \LaTeXe\ Package to help create problem sheets}
-% \author{Nicola L.C. Talbot}
-% \date{21st August 2007}
+%\MakeShortVerb{"}
+%\DeleteShortVerb{\|}
+%
+% \title{probsoln v3.0: creating problem sheets optionally with solutions}
+% \author{Nicola L.C. Talbot\\[10pt]
+%School of Computing Sciences\\
+%University of East Anglia\\
+%Norwich. Norfolk\\
+%NR4 7TJ. United Kingdom.\\
+%\url{http://theoval.cmp.uea.ac.uk/~nlct/}}
+%
+% \date{26th August 2008}
% \maketitle
-% \tableofcontents
+%\tableofcontents
%
% \section{Introduction}
%The \sty{probsoln} package is designed for teachers or
@@ -91,466 +142,635 @@
%printed. In this way, one file can either produce the
%student's version or the teacher's version.
%
-%\section{Package Options}
+%\section{Package Options}\label{sec:pkgopt}
%The following options may be passed to this package:
-%\begin{center}
-%\begin{tabular}{@{\ttfamily}ll}
-%answers & Show the answers\\
-%noanswers & Don't show the answers (default)
-%\end{tabular}
-%\end{center}
-%
-%\section{Creating a New Problem}
-%\DescribeMacro{\newproblem}
-%\cmddef{newproblem}\verb|[|\meta{nargs}\verb/]{/\meta{label}\verb!}{!\meta{problem}\verb+}{+\meta{solution}\verb=}=\\[10pt]
-%A new problem is defined using the command
-%\cmdname{newproblem}. This does not print anything,
-%but merely stores the problem. As from version 2.03, there is also
-%a starred version of this command for problems without a solution
-%(for example, essay style questions):\\[10pt]
-%\DescribeMacro{\newproblem*}
-%\cmddef{newproblem*}\verb|[|\meta{nargs}\verb/]{/\meta{label}\verb!}{!\meta{problem}\verb+}+\\[10pt]
-%The argument \meta{label} is
-%a unique string that is assigned to this problem so that it
-%can be used later. The argument \meta{problem} is normal
-%\LaTeX\ code that should be used to typeset the problem.
-%The argument \meta{solution} is normal \LaTeX\ code that
-%should be used to typeset the solution, if required. For
-%example, the following defines a problem with the label
-%\problabel{quaddiff}{quaddiff}:
+%\begin{description}
+%\item[\pkgopt{answers}] Show the answers
+%\item[\pkgopt{noanswers}] Don't show the answers (default)
+%\item[\pkgopt{draft}] Display the label and dataset name when a problem is used
+%\item[\pkgopt{final}] Don't display label and dataset name when a problem is used
+%\end{description}
+%
+%\section{Showing and Hiding Solutions}\label{sec:showanswers}
+%
+%In addition to the \pkgopt{answers} and \pkgopt{noanswers} package
+%options, it is also possible to show or suppress the solutions
+%using \DescribeMacro{\showanswers}\cs{showanswers} and
+%\DescribeMacro{\hideanswers}\cs{hideanswers}, respectively.
+%The boolean variable \bool{showanswers} determines whether the
+%answers should be displayed. You can use this value with the
+%\isty{ifthen} package to specify different text depending on
+%whether the solutions should be displayed. For example:
+%\begin{verbatim}
+%Assignment 1\ifthenelse{\boolean{showanswers}}{ (Solution Sheet)}{}
+%\end{verbatim}
+%Alternatively you can use \ics{ifshowanswers}\ldots\cs{else}\ldots
+%\cs{fi}:
+%\begin{verbatim}
+%Assignment 1\ifshowanswers\space (Solution Sheet)\fi
+%\end{verbatim}
+%
+%For longer passages, you can use the environments \DescribeEnv{onlyproblem}\env{onlyproblem}
+%and \DescribeEnv{onlysolution}\env{onlysolution}. For example:
+%\begin{verbatim}
+%\begin{onlyproblem}%
+%What is the derivative of $f(x) = x^2$?
+%\end{onlyproblem}%
+%\begin{onlysolution}%
+%$f'(x) = 2x$
+%\end{onlysolution}
+%\end{verbatim}
+%The above will only display the question if \bool{showanswers}
+%is false and will only display the solution if \bool{showanswers}
+%is true. If you want the question to appear in the answer
+%sheet as well as the solution, then don't put the question in
+%the \env{onlyproblem} environment:
%\begin{verbatim}
-% \newproblem{quaddiff}{%
-% %This is the problem
-% \begin{displaymath}
-% f(x) = x^2 + 3x + 4
-% \end{displaymath}
-% }{%
-% %This is the solution
-% \begin{displaymath}
-% f'(x) = 2x + 3
-% \end{displaymath}
-% }
+%What is the derivative of $f(x) = x^2$?
+%\begin{onlysolution}%
+%Solution: $f'(x) = 2x$
+%\end{onlysolution}
%\end{verbatim}
-%The following is an essay question, so doesn't come with a solution:
+%\begin{important}
+%You can't use verbatim text in the body of the
+%\ienv{onlyproblem} or \ienv{onlysolution} environments.
+%If you need verbatim-like text, then try packages such as
+%\isty{alltt}. Remember that you also can't use verbatim
+%text in command arguments.
+%\end{important}
+%
+%\section{General Formatting Commands}\label{sec:formatting}
+%
+%The commands and environments described in this section are
+%provided to assist formatting problems and their solutions.
+%\DescribeEnv{solution}
+%\begin{definition}
+%\verb|\begin{solution}|\meta{text}\verb|\end{solution}|
+%\end{definition}
+%This is equivalent to
+%\verb|\par\noindent\textbf{\solutionname}:|\meta{text}
+%where \DescribeMacro{\solutionname}\cs{solutionname} defaults
+%to \dq{Solution}. Note that you must place the \env{solution}
+%environment inside the \ienv{onlysolution} environment or
+%between \ics{ifshowanswers}\ldots\cs{fi} to ensure that it
+%is suppressed when the solutions are not wanted. (See
+%\autoref{sec:showanswers}.)
+%
+%
+%Note that the \sty{probsoln} package will only define the
+%\env{solution} environment if it is not already defined.
+%
+%\DescribeEnv{textenum}
+%\begin{definition}
+%\verb|\begin{textenum}|\ldots\verb|\end{textenum}|
+%\end{definition}
+%The \env{textenum} environment is like the \ienv{enumerate}
+%environment but is in-line. It uses the same counter that the
+%\env{enumerate} environment would use at that level so the
+%question can be compact but the answer can use \env{enumerate}
+%instead. For example:
%\begin{verbatim}
-%\newproblem*{inheritance}{Describe what is meant by the term
-%\emph{inheritance} in object-oriented programming. Use examples.}
+%\begin{onlyproblem}%
+%Differentiate the following:
+%\begin{textenum}
+%\item $f(x)=2^x$;
+%\item $f(x)=\cot(x)$
+%\end{textenum}
+%\end{onlyproblem}
+%\begin{onlysolution}
+%\begin{enumerate}
+%\item
+%\begin{align*}
+%f(x) &= 2^x = \exp(\ln(x^2)) =\exp(2\ln(x))\\
+%f'(x) &= \exp(2\ln(x))\times \frac{2}{x}\\
+% &= f(x)\frac{2}{x}
+%\end{align*}
+%\item
+%\begin{align*}
+%f(x) &= \cot(x) = (\tan(x))^{-2}\\
+%f'(x) &= -(\tan(x))^{-2}\times\sec^2(x)\\
+%&=-\csc^2x
+%\end{align*}
+%\end{enumerate}
+%\end{onlysolution}
%\end{verbatim}
+%In this example, the items in the question are brief, so an
+%\ienv{enumerate} environment would result in a lot of
+%unnecessary white space,
+%but the answers require more space, so an \env{enumerate}
+%environment is more appropriate. Since the \ienv{textenum}
+%environment uses the same counters as the \env{enumerate}
+%environment, the question and answer sheets use consistent
+%labelling. Note that there are other packages available on
+%CTAN that you can use to create in-line lists. Check the
+%\href{http://www.tex.ac.uk/tex-archive/help/Catalogue/bytopic.html\#enumeration}{TeX Catalogue} for
+%further details.
%
-%The optional argument \meta{nargs} specifies the number of
-%parameters this problem will take. By default this value is
-%0, but any value from 1 to 9 may be used. Each parameter is
-%referred to by \verb|#1|, \verb/#2/, \ldots, \verb!#9!.
-%For example, the following problem, labelled \problabel{sindiff}{sindiff},
-%takes one parameter:
+%\DescribeMacro{\correctitem}\DescribeMacro{\incorrectitem}
+%\begin{definition}
+%\csdef{correctitem}\\
+%\csdef{incorrectitem}
+%\end{definition}
+%You can use the commands \cs{correctitem} and \cs{incorrectitem}
+%in place of \ics{item}. If the solutions are suppressed, these
+%commands behave in the same way as \cs{item}, otherwise they
+%format the item label using one of the commands:
+%\DescribeMacro{\correctitemformat}\DescribeMacro{\incorrectitemformat}
+%\begin{definition}
+%\csdef{correctitemformat}\marg{label}\\
+%\csdef{incorrectitemformat}\marg{label}
+%\end{definition}
+%For example:
%\begin{verbatim}
-%\newproblem[1]{sindiff}{%
+%Under which of the following functions does $S=\{a_1,a_2\}$
+%become a probability space?
+%\begin{enumerate}
+%\incorrectitem $P(a_1)=\frac{1}{3}$, $P(a_2)=\frac{1}{2}$
+%\correctitem $P(a_1)=\frac{3}{4}$, $P(a_2)=\frac{1}{4}$
+%\correctitem $P(a_1)=1$, $P(a_2)=0$
+%\incorrectitem $P(a_1)=\frac{5}{4}$, $P(a_2)=-\frac{1}{4}$
+%\end{enumerate}
+%\end{verbatim}
+%
+%\section{Defining a Problem}\label{sec:defproblem}
+%
+%It is possible to construct a problem sheet with solutions using
+%the commands described in the previous sections, however it is
+%also possible to define a set of problems for later use. In this
+%way you can create an external file containing many problems some
+%or all of which can be loaded and used in a document. The
+%\sty{probsoln} package has a default data set labelled
+%\dq{default} in which you can store problems or you can create
+%multiple data sets. You can then iterate through each problem
+%in a problem set. You can use a previously defined problem more
+%than once, which means that by judicious use of \ienv{onlyproblem},
+%\ienv{onlysolution} or the \bool{showanswers} boolean variable
+%in conjunction with \ics{showanswers} and \ics{hideanswers},
+%you can print the solutions in a different location to the
+%questions (for example in an appendix).
+%
+%\DescribeEnv{defproblem}
+%\begin{definition}
+%\verb|\begin{defproblem}|\oarg{n}\marg{label}\meta{definition}\verb|\end{defproblem}|
+%\end{definition}
+%This defines the problem whose label is given by \meta{label}.
+%The label must be unique for a given data set and should not
+%contain active characters. (Active characters include the special
+%characters such as \$ and \&, but some packages may make other
+%symbols active. For example, the \isty{ngerman} and \isty{babel}
+%packages make certain punctuation active. Check the relevant
+%package documentation for details.)
+%
+%If \env{defproblem} occurs in the document or is included via
+%\cs{input} or \cs{include}, then the problem will be added to
+%the default data set. If \env{defproblem} occurs in an external
+%file that is loaded using one of the commands defined in
+%\autoref{sec:load} then the problem will be added to
+%the specified data set.
+%
+%The contents of the \env{defproblem} environment should be the
+%text that defines the problem. This may include any of the
+%commands defined in
+%\autoref{sec:showanswers} and \autoref{sec:formatting}.
+%
+%The problem may optionally take \meta{n} arguments (where
+%\meta{n} is from 0 to 9). The arguments can be referenced
+%in the definition via \texttt{\#1},\ldots,\texttt{\#9}.
+%If \meta{n} is omitted then the problem doesn't take any
+%arguments.
+%The following example defines a problem with one argument:
+%\begin{verbatim}
+%\begin{defproblem}[1]{diffsin}
+%Differentiate $f(x)=\sin(#1x)$.
+%\begin{onlysolution}%
+%\begin{solution}
+%$f'(x) = #1\cos(#1x)$
+%\end{solution}
+%\end{onlysolution}
+%\end{defproblem}
+%\end{verbatim}
+%
+%\DescribeMacro{\newproblem}
+%\begin{definition}
+%\csdef{newproblem}\oarg{n}\marg{label}\marg{problem}\marg{solution}
+%\end{definition}
+%This is a shortcut command for:
+%\begin{ttfamily}\obeylines
+%\cs{begin}\{defproblem\}\oarg{n}\marg{label}\%
+%\meta{problem}\%
+%\cs{begin}\{onlysolution\}\%
+%\cs{begin}\{solution\}\%
+%\meta{solution}\%
+%\cs{end}\{solution\}\%
+%\cs{end}\{onlysolution\}\%
+%\cs{end}\{defproblem\}
+%\end{ttfamily}
+%For example:
+%\begin{verbatim}
+%\newproblem[1]{diffsin}{%
%\(f(x) = \sin(#1x)\)
%}{%
%\(f'(x) = #1\cos(#1x)\)
%}
%\end{verbatim}
+%is equivalent to
+%\begin{verbatim}
+%\begin{defproblem}[1]{diffcos}%
+%\(f(x) = \cos(#1x)\)
+%\begin{onlysolution}%
+%\begin{solution}%
+%\(f'(x) = -#1\sin(#1x)\)
+%\end{solution}%
+%\end{onlysolution}%
+%\end{defproblem}
+%\end{verbatim}
+%(In this example, the argument will need to be a positive number
+%to avoid a double minus in the answer. If you want to perform
+%floating point arithmetic on the arguments, then try the
+%\isty{fp} package.)
+%
+%\DescribeMacro{\newproblem*}
+%\begin{definition}
+%\csdef{newproblem*}\oarg{n}\marg{label}\marg{definition}
+%\end{definition}
+%This is a shortcut for:
+%\begin{ttfamily}\obeylines
+%\cs{begin}\{defproblem\}\oarg{n}\marg{label}\%
+%\meta{definition}\%
+%\cs{end}\{defproblem\}
+%\end{ttfamily}
+%
+%\begin{important}
+%Verbatim text must not be used in the contents of \ienv{defproblem}
+%or in any of the arguments to \cs{newproblem} or
+%\cs{newproblem*}. If you need verbatim-like text consider using
+%\cs{texttt} or the \isty{alltt} package.
+%\end{important}
+%
+%\section{Using a Problem}\label{sec:useproblem}
%
-%The \probref{quaddiff} problem shown above can be made more
-%generic by using parameters\problabel{diff:quad}{}:
+%Once you have defined a problem using \ienv{defproblem} or
+%\cs{newproblem} (see
+%\autoref{sec:defproblem}), you can later display the problem
+%using:
+%\DescribeMacro{\useproblem}
+%\begin{definition}
+%\csdef{useproblem}\oarg{data set}\marg{label}\marg{arg$_1$}\ldots\marg{arg$_N$}\end{definition}
+%where \meta{data set} is the name of the data set that contains
+%the problem (the default data set is used if omitted),
+%\meta{label} is the label identifying the required problem and
+%\meta{arg$_1$}, \ldots, \meta{arg$N$} are the arguments to pass to the problem, if the problem was
+%defined to have arguments (where $N$ is the number of arguments specified when the problem was defined).
+%
+%For example, in the previous section the problem \texttt{diffcos}
+%was defined to have one argument, so it can be used as follows:
%\begin{verbatim}
-%\newcount\ctr
-%\newproblem[3]{diff:quad}{%
-%\(f(x) =
-%\ifnum#1=0
-%\else
-%\ifnum#1=1\else#1\fi x^2
-%\fi
-%\ifnum#2=0
-%\else
-%\ifnum#2>0 \ifnum#1=0 \else + \fi \fi
-%\ifnum#2=1\else#2\fi x
-%\fi
-%\ifnum#3=0
-%\else
-%\ifnum#3>0 \ifnum#2=0 \ifnum#1=0 \else + \fi \else + \fi\fi
-%#3
-%\fi\)
-%}{%
-%\(f'(x) =
-%\ifnum#1=0
-%\else
-%\ctr=2
-%\multiply\ctr by #1
-%\the\ctr x
-%\fi
-%\ifnum#2=0
-%\else
-%\ifnum#2>0 \ifnum#1=0 \else + \fi \fi
-%#2
-%\fi
-% % print 0 if both #1 and #2 are 0
-%\ifnum#1=0 \ifnum#2=0 0 \fi\fi
-%\)
-%}
+%\useproblem{diffcos}{3}
%\end{verbatim}
-%The three parameters correspond to the coefficients. Note
-%that they must all be integers since \TeX\ only performs
-%integer arithmetic.
-%
-%\section{Creating a Database}
-%
-%To generate a database, simply create a \texttt{.tex} file
-%where all the problems are defined using \cmdlink{newproblem} or
-%\cmdlink{newproblem*},
-%and either \cmdname{input} it at the start of your document if
-%you want to use specific problems (see Section~\ref{sec:useprob}), or pass it to
-%\cmdname{selectrandomly} (see Section~\ref{sec:selran}). This package
-%comes with some sample databases, along with some sample documents
-%that use these databases.
-%
-%\section{Displaying a Problem}
-%\label{sec:useprob}
-% \DescribeMacro{\useproblem}
-%\cmddef{useproblem}\verb|{|\meta{label}\verb/}/\\[10pt]
-%Once a problem has been defined using \cmdlink{newproblem}, it
-%can be typeset using the command \cmdname{useproblem}. If the
-%problem was defined to take arguments, the arguments to the
-%problem should come after the label. In the case of the
-%\probref{sindiff} example above, the command
-%\verb|\useproblem{sindiff}{2}| would produce the following:\\[10pt]
-% $f(x) = \sin(2x)$ \paragraph{Solution:} $f'(x) = 2\cos(2x)$\\[10pt]whereas the command \verb|\useproblem{diff:quad}{3}{0}{-2}| would produce:\\[10pt]
-% $f(x) = 3x^2 - 2$ \paragraph{Solution:} $f'(x) = 6x$\vspace{10pt}
-%
-%Suppose all the above problems are defined in the file
-%\texttt{probs.tex}, then the following code will create a
-%problem sheet with four questions in it:
+%This will be equivalent to:
%\begin{verbatim}
-%\documentclass{article}
+%\(f(x) = \cos(3x)\)
+%\begin{onlysolution}%
+%\begin{solution}%
+%\(f'(x) = -3\sin(3x)\)
+%\end{solution}%
+%\end{onlysolution}%
+%\end{verbatim}
%
-%\usepackage{probsoln}
-%\input{probs}
+%\section{Loading Problems From External Files}\label{sec:load}
%
-%\begin{document}
-%Differentiate the following functions with respect to $x$:
-%\begin{enumerate}
-%\item \useproblem{quaddiff}
-%\item \useproblem{sindiff}{4}
-%\item \useproblem{diff:quad}{2}{3}{1}
-%\item \useproblem{diff:quad}{0}{1}{2}
-%\end{enumerate}
-%\end{document}
-%\end{verbatim}
-%The answer sheet can then be generated by passing the option
-%\texttt{answers} to the \texttt{probsoln} package.
+%You can store all your problem definitions (see
+%\autoref{sec:defproblem}) in an external file.
+%These problems can all be appended to the default data set by
+%including the file via \ics{input} or they can be appended
+%to other data sets using one of the commands described below.
+%Once you have loaded all the required problems, you can
+%iterate through the data sets using the commands described
+%in \autoref{sec:foreach}. Note that the commands below
+%will create a new data set, if the named data set doesn't
+%exist.
%
-%\section{Selecting All Problems}
+%\DescribeMacro{\loadallproblems}
+%\begin{definition}
+%\csdef{loadallproblems}\oarg{data set}\marg{filename}
+%\end{definition}
+%This will load all problems defined in \meta{filename} and
+%append them to the specified data set, in the order in which
+%they are defined in the file. If \meta{data set} is
+%omitted, the default data set will be used. If \meta{data set}
+%doesn't exist, it will be created.
%
-%To select all problems defined in a database, in the order in
-%which they were defined, use the command:
-%\DescribeMacro{\selectallproblems}
-%\cmddef{selectallproblems}\verb|{|\meta{filename}\verb/}/
-%For example, suppose the problems are defined in the file
-%\texttt{easy.tex}, then the following will create a problem sheet
-%which uses all these problems:
+%\DescribeMacro{\loadselectedproblems}
+%\begin{definition}
+%\csdef{loadselectedproblems}\oarg{data set}\marg{labels}\marg{filename}
+%\end{definition}
+%This is like \cs{loadproblems}, but only those problems whose
+%label is listed in the comma-separated list \meta{labels} are
+%loaded. For example, if I have some problems defined in the
+%file \texttt{derivatives.tex}, then
%\begin{verbatim}
-%\documentclass[a4paper]{article}
+%\loadselectedproblems{diffsin,diffcos}{derivatives}
+%\end{verbatim}
+%will only load the problems whose labels are \texttt{diffsin}
+%and \texttt{diffcos}, respectively. All the other problems in
+%the file will remain undefined.
%
-%\usepackage{probsoln}
+%\DescribeMacro{\loadrandomproblems}
+%\begin{definition}
+%\csdef{loadrandomproblems}\oarg{data set}\marg{n}\marg{filename}
+%\end{definition}
+%This randomly loads \meta{n} problems from \meta{filename} and
+%adds them to the given data set. If \meta{data set} is omitted,
+%the default data set is assumed. Note that the problems will be
+%added to the data set in a random order, not in the order in
+%which they were defined. There must be at least \meta{n} problems
+%defined in \meta{filename}.
%
-%\begin{document}
-%Differentiate the following functions:
+%\begin{important}
+%It is generally not a good idea to place anything in
+%\meta{filename} that is not inside the body of \ienv{defproblem}
+%or in the arguments to \ics{newproblem} or \ics{newproblem*}.
+%All the commands in this section input the external file within
+%a local scope, so commands definitions would need to be made
+%global to have any effect. In addition, \cs{loadrandomproblems}
+%has to load each file twice, which means that anything outside
+%a problem definition will be parsed twice.
+%\end{important}
+%
+%
+%\section{Iterating Through Datasets}\label{sec:foreach}
+%
+%Once you have defined all your problems for a given data set,
+%you can use an individual problem with \ics{useproblem}
+%(see \autoref{sec:useproblem}) but it is more likely that you will
+%want to iterate through all the problems so that you don't need
+%to remember the labels of all the problems you have defined.
+%
+%\DescribeMacro{\foreachproblem}
+%\begin{definition}
+%\csdef{foreachproblem}\oarg{data set}\marg{body}
+%\end{definition}
+%This does \meta{body} for each problem in the given data set.
+%If \meta{data set} is omitted, the default data set is used.
+%Within \meta{body} you can use
+%\DescribeMacro{\thisproblem}\cs{thisproblem} to use the
+%current problem and \DescribeMacro{\thisproblemlabel}\cs{thisproblemlabel}
+%to access the current label. If the problem requires arguments,
+%you will be prompted for them, so if you want to use this
+%approach you will need to use \LaTeX\ in interactive mode. If
+%you do provide arguments, they will be stored in the event that
+%you need to iterate through the data set again. The
+%arguments will be included in \cs{thisproblem}, so you only
+%need to use \cs{thisproblem} without having to specify
+%\ics{useproblem}. For example, to iterate through all problems
+%in the default data set:
+%\begin{verbatim}
%\begin{enumerate}
-%\selectallproblems{easy}
+%\foreachproblem{\item\thisproblem}
%\end{enumerate}
-%\end{document}
%\end{verbatim}
%
-%\section{Selecting Problems at Random}
-%\label{sec:selran}
-% \DescribeMacro{\selectrandomly}
-%\cmddef{selectrandomly}\verb|{|\meta{filename}\verb/}{/\meta{n}\verb!}!\\[10pt]
-%The command \cmdname{selectrandomly} will select \meta{n}
-%problems that are defined in the file \meta{filename}. Each
-%problem is proceeded by
-%\DescribeMacro{\PSNitem}\cmddef{PSitem} which is
-%defined to be \cmdname{item}, so the command
-%\cmdname{selectrandomly} should occur within one of the
-%list-like environments, such as \texttt{enumerate}.
-%For example:
+%\DescribeMacro{\foreachdataset}
+%\begin{definition}
+%\csdef{foreachdataset}\marg{cmd}\marg{body}
+%\end{definition}
+%This does \meta{body} for each of the defined data sets. Within
+%\meta{body}, \meta{cmd} will be set to the name of the current
+%data set. For example, to display all problems in all data sets:
%\begin{verbatim}
%\begin{enumerate}
-%\selectrandomly{easy.tex}{4}
+%\foreachdataset{\thisdataset}{%
+%\foreachproblem[\thisdataset]{\item\thisproblem}}
%\end{enumerate}
%\end{verbatim}
-%will result in four numbered problems, selected at random
-%from the file \texttt{easy.tex}. (The \texttt{.tex} extension
-%may be omitted.) Each problem is followed by the command
-%\cmddef{endPSNitem} which by default does nothing.
-%
-%Multiple \cmdname{selectrandomly} commands may be used, however a
-%different file must be used each time. For
-%example:
+%
+%Suppose I have two external files called
+%\texttt{derivatives.tex} and \texttt{probspaces.tex} which
+%define problems using both \ienv{onlyproblem} and
+%\ienv{onlysolution} for example:
+%\begin{verbatim}
+%\begin{defproblem}{cosxsqsinx}%
+%\begin{onlyproblem}%
+%$y = \cos(x^2)\sin x$.%
+%\end{onlyproblem}%
+%\begin{onlysolution}%
+%\[\frac{dy}{dx} = -\sin(x^2)2x\sin x + \cos(x^2)\cos x\]
+%\end{onlysolution}%
+%\end{defproblem}
+%\end{verbatim}
+%I can write a document that creates two data sets, one for
+%the derivative problems and one for the problems about
+%probability spaces. I can then use \ics{hideanswers} and
+%iterate through the require data set to produce the problems.
+%Later, I can use \ics{showanswers} and iterate over all problems defined in both data
+%sets to produce the chapter containing all the answers. When
+%displaying the questions, I have taken advantage of the fact that
+%I can cross-reference items within an \ienv{enumerate} environment,
+%and redefined \ics{theenumi} to label the questions according to
+%the chapter. The cross-reference label is constructed from
+%the problem label and is referenced in the answer section to
+%ensure that the answers have the same label as the questions.
%\begin{verbatim}
-%\begin{enumerate}
-%\item Differentiate the following functions with respect to $x$:
+%\documentclass{report}
+%\usepackage{probsoln}
+%\begin{document}
+%\hideanswers
+%\chapter{Differentiation}
+%% randomly select 25 problems from derivatives.tex and add to
+%% the data set called 'deriv'
+%\loadrandomproblems[deriv]{25}{derivatives}
%
+%% Display the problems
+%\renewcommand{\theenumi}{\thechapter.\arabic{enumi}}
%\begin{enumerate}
-%\selectrandomly{samples/easy.tex}{3}
-%\selectrandomly{samples/args.tex}{1}
+%\foreachproblem[deriv]{\item\label{prob:\thisproblemlabel}\thisproblem}
%\end{enumerate}
+%% You may need to change \theenumi back here
%
-%\selectrandomly{samples/implicit.tex}{1}
-%\selectrandomly{samples/1stprncpl.tex}{1}
+%\chapter{Probability Spaces}
+%% randomly select 25 problems from probspaces.tex and add to
+%% the data set called 'spaces'
+%\loadrandomproblems[spaces]{25}{probspaces}
%
+%% Display the problems
+%\renewcommand{\theenumi}{\thechapter.\arabic{enumi}}
+%\begin{enumerate}
+%\foreachproblem[spaces]{\item\label{prob:\thisproblemlabel}\thisproblem}
%\end{enumerate}
-%\end{verbatim}
-%This will result in a total of 6 problems, numbered 1(a),
-%1(b), 1(c), 1(d), 2 and 3.
+%% You may need to change \theenumi back here
%
-%If a randomly selected problem requires arguments, a message
-%similar to the following will be displayed:
-%\begin{verbatim}
-%Problem diff:quad requires 3 argument(s), please specify (e.g. {5}{3}):
-%\end{verbatim}
-%Enter the required arguments, where each argument is
-%enclosed in braces (\{ \}).
+%\appendix
%
-%\section{Other Commands}
-%\DescribeMacro{\PSNrandseed}
-%The command \cmddef{PSNrandseed}\verb|{|\meta{n}\verb/}/ specifies
-%the seed for the random number generator. For example,
-%if you are using \cmdlink{selectrandomly},
-%\verb|\PSNrandseed{\year}| will produce a different set of
-%problems each year, whereas \verb|\PSNrandseed{\time}|
-%will produce a different set of problems each time you
-%\LaTeX\ the problem sheet (as long as you leave at least a
-%minute between runs.)
+%\chapter{Solutions}
+%\showanswers
+%\begin{itemize}
+%\foreachdataset{\thisdataset}{%
+%\foreachproblem[\thisdataset]{\item[\ref{prob:\thisproblemlabel}]\thisproblem}
+%}
+%\end{itemize}
%
-%\DescribeMacro{\random}
-%The command \cmddef{random}\verb|{|\meta{counter}\verb/}{/\meta{a}\verb!}{!\meta{b}\verb-}-
-%generates a random number from \meta{a} to \meta{b} and
-%stores it in the \LaTeX\ counter \meta{counter}. For example,
-%to select 2, 3 or 4 problems from the file
-%\texttt{implicit.tex}:
-%\begin{verbatim}
-%\newcounter{numproblems}
-%\begin{enumerate}
-%\random{numproblems}{2}{4}
-%\selectrandomly{implicit.tex}{\value{numproblems}}
-%\end{enumerate}
+%\end{document}
%\end{verbatim}
-%(Note the use of \cmdname{value}.)
%
-%This command can also be used to generate random values for
-%problems that take arguments. Consider the problem \probref{diff:quad}
-%defined earlier. Three counters can be defined to represent the
-%three coefficients:
+%
+%\section{Random Number Generator}\label{sec:random}
+%
+%This package provides a pseudo-random number generator that is used
+%by \ics{loadrandomproblems}.
+%
+%\DescribeMacro{\PSNrandseed}
+%\begin{definition}
+%\csdef{PSNrandseed}\marg{n}
+%\end{definition}
+%This sets the seed to \meta{n} which must be a non-zero integer.
+%For example, to generate a different set of random numbers
+%every time you \LaTeX\ your document,\footnote{assuming you
+%leave at least a minute between runs.} put the following in your
+%preamble:
%\begin{verbatim}
-%\newcounter{A}
-%\newcounter{B}
-%\newcounter{C}
+%\PSNrandseed{\time}
%\end{verbatim}
-%Random values can now be assigned to these counters:
+%or to generate a different set of random numbers every year you
+%\LaTeX\ your document:
%\begin{verbatim}
-%\random{A}{-5}{5}
-%\random{B}{-5}{5}
-%\random{C}{-5}{5}
+%\PSNrandseed{\year}
%\end{verbatim}
-%Finally, the problem can be used (note the use of \cmdname{arabic}):
-%\begin{verbatim}
-%\useproblem{diff:quad}{\arabic{A}}{\arabic{B}}{\arabic{C}}
-%\end{verbatim}
-%
-%\DescribeMacro{\doforrandN}%
-%The command
-%\cmddef{doforrandN}\verb|{|\meta{n}\verb/}{/\meta{cmd}\verb!}{!\meta{list}\verb+}{+\meta{text}\verb-}- will apply
-%\meta{text} for a random selection of \meta{n} items in the
-%comma separated \meta{list}. In each iteration the list
-%item is denoted by \meta{cmd}. For example, suppose you
-%have three files called \texttt{file1.tex},
-%\texttt{file2.tex} and \texttt{file3.tex}, and you want to
-%select 1 problem from two of the three files, then you can
-%do:
+%
+%\DescribeMacro{\PSNgetrandseed}
+%\begin{definition}
+%\csdef{PSNgetrandseed}\marg{register}
+%\end{definition}
+%This stores the current seed in the count register specified by
+%\meta{register}.
+%For example:
%\begin{verbatim}
-%\doforrandN{2}{\file}{file1,file2,file3}{\selectrandomly{\file}{1}}
+%\newcount\myseed
+%\PSNgetrandseed{\myseed}
%\end{verbatim}
-%Note that it is also possible to do
+%
+%\DescribeMacro{\PSNrandom}
+%\begin{definition}
+%\csdef{PSNrandom}\marg{register}\marg{n}
+%\end{definition}
+%Generates a random integer from 1 to \meta{n} and stores in
+%the count register specified by \meta{register}. For example,
+%the following generates an integer from 1 to 10 and stores it
+%in the register \cs{myreg}:
%\begin{verbatim}
-%\newcounter{numproblems}
-%\random{numproblems}{1}{3}
-%\selectrandomly{file\arabic{numproblems}}{1}
-%\random{numproblems}{1}{3}
-%\selectrandomly{file\arabic{numproblems}}{1}
+%\newcount\myreg
+%\PSNrandom{\myreg}{10}
%\end{verbatim}
-%however there is a possibility that the same file may be
-%selected twice which will cause an error.
-%
-%\DescribeMacro{\showanswers}
-%The command \cmddef{showanswers} will show the solutions from
-%that point on. May be localised by placing within a group.
-%
-%\DescribeMacro{\hideanswers}
-%The command \cmddef{hideanswers} will hide the solutions from
-%that point on. May be localised by placing within a group.
-%
-%The solution is placed inside the \DescribeEnv{solution}\env{solution}
-%environment. By default this environment simply does
-%\verb|\par\noindent\textbf{\solutionname:} | at the start, where
-%\DescribeMacro{\solutionname}\cmddef{solutionname}
-%has the value: Solution. See the file \texttt{sample3.tex}, which
-%comes with this package, for an illustration of how to
-%customise the way in which the randomly selected problems are
-%displayed. This sample file randomly selects multiple choice
-%problems stored in the file \texttt{tabmchoice.tex}, and displays them
-%in a longtable \env{environment}. As from version 2.03, the package
-%will not define this environment if another package or class file has
-%already defined it.
-%
-%\DescribeMacro{showanswers}
-%The boolean variable \texttt{showanswers} is defined to be
-%true if the answers are shown and false otherwise. You can
-%therefore do something like:
+%
+%\DescribeMacro{\random}
+%\begin{definition}
+%\csdef{random}\marg{counter}\marg{min}\marg{max}
+%\end{definition}
+%Generates a random integer from \meta{min} to \meta{max} and
+%stores in the given counter. For example, the following generates
+%a random number between 3 and 8 (inclusive) and stores it in
+%the counter \texttt{myrand}.
%\begin{verbatim}
-%\ifthenelse{\boolean{showanswers}}{\textbf{Solution Sheet}}{}
+%\newcounter{myrand}
+%\random{myrand}{3}{8}
%\end{verbatim}
-%and \textbf{Solution Sheet} will be printed only if the
-%answers are displayed. (For more information on
-%\cmdname{ifthenelse} and \cmdname{boolean} see the
-%documentation for the \texttt{ifthen} package by
-%David Carlisle.)
-%
-%The \texttt{showanswers} switch can also be used within the definition
-%of a problem, if you want the question to appear differently if the
-%solution is displayed. For example:
+%
+%\DescribeMacro{\doforrandN}
+%\begin{definition}
+%\csdef{doforrandN}\marg{n}\marg{cmd}\marg{list}\marg{text}
+%\end{definition}
+%Randomly selects \meta{n} values from the comma-separated list
+%given by \meta{list} and iterates through this subset. On
+%each iteration it sets \meta{cmd} to the current value and
+%does \meta{text}. For example, the following will load a
+%randomly selected problem from two of the listed files (where
+%\texttt{file1.tex}, \texttt{file2.tex} and \texttt{file3.tex}
+%are files containing at least one problem):
%\begin{verbatim}
-%\newproblem{mc:prod}{%
-%Which of the following is the derivative of $x\sin(x)$?
-%(Circle the correct answer.)
-%\ifthenelse{\boolean{showanswers}}{}%
-%{\begin{description}
-%\item[A] $\sin(x)$
-%\item[B] $x\cos(x)$
-%\item[C] $\sin(x) + x\cos(x)$
-%\end{description}
-%}}{%
-%\begin{description}
-%\item[A] $\sin(x)$
-%\item[B] $x\cos(x)$
-%\item[\textcircled{C}] $\sin(x) + x\cos(x)$ (product rule).
-%\end{description}
-%}
+%\doforrandN{2}{\thisfile}{file1,file2,file3}{%
+%\loadrandomproblems{1}{\thisfile}}
%\end{verbatim}
-%If the solutions are not displayed, the question will appear
-%as
-%\begin{description}
-%\item Which of the following is the derivative of
-%$x\sin(x)$? (Circle the correct answer.)
-%\begin{description}
-%\item[A] $\sin(x)$\item[B] $x\cos(x)$\item[C] $\sin(x) + x\cos(x)$\end{description}
-%\end{description}
-%otherwise it will appear as:
-%\begin{description}
-%\item Which of the following is the derivative of
-%$x\sin(x)$? (Circle the correct answer.)
-%\begin{description}
-%\item[A] $\sin(x)$\item[B] $x\cos(x)$\item[\textcircled{C}] $\sin(x) + x\cos(x)$ (product rule)\end{description}
-%\end{description}
%
-%\section{Troubleshooting}
-%\subsection{Unexpected Output}
-%\begin{itemize}
-%\item I have lots of blank space before the first problem when
-%using \cmdlink{selectrandomly}.
-%
-%This is probably because you have lots of extraneous white space
-%in your database. \cmdlink{selectrandomly} will input the entire
-%file, so any extra space will be included. Try commenting out the
-%extra space using \%.
-%\end{itemize}
-%
-%\subsection{Error Messages}
-%\begin{itemize}
-%\item
-%\begin{ttfamily}
-%! Package probsoln Error: Label \ldots\ already used.
-%\end{ttfamily}
%
-%Each label identifier used in \cmdlink{newproblem} must be
-%unique. Check to make sure you haven't used the same label
-%more than once. Also check to make sure you haven't
-%\cmdname{input}ed or randomly selected from the same file more
-%than once. (Or \cmdname{input}ed and randomly selected from
-%the same file.)
+%\section{Compatibility With Versions Prior to 3.0}
%
-%\item
-%\begin{ttfamily}
-%! Package probsoln Error: Label \ldots\ undefined.
-%\end{ttfamily}
+%Version 3.0 of the \sty{probsoln} package completely changed the
+%structure of the package, but the commands described in this
+%section have been provided to maintain compatibility with
+%earlier versions. The only problems that are likely to occur are
+%those where commands are contained within groups. This will
+%effect any commands that are contained in external files that are
+%outside of the arguments to \ics{newproblem} and \ics{newproblem*}.
+%However, since the external files had to be parsed twice in
+%order to load the problems, this shouldn't be an issue as adding
+%anything other than problem definitions in those files would
+%be problematic anyway.
%
-%You need to define a problem before you can use it. Check to
-%make sure you haven't mis-spelt it, and check to make sure you
-%have \cmdname{input}ed the file in which it is defined.
+%The other likely difference is where the random generator is
+%used in a group. This includes commands such as
+%\ics{selectrandomly}. For example, if your document contained
+%something like:
+%\begin{verbatim}
+%\begin{enumerate}
+%\selectrandomly{file1}{8}
%
-%\item
-%\begin{ttfamily}
-%! Package probsoln Error: Requested number too large.
-%\end{ttfamily}
+%\item Solve the following:
+%\begin{enumerate}
+%\selectrandomly{file2}{4}
+%\end{enumerate}
%
-%You have asked for more problems than are defined within the
-%specified file. All problems in that file will be selected.
+%\selectrandomly{file3}{2}
+%\end{enumerate}
+%\end{verbatim}
+%Then using versions prior to v3.0 will produce a different
+%set of random numbers since the second \cs{selectrandomly}
+%is in a different level of grouping. If you want to ensure
+%that the document produces exactly the same random set with
+%the new version as with the old version, you will need to
+%get and set the random number seed. For example, the above
+%would need to be modified so that it becomes:
+%\begin{verbatim}
+%\begin{enumerate}
+%\selectrandomly{file1}{8}
%
-%\item
-%\begin{ttfamily}
-%! Package probsoln Error: Can't randomly select \meta{n}
-%item(s)
-%\end{ttfamily}
+%\item Solve the following:
+%\newcount\oldseed
+%\PSNgetrandseed{\oldseed}
+%\begin{enumerate}
+%\selectrandomly{file2}{4}
+%\end{enumerate}
+%\PSNrandseed{\oldseed}
%
-%You have asked to randomly select \meta{n} items from a list
-%that has less than \meta{n} elements. For example, the
-%following will generate this error:
-%\begin{verbatim}
-%\doforrandN{10}{\file}{file1,file2,file3}{%
-%\selectrandomly{\file}{1}}
+%\selectrandomly{file3}{2}
+%\end{enumerate}
%\end{verbatim}
-%In this case the list, \texttt{file1,file2,file3} has only 3
-%elements, but the user has asked for 10 elements. If you type
-%`h' at the \LaTeX\ prompt it will tell you how many items it thinks
-%there are in the list. Remember that each item must be separated by a
-%comma.
%
-%\item
-%\begin{ttfamily}
-%! LaTeX Error: Lonely \cmdname{item}--perhaps missing list
-%environment.
+%\DescribeMacro{\selectrandomly}
+%\begin{definition}
+%\csdef{selectrandomly}\marg{filename}\marg{n}
+%\end{definition}
+%This is now equivalent to:
+%\begin{ttfamily}\obeylines
+%\{\cs{loadrandomproblems}\oarg{filename}\marg{n}\marg{filename}\}\%
+%\cs{foreachproblem}\oarg{filename}\marg{\cs{PSNitem}\cs{thisproblem}\cs{endPSNitem}}
%\end{ttfamily}
%
-%Each problem selected using \cmdlink{selectrandomly} is
-%proceeded by \cmdlink{PSNitem} which by default is defined
-%as \cmdname{item}, and should therefore be
-%placed in one of the list environments, such as
-%\texttt{enumerate}. Alternatively, redefine \cmdlink{PSNitem}.
+%\DescribeMacro{\selectallproblems}
+%\begin{definition}
+%\csdef{selectallproblems}\marg{filename}
+%\end{definition}
+%This is now equivalent to:
+%\begin{ttfamily}\obeylines
+%\{\cs{loadallproblems}\oarg{filename}\marg{filename}\}\%
+%\cs{foreachproblem}\oarg{filename}\marg{\cs{PSNitem}\cs{thisproblem}\cs{endPSNitem}}
+%\end{ttfamily}
%
-%\item I get an error when I put a command definition in my database
-%when using \cmdname{selectrandomly}.
+%Note that in both the above cases, a new data set is created
+%with the same name as the file name.
%
-%\cmdlink{selectrandomly} inputs the database twice, so any
-%command definition will be read twice, causing an error. You
-%can use the switch \cmdname{iffirstpass} to prevent the error. For
-%example:
-%\begin{verbatim}
-%\iffirstpass
-%\newcommand{\mycmd}{}
-%\fi
-%\end{verbatim}
-%It is generally not a good idea to put anything other than
-%\cmdlink{newproblem} commands within the database.
%
-%\end{itemize}
+% \StopEventually{\clearpage\phantomsection\addcontentsline{toc}{section}{Index}\PrintIndex}
%
-%\section{Contact Details}
-%Dr Nicola Talbot\\
-%School of Computing Sciences\\
-%University of East Anglia\\
-%Norwich. NR4 7TJ\\
-%\url{http://theoval.cmp.uea.ac.uk/~nlct/}
%
-%\StopEventually{\PrintIndex}
%
%\section{The Code}
%\iffalse
@@ -558,147 +778,641 @@
%<*probsoln.sty>
% \end{macrocode}
%\fi
-% At the start of the package, specify that the \LaTeXe\ format is
-% required. And specify the package provided.
+%\subsection{Package Definition}
+% This package requires \LaTeXe.
% \begin{macrocode}
\NeedsTeXFormat{LaTeX2e}
-\ProvidesPackage{probsoln}[2007/08/21 v2.04 Problems and their Solutions Package (NLCT)]
+% \end{macrocode}
+% Identify this package and version:
+% \begin{macrocode}
+\ProvidesPackage{probsoln}[2008/08/25 v3.0 (NLCT)]
+% \end{macrocode}
+% Required packages:
+% \begin{macrocode}
\RequirePackage{ifthen}
+\RequirePackage{substr}
+\RequirePackage{amsmath}
% \end{macrocode}
-% Define newif to determine whether or not to show the answers.
-% (Changed to |\provideboolean| 21 Mar 2004.)
+% \subsection{Package Options}
+%\begin{macro}{\ifshowanswers}
+% Define boolean to determine whether or not to show the
+% solutions. This governs whether the contents of \env{onlysolution}
+% and \env{onlyproblem} are displayed.
% \begin{macrocode}
-\provideboolean{showanswers}
+\newif\ifshowanswers
+\showanswersfalse
% \end{macrocode}
+%\end{macro}
%\begin{macro}{\showanswers}
+% Define synonym for \cs{showanswerstrue}
% \begin{macrocode}
-\let\showanswers=\showanswerstrue
+\let\showanswers\showanswerstrue
% \end{macrocode}
%\end{macro}
%\begin{macro}{\hideanswers}
+% Define synonym for \cs{showanswersfalse}
% \begin{macrocode}
-\let\hideanswers=\showanswersfalse
+\let\hideanswers\showanswersfalse
% \end{macrocode}
%\end{macro}
-% Now define the package options
+% The package option \pkgopt{answers} displays the solutions.
% \begin{macrocode}
\DeclareOption{answers}{\showanswerstrue}
+% \end{macrocode}
+% The package option \pkgopt{noanswers} hides the solutions.
+% \begin{macrocode}
\DeclareOption{noanswers}{\showanswersfalse}
-\ExecuteOptions{noanswers}
+% \end{macrocode}
+%\begin{macro}{\prob@showdraftlabel}
+%\begin{definition}
+%\cs{prob@showdraftlabel}\marg{db name}\marg{label}
+%\end{definition}
+% Used by \cs{useproblem} to display data base name and problem
+% label when in draft mode.
+% \begin{macrocode}
+\newcommand*{\prob@showdraftlabel}[2]{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\draftproblemlabel}
+%\begin{definition}
+%\cs{draftproblemlabel}\marg{db name}\marg{label}
+%\end{definition}
+% Displays the data base name and label.
+% \begin{macrocode}
+\newcommand*{\draftproblemlabel}[2]{[#1,#2]}
+% \end{macrocode}
+%\end{macro}
+% Draft mode displays the problem label using \cs{draftproblemlabel}
+% \begin{macrocode}
+\DeclareOption{draft}{%
+\renewcommand*{\prob@showdraftlabel}[2]{\draftproblemlabel{#1}{#2}}}
+% \end{macrocode}
+% Final mode:
+% \begin{macrocode}
+\DeclareOption{final}{%
+\renewcommand*{\prob@showdraftlabel}[2]{}}
+% \end{macrocode}
+% Process package options:
+% \begin{macrocode}
\ProcessOptions
+% \end{macrocode}
+%\subsection{Databases}
+% All the problems are stored in data bases. Each data base
+% \meta{name} is represented as a macro \cs{prob@db@}\meta{name}
+% which stores a comma-separated list of labels for each problem
+% associated with that data base. Each problem \meta{label} is
+% stored in the macro
+% \cs{prob@data@}\meta{name}"@"\meta{name}"@"\meta{label}. Problems
+% loaded from an external file using \cs{loadproblems} are added
+% to the specified data base. Any problems that are defined in the
+% document or are \cs{input}ed from another file (without the
+% use of \cs{loadproblems}) are added to the default data base.
+%
+% Define the default data base:
+% \begin{macrocode}
+\newcommand*{\prob@db@default}{}
% \end{macrocode}
-% Create newifs for selecting randomly and parsing through file
+%
+%\begin{macro}{\prob@databases}
+% Store a list of all the defined data bases.
% \begin{macrocode}
-\newif\ifselectrandom \selectrandomfalse
-\newif\iffirstpass
-\newif\ifselected
+\newcommand*{\prob@databases}{default}
% \end{macrocode}
-%\begin{macro}{\newproblem}
-% Define the command that creates a new problem. As from version
-% 2.03 this command now has a starred version for problems without
-% solutions.
+%\end{macro}
+%
+%\begin{macro}{\prob@newdb}
+%\begin{definition}
+%\cs{prob@newdb}\marg{name}
+%\end{definition}
+% Creates a new (empty) data base.
% \begin{macrocode}
-\newcommand{\newproblem}{\@ifstar\@snewproblem\@newproblem}
+\newcommand*{\prob@newdb}[1]{%
+\@ifundefined{prob@db@#1}{%
+ \expandafter\gdef\csname prob@db@#1\endcsname{}%
+ \xdef\prob@databases{\prob@databases,#1}%
+ }{%
+ \PackageError{probsoln}{Data set `#1' is already defined}{}}}
% \end{macrocode}
%\end{macro}
-%\begin{macro}{\@newproblem}
-% The unstarred version.
+%
+%\begin{macro}{\prob@currentdb}
+% Keep a track of the current data base
% \begin{macrocode}
-\newcommand{\@newproblem}[4][0]{%
-\ifselectrandom
-\iffirstpass
-% on the first pass, just store the label, and increment \@probN
-\global\advance\@probN by 1
-\expandafter\gdef\csname @problabel\romannumeral\@probN\endcsname{#2}%
-\else
-% check to see if this problem has been selected
-\checkselected{#2}%
-\ifselected
-\@ifundefined{@prob@#2}{%
-\ifnum#1=0
-% this problem has no arguments
-\expandafter\gdef\csname @prob@#2\endcsname{%
-#3 \ifshowanswers\begin{solution}#4\end{solution}\fi}%
-\expandafter\gdef\csname @prob@#2@arg\endcsname{\relax}%
-\else
-\message{Problem #2 requires #1 argument(s), please specify (e.g. {5}{3}):}%
-\read-1to\@tmp
-\expandafter\xdef\csname @prob@#2@arg\endcsname{\@tmp}%
-\expandafter\global\expandafter\newcommand\csname @prob@#2\endcsname[#1]{%
-#3 \ifshowanswers\begin{solution}#4\end{solution}\fi}%
-\fi
-}{%
-\PackageError{probsoln}{Label #2 already used}%
-{Each problem must have a unique label identifier}%
+\newcommand*{\prob@currentdb}{default}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\moveproblem}
+%\begin{definition}
+%\cs{moveproblem}\marg{label}\marg{source}\marg{target}
+%\end{definition}
+% \begin{macrocode}
+\newcommand{\moveproblem}[3]{%
+\@moveproblem{#1}{#2}{#3}%
+\expandafter\let\expandafter\@tmpdblist
+ \csname prob@db@#2\endcsname
+\expandafter\gdef\csname prob@db@#2\endcsname{}%
+\@for\@tmplab:=\@tmpdblist\do{%
+ \ifthenelse{\equal{\@tmplab}{#1}}{}{%
+ \expandafter\ifx\csname prob@db@#2\endcsname\@empty
+ \expandafter\xdef\csname prob@db@#2\endcsname{\@tmplab}%
+ \else
+ \expandafter\xdef\csname prob@db@#2\endcsname{%
+ \csname prob@db@#2\endcsname,%
+ \@tmplab}%
+ \fi
+ }%
}%
-\fi
-\fi
-\else
-\@ifundefined{@prob@#2}{%
-\expandafter\global\expandafter\newcommand\csname @prob@#2\endcsname[#1]{%
-#3 \ifshowanswers\begin{solution}#4\end{solution}\fi}%
-}{%
-\PackageError{probsoln}{Label #2 already used}%
-{Each problem must have a unique label identifier}%
}
-\fi
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@moveproblem}
+%\begin{definition}
+%\cs{@moveproblem}\marg{label}\marg{source}\marg{target}
+%\end{definition}
+% Moves problem identified by \meta{label} from the data base
+% \meta{source} to the data base \meta{target}. (Doesn't remove
+% label from \meta{source} --- that needs to be done separately.)
+% \begin{macrocode}
+\newcommand*{\@moveproblem}[3]{%
+% \end{macrocode}
+% Add label to target data base
+% \begin{macrocode}
+ \expandafter\ifx\csname prob@db@#3\endcsname\@empty
+ \expandafter\xdef\csname prob@db@#3\endcsname{#1}%
+ \else
+ \expandafter\xdef\csname prob@db@#3\endcsname{%
+ \csname prob@db@#3\endcsname,#1}%
+ \fi
+% \end{macrocode}
+% Redefine \cs{prob@data@}\meta{source}"@"\meta{label} as
+% \cs{prob@data@}\meta{target}"@"\meta{label}.
+% \begin{macrocode}
+ \edef\do@movedata{%
+ \noexpand\global\noexpand\let\expandafter\noexpand
+ \csname prob@data@#3@#1\endcsname=%
+ \expandafter\noexpand\csname prob@data@#2@#1\endcsname
+ \noexpand\global\noexpand\let
+ \expandafter\noexpand
+ \csname prob@data@#2@#1\endcsname=\noexpand\undefined
+ }%
+ \do@movedata
+% \end{macrocode}
+% Redefine \cs{prob@argN@}\meta{source}"@"\meta{label} as
+% \cs{prob@argN@}\meta{target}"@"\meta{label}.
+% \begin{macrocode}
+ \edef\do@moveargN{%
+ \noexpand\global\noexpand\let\expandafter\noexpand
+ \csname prob@argN@#3@#1\endcsname=%
+ \expandafter\noexpand\csname prob@argN@#2@#1\endcsname
+ \noexpand\global\noexpand\let
+ \expandafter\noexpand
+ \csname prob@argN@#2@#1\endcsname=\noexpand\undefined
+ }%
+ \do@moveargN
+% \end{macrocode}
+% Redefine \cs{prob@args@}\meta{source}"@"\meta{label} as
+% \cs{prob@args@}\meta{target}"@"\meta{label}, if defined.
+% \begin{macrocode}
+ \@ifundefined{prob@args@#2@#1}{}{%
+ \edef\do@moveargs{%
+ \noexpand\global\noexpand\let\expandafter\noexpand
+ \csname prob@args@#3@#1\endcsname=%
+ \expandafter\noexpand\csname prob@args@#2@#1\endcsname
+ \noexpand\global\noexpand\let
+ \expandafter\noexpand
+ \csname prob@args@#2@#1\endcsname=\noexpand\undefined
+ }%
+ \do@moveargs
+ }%
}
% \end{macrocode}
%\end{macro}
-%\begin{macro}{\@snewproblem}
-% The starred version (new to version 2.03). Note that there is one
-% less argument, because the problem doesn't have a solution.
+%
+%\subsection{Defining New Problems}
+%\begin{macro}{\prob@newproblem}
+%\begin{definition}
+%\cs{prob@newproblem}\marg{n}\marg{db name}\marg{label}\marg{definition}
+%\end{definition}
+% Define a new problem identified by \meta{label} for data base
+% \meta{db name} with the given definition. The problem has \meta{n}
+% arguments (each represented by "#1" etc). The arguments may
+% either be appended to \cs{useproblem}\marg{label} or may
+% be stored in \cs{prob@args@}\meta{db name}"@"\meta{label} if
+% the problem is to be accessed via \cs{foreachproblem}. The
+% number of arguments is stored in
+% \cs{prob@argN@}\meta{db name}"@"\meta{label}
% \begin{macrocode}
-\newcommand{\@snewproblem}[3][0]{%
-\ifselectrandom
-\iffirstpass
-% on the first pass, just store the label, and increment \@probN
-\global\advance\@probN by 1
-\expandafter\gdef\csname @problabel\romannumeral\@probN\endcsname{#2}%
-\else
-% check to see if this problem has been selected
-\checkselected{#2}%
-\ifselected
-\@ifundefined{@prob@#2}{%
-\ifnum#1=0
-% this problem has no arguments
-\expandafter\gdef\csname @prob@#2\endcsname{#3}%
-\expandafter\gdef\csname @prob@#2@arg\endcsname{\relax}%
+\newcommand{\prob@newproblem}[4]{%
+% \end{macrocode}
+% If the given data base is not defined, create it:
+% \begin{macrocode}
+\@ifundefined{prob@db@#2}{\prob@newdb{#2}}{}%
+% \end{macrocode}
+% Check whether this entry has already been defined:
+% \begin{macrocode}
+\@ifundefined{prob@data@#2@#3}{%
+% \end{macrocode}
+% Define the new problem and make it global:
+% \begin{macrocode}
+\let\@tmp=\undefined
+\newcommand\@tmp[#1]{#4}%
+\expandafter\global\expandafter\let
+ \csname prob@data@#2@#3\endcsname=\@tmp
+\expandafter\xdef\csname prob@argN@#2@#3\endcsname{\number#1}%
+\let\@tmp=\undefined
+% \end{macrocode}
+% Add the label to the data base:
+% \begin{macrocode}
+\expandafter\ifx\csname prob@db@#2\endcsname\@empty
+ \expandafter\xdef\csname prob@db@#2\endcsname{#3}%
\else
-\message{Problem #2 requires #1 argument(s), please specify (e.g. {5}{3}):}%
-\read-1to\@tmp
-\expandafter\xdef\csname @prob@#2@arg\endcsname{\@tmp}%
-\expandafter\global\expandafter\newcommand\csname @prob@#2\endcsname[#1]{#3}%
-\fi
-}{%
-\PackageError{probsoln}{Label #2 already used}%
-{Each problem must have a unique label identifier}%
-}%
+ \expandafter\xdef\csname prob@db@#2\endcsname{%
+ \csname prob@db@#2\endcsname,#3}%
\fi
+% \end{macrocode}
+% If the problem requires arguments, prompt the user if necessary:
+% \begin{macrocode}
+\ifnum#1>0\relax
+ \@prob@do@getargs{#1}{#2}{#3}%
\fi
+ }{%
+ \PackageError{probsoln}{Problem `#3' is already defined for
+ data base `#2'}{Problem labels must be unique for each data base}}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\@prob@gobblethree}
+% Ignore all three arguments
+% \begin{macrocode}
+\newcommand{\@prob@gobblethree}[3]{}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@prob@getargs}
+%\begin{definition}
+%\cs{@prob@getargs}\meta{n}\meta{db name}\meta{label}
+%\end{definition}
+% Prompt user for \meta{n} arguments for problem \meta{label}
+% in data base \meta{db name}.
+% \begin{macrocode}
+\newcommand{\@prob@getargs}[3]{%
+\message{Problem `#3' (in data base `#2') requires #1 argument(s).^^J
+Please specify (e.g. {5}{3}):}%
+\read-1to\@tmp
+\expandafter\global\expandafter\let
+ \csname prob@args@#2@#3\endcsname=\@tmp
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@prob@do@getargs}
+% \begin{macrocode}
+\let\@prob@do@getargs\@prob@gobblethree
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\long@collect@body}
+% Need long versions of \cs{collect@body}. These macros are
+% adapted from the macros defined by \sty{amsmath}.
+% \begin{macrocode}
+\long\def\long@collect@body#1{%
+ \@envbody{\@xp#1\@xp{\the\@envbody}}%
+ \edef\process@envbody{\the\@envbody\@nx\end{\@currenvir}}%
+ \@envbody\@emptytoks \def\begin@stack{b}%
+ \begingroup
+ \@xp\let\csname\@currenvir\endcsname\long@collect@@body
+ \edef\process@envbody{\@xp\@nx\csname\@currenvir\endcsname}%
+ \process@envbody
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\long@addto@envbody}
+% \begin{macrocode}
+\long\def\long@addto@envbody#1{\global\@envbody\@xp{\the\@envbody#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\long@collect@@body}
+% \begin{macrocode}
+\long\def\long@collect@@body#1\end#2{%
+ \edef\begin@stack{\long@push@begins#1\begin\end \@xp\@gobble\begin@stack}%
+ \ifx\@empty\begin@stack
+ \endgroup
+ \@checkend{#2}%
+ \long@addto@envbody{#1}%
+ \else
+ \long@addto@envbody{#1\end{#2}}%
+ \fi
+ \process@envbody
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\long@push@begins}
+% \begin{macrocode}
+\long\def\long@push@begins#1\begin#2{%
+ \ifx\end#2\else b\@xp\long@push@begins\fi
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{environment}{defproblem}
+%\begin{definition}
+%"\begin{defproblem}"\oarg{n}\marg{label}
+%\end{definition}
+% Define a new problem identified by \meta{label} with
+% \meta{n} arguments to add to the current data base. Note that
+% since the contents of the environment are passed to a command,
+% the contents can't contain any verbatim text.
+% \begin{macrocode}
+\newenvironment{defproblem}[2][0]{%
+ \def\@prob@currentargN{#1}%
+ \def\@prob@currentlabel{#2}%
+ \long@collect@body\prob@do@defproblem
+}{}
+% \end{macrocode}
+%\end{environment}
+%\begin{macro}{\prob@do@newproblem}
+%\begin{definition}
+%\cs{prob@do@newproblem}\marg{definition}
+%\end{definition}
+% Defines a new problem given by \meta{definition}, where
+% the number of arguments is given by \cs{@prob@currentargN},
+% the label is given by \cs{@prob@currentlabel} and the data base
+% is given by \cs{prob@currentdb}.
+% \begin{macrocode}
+\newcommand{\prob@do@newproblem}[1]{%
+\prob@newproblem\@prob@currentargN\prob@currentdb
+ \@prob@currentlabel{#1}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\prob@do@defproblem}
+% The default action of the \env{defproblem} environment is to
+% define a new problem.
+% \begin{macrocode}
+\let\prob@do@defproblem=\prob@do@newproblem
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{environment}{onlysolution}
+% Define an environment that only displays its contents if the
+% solutions should be displayed.
+% \begin{macrocode}
+\newenvironment{onlysolution}{%
+ \long@collect@body\do@onlysolution
+}{}
+% \end{macrocode}
+%\end{environment}
+%\begin{macro}{\do@onlysolution}
+% \begin{macrocode}
+\newcommand{\do@onlysolution}[1]{%
+\ifshowanswers
+ #1%
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{environment}{onlyproblem}
+% Define an environment that only displays its contents if the
+% solutions should not be displayed.
+% \begin{macrocode}
+\newenvironment{onlyproblem}{%
+ \long@collect@body\do@onlyproblem
+}{}
+% \end{macrocode}
+%\end{environment}
+%\begin{macro}{\do@onlyproblem}
+% \begin{macrocode}
+\newcommand{\do@onlyproblem}[1]{%
+\ifshowanswers
\else
-\@ifundefined{@prob@#2}{%
-\expandafter\global\expandafter\newcommand\csname @prob@#2\endcsname[#1]{#3}%
+ #1%
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Using Problems}
+%\begin{macro}{\useproblem}
+%\begin{definition}
+%\cs{useproblem}\oarg{db name}\marg{label}\marg{arg1}\ldots
+%\marg{argN}
+%\end{definition}
+% Use problem identified by \meta{label} in data base
+% \meta{db name} where \meta{arg1}\ldots\meta{argN} are the
+% arguments to pass to the problem, if the problem was defined
+% to take arguments.
+% \begin{macrocode}
+\newcommand{\useproblem}[2][default]{%
+\prob@showdraftlabel{#1}{#2}%
+\let\@next=\relax
+\@ifundefined{prob@data@#1@#2}{%
+ \PackageError{probsoln}{Problem `#2' is not defined in data set
+ `#1'}{}%
}{%
-\PackageError{probsoln}{Label #2 already used}%
-{Each problem must have a unique label identifier}%
+ \def\@next{\csname prob@data@#1@#2\endcsname}%
+}%
+\@next}
+% \end{macrocode}
+%\end{macro}
+%\subsection{Loading Problems From Another File}
+%\begin{macro}{\loadallproblems}
+%\begin{definition}
+%\cs{loadallproblems}\oarg{db name}\marg{filename}
+%\end{definition}
+% Loads all the problems defined in \meta{filename} and adds
+% them to data base \meta{db name}. (\cs{par} is temporarily
+% disabled to allow for blank lines between problems.)
+% \begin{macrocode}
+\newcommand*{\loadallproblems}[2][default]{%
+\bgroup
+ \let\par\relax
+ \edef\prob@currentdb{#1}%
+ \input{#2}%
+\egroup
}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\prob@do@selectedproblem}
+% Only define problem if the label is listed in
+% \cs{prob@selectedlabels}. (The current label is
+% given by \cs{@prob@currentlabel}.)
+% \begin{macrocode}
+\newcommand{\prob@do@selectedproblem}[1]{%
+\IfSubStringInString{,\@prob@currentlabel,}{,\prob@selectedlabels,}{%
+\prob@do@newproblem{#1}}{}%
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\loadselectedproblems}
+%\begin{definition}
+%\cs{loadselectedproblems}\oarg{db name}\marg{list}\marg{filename}
+%\end{definition}
+% Loads only those problems whose labels are listed in
+% \meta{list}.
+% \begin{macrocode}
+\newcommand{\loadselectedproblems}[3][default]{%
+\bgroup
+ \let\par\relax
+ \edef\prob@currentdb{#1}%
+ \edef\prob@selectedlabels{#2}%
+ \let\prob@do@defproblem=\prob@do@selectedproblem
+ \input{#3}%
+\egroup
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\prob@add@currentlabel}
+% Adds the current label to \cs{prob@selectedlabels} (ignores
+% argument.)
+% \begin{macrocode}
+\newcommand{\prob@add@currentlabel}[1]{%
+\ifx\prob@selectedlabels\@empty
+ \xdef\prob@selectedlabels{\@prob@currentlabel}%
+\else
+ \xdef\prob@selectedlabels{\prob@selectedlabels,\@prob@currentlabel}%
\fi
}
% \end{macrocode}
%\end{macro}
-%\begin{macro}{\useproblem}
-% Define the command that uses a problem
+%\begin{macro}{\iffirstpass}
+% Determines if this is the first pass of the filename when loading
+% a data base.
+% \begin{macrocode}
+\newif\iffirstpass
+\firstpasstrue
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\loadrandomproblems}
+%\begin{definition}
+%\cs{loadrandomproblems}\oarg{db name}\marg{n}\marg{filename}
+%\end{definition}
+% Loads \meta{n} randomly selected problems from \meta{filename}.
+% Needs to input \meta{filename} twice: the first time just gathers
+% all the labels, the second time only loads the selected problems.
+% \begin{macrocode}
+\newcommand{\loadrandomproblems}[3][default]{%
+\bgroup
+ \let\par\relax
+ \def\prob@db@reserved{}%
+ \def\prob@currentdb{reserved}%
+ \edef\prob@selectedlabels{}%
+% \end{macrocode}
+% Collect labels:
+% \begin{macrocode}
+ \let\prob@do@defproblem=\prob@add@currentlabel
+ \firstpasstrue
+ \input{#3}%
+% \end{macrocode}
+% Shuffle labels.
+% \begin{macrocode}
+ \@probselN=0\relax
+ \@for\@thislabel:=\prob@selectedlabels\do{%
+ \advance\@probselN by 1\relax
+ \expandafter
+ \edef\csname @prob@tmp@\romannumeral\@probselN\endcsname{%
+ \@thislabel}%
+ }%
+ \shuffle{@prob@tmp@}{\@probselN}%
+ \ifnum\@probselN<#2\relax
+ \PackageError{probsoln}{%
+ Can't select \number#2\space\space problem(s):^^J
+ '#3' only contains \number\@probselN\space problem(s)}{%
+ Only \number\@probselN\space problem(s) will be selected}%
+ \else
+ \@probselN=#2\relax
+ \fi
+% \end{macrocode}
+% Store only the first \meta{n} of the shuffled labels.
+% \begin{macrocode}
+ \@probN=0\relax
+ \def\prob@selectedlabels{}%
+ \whiledo{\@probN<\@probselN}{%
+ \advance\@probN by 1\relax
+ \ifx\prob@selectedlabels\@empty
+ \edef\prob@selectedlabels{%
+ \csname @prob@tmp@\romannumeral\@probN\endcsname}%
+ \else
+ \edef\prob@selectedlabels{%
+ \prob@selectedlabels,%
+ \csname @prob@tmp@\romannumeral\@probN\endcsname}%
+ \fi
+ }%
+% \end{macrocode}
+% Only load selected labels.
% \begin{macrocode}
-\newcommand*{\useproblem}[1]{%
-\@ifundefined{@prob@#1}{%
-\PackageError{probsoln}{Label #1 undefined}%
-{Can't find problem defined with label identifier `#1'}%
-}{\csname @prob@#1\endcsname}%
+ \let\prob@do@defproblem=\prob@do@selectedproblem
+ \firstpassfalse
+ \input{#3}%
+% \end{macrocode}
+% Move them from the reserved data base into the required data base
+% in the order specified by \cs{prob@selectedlabels}
+% \begin{macrocode}
+\@ifundefined{prob@db@#1}{\prob@newdb{#1}}{}%
+\@for\@thislabel:=\prob@selectedlabels\do{%
+ \@moveproblem{\@thislabel}{reserved}{#1}%
+}%
+% \end{macrocode}
+% \cs{prob@selectedlabels} had to be globally defined. It's no
+% longer required to undefine it.
+% \begin{macrocode}
+ \let\prob@selectedlabels=\undefined
+\egroup
+}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Iterating Through a Data Base}
+%\begin{macro}{\foreachproblem}
+%\begin{definition}
+%\cs{foreachproblem}\oarg{db name}\marg{body}
+%\end{definition}
+% Does \meta{body} for each problem defined in the data base
+% \meta{db name}. Within \meta{body}, the command \cs{thisproblem}
+% can be used to do the current problem and the command
+% \cs{thisproblemlabel} can be used to access the current label.
+% \begin{macrocode}
+\newcommand{\foreachproblem}[2][default]{%
+\@ifundefined{prob@db@#1}{%
+ \PackageError{probsoln}{Data base `#1' is not defined}{}%
+}{%
+ \expandafter\let\expandafter\@tmp\csname prob@db@#1\endcsname
+ \@for\thisproblemlabel:=\@tmp\do{%
+ \expandafter\ifnum
+ \csname prob@argN@#1@\thisproblemlabel\endcsname>0\relax
+ \@ifundefined{prob@args@#1@\thisproblemlabel}{%
+ \expandafter\@prob@getargs
+ \csname prob@argN@#1@\thisproblemlabel\endcsname
+ {#1}{\thisproblemlabel}}{}%
+ \expandafter\let\expandafter\thisproblemargs
+ \csname prob@args@#1@\thisproblemlabel\endcsname
+ \else
+ \let\thisproblemargs\@empty
+ \fi
+ \expandafter\toks@\expandafter{\thisproblemargs}%
+ \edef\thisproblem{\noexpand\useproblem[#1]{\thisproblemlabel}%
+ \the\toks@}%
+ #2%
+ }%
+}%
}
% \end{macrocode}
%\end{macro}
-% Now deal with the stuff for random selection.
+%
+%\begin{macro}{\foreachdataset}
+%\begin{definition}
+%\cs{foreachdataset}\marg{cmd}\marg{body}
+%\end{definition}
+% Iterates through all defined data sets. Assigns \meta{cmd} to the
+% name of the data base.
+% \begin{macrocode}
+\newcommand{\foreachdataset}[2]{%
+\@for#1:=\prob@databases\do{#2}}
+% \end{macrocode}
+%\end{macro}
+%
+%\subsection{Random Numbers}
% First define some registers for later use.
% \begin{macrocode}
\newcount\@probN \newcount\@probselN \newcount\@rndselctr
@@ -712,14 +1426,19 @@
\newcommand*{\PSNrandseed}[1]{%
\ifnum#1=0\relax
\PackageWarning{probsoln}{Can't have 0 as random seed, changing to 1}%
- \r@ndcur=1\relax
+ \global\r@ndcur=1\relax
\else
- \r@ndcur=#1\relax
+ \global\r@ndcur=#1\relax
\fi
\PackageInfo{probsoln}{Random Seed = \number\r@ndcur}%
}
% \end{macrocode}
%\end{macro}
+%\begin{macro}{\PSNgetrandseed}
+% \begin{macrocode}
+\newcommand*{\PSNgetrandseed}[1]{#1=\r@ndcur\relax}
+% \end{macrocode}
+%\end{macro}
%\begin{macro}{\PSNrand}
% Generate a random integer.
% \begin{macrocode}
@@ -727,17 +1446,21 @@
\@ps@randtmp=\r@ndcur
\multiply\@ps@randtmp by 16807\relax
\r@ndcur=\@ps@randtmp
-\divide\r@ndcur by 120001\relax
-\multiply\r@ndcur by 120001\relax
+\global\divide\r@ndcur by 120001\relax
+\global\multiply\r@ndcur by 120001\relax
\advance\@ps@randtmp by -\r@ndcur
-\r@ndcur = \@ps@randtmp
-\ifnum\r@ndcur=0\relax\r@ndcur=1\fi
+\global\r@ndcur = \@ps@randtmp
+\ifnum\r@ndcur=0\relax
+ \global\r@ndcur=1\relax
+\fi
}
% \end{macrocode}
%\end{macro}
%\begin{macro}{\PSNrandom}
-% \cs{PSNrandom}\marg{count}\marg{n} stores a random number
-% from 1 to \meta{n}
+%\begin{definition}
+%\cs{PSNrandom}\marg{count}\marg{n}
+%\end{definition}
+% stores a random number from 1 to \meta{n}
% in the TeX count register \meta{count}
% \begin{macrocode}
\newcommand{\PSNrandom}[2]{%
@@ -758,7 +1481,9 @@
% \end{macrocode}
%\end{macro}
%\begin{macro}{\random}
-% \cs{random}\marg{counter}\marg{a}\marg{b}:
+%\begin{definition}
+% \cs{random}\marg{counter}\marg{a}\marg{b}
+%\end{definition}
% Generate a random number in the range $[a,b]$, and store this
% number in the \LaTeX\ counter \meta{counter}.
% \begin{macrocode}
@@ -776,101 +1501,12 @@
}
% \end{macrocode}
%\end{macro}
-%\begin{macro}{\selectallproblems}
-% Define command to use all problems from a given file.
-% Syntax: \cs{selectallproblems}\marg{filename}.
-% \begin{macrocode}
-\newcommand*{\selectallproblems}[1]{%
-\global\@probN=0\relax
-\selectrandomtrue
-\firstpasstrue
-\input{#1}%
-\firstpassfalse
-\selectrandomfalse
-\input{#1}%
-\global\@rndselctr=1\relax
-\whiledo{\@rndselctr < \@probN \TE@or \@rndselctr = \@probN}{%
-\edef\@tmp{\csname @problabel\romannumeral\@rndselctr\endcsname}%
-\edef\@probargs{{\@tmp}\csname @prob@\@tmp @arg\endcsname}%
-\PSNitem \expandafter\useproblem\@probargs \endPSNitem
-\global\advance\@rndselctr by 1\relax
-}}
-% \end{macrocode}
-%\end{macro}
-%\begin{macro}{\selectrandomly}
-% Now define command to randomly select \meta{n} problems from
-% a given file.
-% Syntax: \cs{selectrandomly}\marg{filename}\meta{n}.
-% \begin{macrocode}
-\newcommand*{\selectrandomly}[2]{%
-\global\@probselN=#2\relax
-\global\@probN=0\relax
-\selectrandomtrue
-\firstpasstrue
-\input{#1}%
-\ifnum\@probselN>\@probN
- \PackageError{probsoln}{Requested number too large}%
- {You have asked for \the\@probselN \space problems,
- but there are only \the\@probN \space problems defined in the
- file #1. I will only select \the\@probN \space
- problems.}%
- \global\@probselN=\@probN
-\fi
-\shuffle{@problabel}{\@probN}%
-\firstpassfalse
-\input{#1}%
-\selectrandomfalse
-\global\@rndselctr=1\relax
-\whiledo{\@rndselctr < \@probselN \TE@or \@rndselctr = \@probselN}{%
-\edef\@tmp{\csname @problabel\romannumeral\@rndselctr\endcsname}%
-\edef\@probargs{{\@tmp}\csname @prob@\@tmp @arg\endcsname}%
-\PSNitem \expandafter\useproblem\@probargs \endPSNitem
-\global\advance\@rndselctr by 1\relax
-}%
-}
-% \end{macrocode}
-%\end{macro}
-%\begin{macro}{\PSNitem}
-% What to do at start and end of each randomly selected item:
-% (I may turn this into a normal environment at a later date. At the
-% moment, I have kept \verb|\PSNitem| for compatibility with earlier
-% versions.)
-% \begin{macrocode}
-\newcommand*{\PSNitem}{\item}
-\@ifundefined{endPSNitem}{\def\endPSNitem{}}{%
-\PackageError{probsoln}{\string\endPSitem\ already defined}{}}
-% \end{macrocode}
-%\end{macro}
-%\begin{macro}{\solutionname}
-% How to display each solution
-% \begin{macrocode}
-\providecommand*{\solutionname}{Solution}
-\@ifundefined{solution}{%
-\newenvironment{solution}{\par\noindent\textbf{\solutionname:} }{}}{%
-}
-% \end{macrocode}
-%\end{macro}
-%\begin{macro}{\checkselected}
-% Check to see if label has been selected
-% \begin{macrocode}
-\newcount\@ckselctr
-\newcommand*{\checkselected}[1]{%
-\selectedfalse
-\@ckselctr=1\relax
-\whiledo{\@ckselctr < \@probselN \TE@or \@ckselctr = \@probselN}{%
-\ifthenelse{\equal{#1}{\csname @problabel\romannumeral\@ckselctr\endcsname}}%
-{\global\selectedtrue \global\@ckselctr=\@probselN}{}%
-\advance\@ckselctr by 1\relax
-}%
-}
-% \end{macrocode}
-%\end{macro}
%\begin{macro}{\shuffle}
% Shuffle contents of pseudo-array. For example, suppose you have
-% the following definitions: |\def\fooi{A}|, |\def\fooii{B}| and
-% |\def\fooiii{C}|, then |\shuffle{foo}{3}| will shuffle the
-% definitions, so you may end up with, e.g.\ |\def\fooi{C}|,
-% |\def\fooii{A}|, |\def\fooiii{B}|, or some other variation.
+% the following definitions: "\def\fooi{A}", "\def\fooii{B}" and
+% "\def\fooiii{C}", then "\shuffle{foo}{3}" will shuffle the
+% definitions, so you may end up with, e.g.\ "\def\fooi{C}",
+% "\def\fooii{A}", "\def\fooiii{B}", or some other variation.
% \begin{macrocode}
\newcount\@shfctr \newcount\@shfA \newcount\@shfB
\newcommand{\shuffle}[2]{%
@@ -892,15 +1528,18 @@
% \end{macrocode}
%\end{macro}
%\begin{macro}{\doforrandN}
-% Syntax: \cs{doforrandN}\marg{n}\marg{cmd}\marg{list}\marg{text}.
-% A bit like |\@for| but only for a random subset of the given list.
-% For example,
+%\begin{definition}
+% \cs{doforrandN}\marg{n}\marg{cmd}\marg{list}\marg{text}.
+%\end{definition}
+% A bit like \cs{@for} but only for a random subset of the given
+% list.
+% For example, the following will load one problem each from two
+% out of the three listed files.
%\begin{verbatim}
%\doforrandN{2}{\tmp}{file1,file2,file3}{%
-%\selectrandomly{\tmp}{1}}
+%\loadrandomproblems{1}{\tmp}}
%\end{verbatim}
-%This will select one problem each from two out of the three listed
-%files.
+%
% \begin{macrocode}
\newcount\@ps@forrand
\newcommand{\doforrandN}[4]{%
@@ -927,10 +1566,1071 @@ are only \number\@ps@forrand item(s) in the list}%
}}
% \end{macrocode}
%\end{macro}
+%\subsection{Compatibility With Older Versions}
+% These commands ensure that this version is compatible with
+% versions prior to v3.0
+%\begin{macro}{\newproblem}
+% Defines a new problem.
+% \begin{macrocode}
+\newcommand*{\newproblem}{\@ifstar\@snewproblem\@newproblem}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@snewproblem}
+% \begin{macrocode}
+\newcommand{\@snewproblem}[3][0]{%
+\begin{defproblem}[#1]{#2}%
+#3%
+\end{defproblem}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\@newproblem}
+% \begin{macrocode}
+\newcommand{\@newproblem}[4][0]{%
+\begin{defproblem}[#1]{#2}%
+#3%
+\begin{onlysolution}%
+\begin{solution}%
+#4%
+\end{solution}%
+\end{onlysolution}%
+\end{defproblem}}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\selectallproblems}
+% \begin{macrocode}
+\newcommand*{\selectallproblems}[1]{{\loadallproblems[#1]{#1}}%
+\foreachproblem[#1]{\PSNitem\thisproblem\endPSNitem}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\selectrandomly}
+% \begin{macrocode}
+\newcommand*{\selectrandomly}[2]{%
+{\loadrandomproblems[#1]{#2}{#1}}%
+\foreachproblem[#1]{\PSNitem\thisproblem\endPSNitem}%
+}
+% \end{macrocode}
+%\end{macro}
+%\begin{environment}{PSNitem}
+% \begin{macrocode}
+\newenvironment{PSNitem}{\item}{}
+% \end{macrocode}
+%\end{environment}
+%
+%\subsection{Formatting Commands}
+% These commands are provided to format parts of the
+% problems/solutions.
+%\begin{environment}{solution}
+% \begin{macrocode}
+\@ifundefined{solution}{%
+\newenvironment{solution}{\par\noindent\textbf{\solutionname:}}{}%
+}{}
+% \end{macrocode}
+%\end{environment}
+%\begin{macro}{\solutioname}
+% \begin{macrocode}
+\newcommand*{\solutionname}{Solution}
+% \end{macrocode}
+%\end{macro}
+% Define an in-line enumeration which uses the enumeration
+% environment's counters.
+%\begin{environment}{textenum}
+%\changes{2007 Oct 6}{2.05}{new}
+% \begin{macrocode}
+\newenvironment{textenum}{%
+\ifnum\@enumdepth>\thr@@
+ \@toodeep
+\else
+ \advance\@enumdepth\@ne
+ \edef\@enumctr{enum\romannumeral\the\@enumdepth}%
+ \let\@item\@textitem
+ \def\@itemlabel{\refstepcounter{\@enumctr}%
+ \csname label\@enumctr\endcsname}%
+ \setcounter{\@enumctr}{0}%
+\fi\ignorespaces}{%
+\global\advance\@enumdepth\m@ne}
+% \end{macrocode}
+%\end{environment}
+%\begin{macro}{\@textitem}
+% In-line enumeration item
+% \begin{macrocode}
+\def\@textitem[#1]{#1\space\ignorespaces}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\correctitemformat}
+% \changes{2007 Oct 6}{2.05}{new}
+% Indicates how to format the item label for \cs{correctitem} when
+% the solutions are shown. The argument is the label. This
+% defaults to placing the argument in a box.
+% \begin{macrocode}
+\newcommand*{\correctitemformat}[1]{\fbox{#1}}
+% \end{macrocode}
+%\end{macro}
+%\begin{macro}{\incorrectitemformat}
+% \changes{2007 Oct 6}{2.05}{new}
+% Indicates how to format the item label for \cs{incorrectitem} when
+% the solutions are shown. The argument is the label. This
+% defaults to just the argument shifted
+% by \cs{fboxsep} + \cs{fboxrule} to ensure it aligns
+% with the default \cs{correctitemformat}.
+% \begin{macrocode}
+\newcommand*{\incorrectitemformat}[1]{%
+\hspace{\fboxsep}\hspace{\fboxrule}#1}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\correctitem}
+% \changes{2007 Oct 6}{2.05}{new}
+%This can be used instead of \cs{item}. If the solutions are
+% not shown, it behaves like \cs{item}, otherwise, it's like
+% \cs{item}, but the label is formatted according to
+% \cs{correctitemformat}.
+% \begin{macrocode}
+\newcommand*{\correctitem}{\@inmatherr\correctitem
+\@ifnextchar[\@correctitem{\@noitemargtrue\@correctitem[\@itemlabel]}}
+% \end{macrocode}
+% \begin{macrocode}
+\def\@correctitem[#1]{%
+\ifshowanswers
+ \@item[\correctitemformat{#1}]%
+\else
+ \@item[#1]%
+\fi}
+% \end{macrocode}
+%\end{macro}
+%
+%\begin{macro}{\incorrectitem}
+% \changes{2007 Oct 6}{2.05}{new}
+%This can be used instead of \cs{item}. If the solutions are
+% not shown, it behaves like \cs{item}, otherwise, it's like
+% \cs{item}, but the label is formatted according to
+% \cs{incorrectitemformat}.
+% \begin{macrocode}
+\newcommand*{\incorrectitem}{\@inmatherr\incorrectitem
+\@ifnextchar[\@incorrectitem{\@noitemargtrue\@incorrectitem[\@itemlabel]}}
+% \end{macrocode}
+% \begin{macrocode}
+\def\@incorrectitem[#1]{%
+\ifshowanswers
+ \@item[\incorrectitemformat{#1}]%
+\else
+ \@item[#1]%
+\fi}
+% \end{macrocode}
+%\end{macro}
%\iffalse
% \begin{macrocode}
%</probsoln.sty>
% \end{macrocode}
%\fi
+%\iffalse
+% \begin{macrocode}
+%<*1stprncp.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+ % These all involve differentiating from 1st principles
+
+\newproblem{dfp:xcube}{%
+Differentiate $f(x) = x^3$ with respect to $x$ by first principles.}{%
+\begin{eqnarray*}
+\frac{dy}{dx} & = & \lim_{\Delta x\rightarrow 0}\frac{f(x+\Delta x) - f(x)}{\Delta x}\\
+ & = & \lim_{\Delta x\rightarrow 0}\frac{(x+\Delta x)^3-x^3}{\Delta x}\\
+ & = & \lim_{\Delta x\rightarrow 0}\frac{(x+\Delta x)(x^2+2x\Delta x+(\Delta x)^2)-x^3}{\Delta x}\\
+ & = & \lim_{\Delta x\rightarrow 0}\frac{x^3+3x^2\Delta x+3x(\Delta x)^2+(\Delta x)^3-x^3}{\Delta x}\\
+ & = & \lim_{\Delta x\rightarrow 0}\frac{3x^2\Delta x+3x(\Delta x)^2+(\Delta x)^3}{\Delta x}\\
+ & = & \lim_{\Delta x\rightarrow 0}3x^2+3x\Delta x + (\Delta x)^2\\
+ & = & 3x^2
+\end{eqnarray*}}
+
+\newproblem{dfp:Ioverxsq}{%
+Differentiate $\displaystyle f(x) = \frac{1}{x^2}$ with respect to $x$ by first principles.}{%
+\begin{eqnarray*}
+\frac{df}{dx} & = & \lim_{\Delta x\rightarrow 0}\frac{\frac{1}{(x+\Delta x)^2}-\frac{1}{x^2}}{\Delta x}\\
+ & = & \lim_{\Delta x\rightarrow 0}\frac{\frac{x^2-(x+\Delta x)^2}{x^2(x+\Delta x)^2}}{\Delta x}\\
+ & = & \lim_{\Delta x\rightarrow 0}\frac{x^2-(x^2+2x\Delta x+(\Delta x)^2)}{x^2\Delta x(x+\Delta x)^2}\\
+ & = & \lim_{\Delta x\rightarrow 0}\frac{-2x\Delta x-(\Delta x)^2}{x^2\Delta x(x+\Delta x)^2}\\
+ & = & \lim_{\Delta x\rightarrow 0}\frac{-2x-\Delta x}{x^2(x+\Delta x)^2}\\
+ & = & \frac{-2x}{x^2x^2}\\
+ & = & -\frac{2}{x^3}
+\end{eqnarray*}}
+
+\newproblem{dfp:sqrtx}{%
+Differentiate from first principles $f(x) = \surd x$}{%
+\begin{eqnarray*}
+\frac{df}{dx} & = & \lim_{\Delta x\rightarrow 0}\frac{\sqrt{x+\Delta x}-\surd x}{\Delta x}\\
+ & = & \lim_{\Delta x\rightarrow 0}\frac{(\sqrt{x+\Delta x}-\surd x)(\sqrt{x+\delta x}+\surd x)}{\Delta x(\sqrt{x+\Delta x}+\surd x)}\\
+ & = & \lim_{\Delta x\rightarrow 0}\frac{x+\Delta x - x}{\Delta x(\sqrt{x+\Delta x}+\surd x)}\\
+ & = & \lim_{\Delta x\rightarrow 0}\frac{\Delta x}{\Delta x(\sqrt{x+\Delta x}+\Delta x)}\\
+ & = & \lim_{\Delta x\rightarrow 0}\frac{1}{\sqrt{x+\Delta x}+\surd x}\\
+ & = & \frac{1}{2\surd x}
+\end{eqnarray*}}
+
+\newproblem{dfp:cons}{%
+Differentiate from first principles $f(x) = c$ where $c$ is a constant.}{%
+\begin{eqnarray*}
+\frac{df}{dx} & = & \lim_{\Delta x\rightarrow 0}\frac{c-c}{\Delta x}\\
+ & = & \lim_{\Delta x\rightarrow 0}0\\
+ & = & 0
+\end{eqnarray*}}
+
+\newproblem{dfp:cosx}{%
+Given
+\begin{eqnarray*}
+\lim_{x \rightarrow 0} \frac{\cos x - 1}{x} & = & 0\\
+\lim_{x \rightarrow 0} \frac{\sin x}{x} & = & 1
+\end{eqnarray*}
+differentiate from first principles $f(x) = \cos x$.}{%
+\begin{eqnarray*}
+\frac{df}{dx} & = & \lim_{\Delta x \rightarrow 0}\frac{f(x + \Delta x) - f(x)}{\Delta x}\\
+ & = & \lim_{\Delta x \rightarrow 0} \frac{\cos(x + \Delta x) - \cos(x)}{\Delta x}\\
+ & = & \lim_{\Delta x \rightarrow 0} \frac{\cos x\cos\Delta x - \sin x\sin\Delta x - \cos x}{\Delta x}\\
+ & = & \lim_{\Delta x \rightarrow 0} \frac{\cos x(\cos\Delta x - 1) - \sin x\sin\Delta x}{\Delta x}\\
+ & = & \cos x\lim_{\Delta x \rightarrow 0}\frac{\cos\Delta x - 1}{\Delta x}
+ - \sin x\lim_{\Delta x \rightarrow 0}\frac{\sin\Delta x}{\Delta x}\\
+ & = & -1 \qquad\mbox{(using given results)}
+\end{eqnarray*}}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</1stprncp.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*args.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+ % These problems require arguments
+
+ % Arguments: #1->a_2, #2->a_1 and #3->a_0
+ % (Arguments must be integers)
+\newcount\ctr
+\newproblem[3]{diff:quad}{%
+\(f(x) =
+\ifnum#1=0
+\else
+\ifnum#1=1\else#1\fi x^2
+\fi
+\ifnum#2=0
+\else
+\ifnum#2>0 \ifnum#1=0 \else + \fi \fi
+\ifnum#2=1\else#2\fi x
+\fi
+\ifnum#3=0
+\else
+\ifnum#3>0 \ifnum#2=0 \ifnum#1=0 \else + \fi \else + \fi\fi
+#3
+\fi\)
+}{%
+\(f'(x) =
+\ifnum#1=0
+\else
+\ctr=2
+\multiply\ctr by #1
+\the\ctr x
+\fi
+\ifnum#2=0
+\else
+\ifnum#2>0 \ifnum#1=0 \else + \fi \fi
+#2
+\fi
+ % print 0 if both #1 and #2 are 0
+\ifnum#1=0 \ifnum#2=0 0 \fi\fi
+\)
+}
+
+\newproblem[1]{diff:sin}{%
+\(f(x) = \sin(#1x)\)
+}{%
+\(f'(x) = #1\cos(#1x)\)
+}
+
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</args.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*easy.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+ % These are all easy differentiation problems
+
+\newproblem{diffeasy:gpowh}{%
+\(f(x) = g(x)^{h(x)}.\)}{%
+\begin{eqnarray*}
+f(x) & = & e^{\ln g(x)^{h(x)}}\\
+ & = & e^{h(x)\ln g(x)}\\
+f'(x) & = & e^{h(x)\ln g(x)}(h'(x)\ln g(x) + h(x)\frac{g'(x)}{g(x)})\\
+ & = & g(x)^{h(x)}(h'(x)\ln g(x) + \frac{h(x)g'(x)}{g(x)})
+\end{eqnarray*}}
+
+\newproblem{diffeasy:arcsin}{%
+\(y = \arcsin(x)\)}{%
+\[\sin(y) = x\]
+diff. w.r.t. $x$:
+\begin{eqnarray*}
+\cos y \frac{dy}{dx} & = & 1\\
+\frac{dy}{dx} & = & \frac{1}{\cos y}\\
+ & = & \frac{1}{\sqrt{1 - \sin^2y}}\\
+ & = & \frac{1}{\sqrt{1-x^2}}.
+\end{eqnarray*}}
+
+\newproblem{diffeasy:arccos}{%
+$y = \arccos x$.}{%
+\(\cos y = x\)
+diff. w.r.t. $x$:
+\begin{eqnarray*}
+-\sin y \frac{dy}{dx} & = & 1\\
+\frac{dy}{dx} & = & \frac{-1}{\sin y}\\
+ & = & \frac{-1}{\sqrt{1-\cos^2y}}\\
+ & = & \frac{-1}{\sqrt{1-x^2}}
+\end{eqnarray*}}
+
+\newproblem{diffeasy:tan}{%
+\(y = \tan x\)}{%
+\begin{eqnarray*}
+y & = & \tan x\\
+ & = & \frac{\sin x}{\cos x}\\
+\frac{dy}{dx} & = & \frac{\cos x}{\cos x} + \sin x\times\frac{-1}{\cos^2x}\times -\sin x\\
+ & = & 1 + \tan^2x\\
+ & = & \sec^2x.
+\end{eqnarray*}}
+
+\newproblem{diffeasy:arctan}{%
+\(y = \arctan x = \tan^{-1}x\)}{%
+\[\tan y = x\]
+diff w.r.t. $x$:
+\begin{eqnarray*}
+\sec^2y\frac{dy}{dx} & = & 1\\
+\frac{dy}{dx} & = & \frac{1}{\sec^2y}\\
+ & = & \frac{1}{1+\tan^2y}\\
+ & = & \frac{1}{1+x^2}
+\end{eqnarray*}}
+
+\newproblem{diffeasy:cot}{%
+\(y = (\tan x)^{-1} = \cot x\)}{%
+\begin{eqnarray*}
+\frac{dy}{dx} & = & -(\tan x)^{-2}\sec^2x\\
+ & = & -\frac{\cos^2x}{\sin^2x}\cdot\frac{1}{\cos^2x}\\
+ & = & \frac{-1}{\sin^2x}\\
+ & = & -\csc^2x.
+\end{eqnarray*}}
+
+\newproblem{diffeasy:cosxsqsinx}{%
+$y = \cos(x^2)\sin x$.}{%
+\[\frac{dy}{dx} = -\sin(x^2)2x\sin x + \cos(x^2)\cos x\]}
+
+\newproblem{diffeasy:xlnx}{%
+$y = (x+1)\ln(x+1)$.}{%
+\begin{eqnarray*}
+\frac{dy}{dx} & = & \ln(x+1) + \frac{x+1}{x+1}\\
+ & = & 1 + \ln(x+1).
+\end{eqnarray*}}
+
+\newproblem{diffeasy:glng}{%
+$f(x) = g(x)\ln(g(x))$.}{%
+\begin{eqnarray*}
+f'(x) & = & g'(x)\ln(g(x)) + \frac{g(x)}{g(x)}g'(x)\\
+ & = & g'(x)(1+\ln(g(x))).
+\end{eqnarray*}}
+
+\newproblem{diffeasy:sinx/x}{%
+$y = \frac{\sin x}{x}$.}{%
+\[\frac{dy}{dx} = \frac{\cos x}{x} - \frac{\sin x}{x^2}\]}
+
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</easy.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*easy2.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+ % These are all easy differentiation problems
+
+\begin{defproblem}{diffeasy:gpowh}%
+\begin{onlyproblem}%
+\(f(x) = g(x)^{h(x)}.\)%
+\end{onlyproblem}%
+\begin{onlysolution}%
+\begin{eqnarray*}
+f(x) & = & e^{\ln g(x)^{h(x)}}\\
+ & = & e^{h(x)\ln g(x)}\\
+f'(x) & = & e^{h(x)\ln g(x)}(h'(x)\ln g(x) + h(x)\frac{g'(x)}{g(x)})\\
+ & = & g(x)^{h(x)}(h'(x)\ln g(x) + \frac{h(x)g'(x)}{g(x)})
+\end{eqnarray*}%
+\end{onlysolution}%
+\end{defproblem}
+
+\begin{defproblem}{diffeasy:arcsin}%
+\begin{onlyproblem}%
+\(y = \arcsin(x)\)%
+\end{onlyproblem}%
+\begin{onlysolution}%
+\[\sin(y) = x\]
+diff. w.r.t. $x$:
+\begin{eqnarray*}
+\cos y \frac{dy}{dx} & = & 1\\
+\frac{dy}{dx} & = & \frac{1}{\cos y}\\
+ & = & \frac{1}{\sqrt{1 - \sin^2y}}\\
+ & = & \frac{1}{\sqrt{1-x^2}}.
+\end{eqnarray*}
+\end{onlysolution}%
+\end{defproblem}
+
+\begin{defproblem}{diffeasy:arccos}%
+\begin{onlyproblem}%
+$y = \arccos x$.%
+\end{onlyproblem}%
+\begin{onlysolution}%
+\(\cos y = x\)
+diff. w.r.t. $x$:
+\begin{eqnarray*}
+-\sin y \frac{dy}{dx} & = & 1\\
+\frac{dy}{dx} & = & \frac{-1}{\sin y}\\
+ & = & \frac{-1}{\sqrt{1-\cos^2y}}\\
+ & = & \frac{-1}{\sqrt{1-x^2}}
+\end{eqnarray*}
+\end{onlysolution}%
+\end{defproblem}
+
+\begin{defproblem}{diffeasy:tan}%
+\begin{onlyproblem}%
+\(y = \tan x\)%
+\end{onlyproblem}
+\begin{onlysolution}%
+\begin{eqnarray*}
+y & = & \tan x\\
+ & = & \frac{\sin x}{\cos x}\\
+\frac{dy}{dx} & = & \frac{\cos x}{\cos x} + \sin x\times\frac{-1}{\cos^2x}\times -\sin x\\
+ & = & 1 + \tan^2x\\
+ & = & \sec^2x.
+\end{eqnarray*}
+\end{onlysolution}%
+\end{defproblem}
+
+\begin{defproblem}{diffeasy:arctan}%
+\begin{onlyproblem}%
+\(y = \arctan x = \tan^{-1}x\)%
+\end{onlyproblem}%
+\begin{onlysolution}%
+\[\tan y = x\]
+diff w.r.t. $x$:
+\begin{eqnarray*}
+\sec^2y\frac{dy}{dx} & = & 1\\
+\frac{dy}{dx} & = & \frac{1}{\sec^2y}\\
+ & = & \frac{1}{1+\tan^2y}\\
+ & = & \frac{1}{1+x^2}
+\end{eqnarray*}
+\end{onlysolution}%
+\end{defproblem}
+
+\begin{defproblem}{diffeasy:cot}%
+\begin{onlyproblem}%
+\(y = (\tan x)^{-1} = \cot x\)%
+\end{onlyproblem}
+\begin{onlysolution}%
+\begin{eqnarray*}
+\frac{dy}{dx} & = & -(\tan x)^{-2}\sec^2x\\
+ & = & -\frac{\cos^2x}{\sin^2x}\cdot\frac{1}{\cos^2x}\\
+ & = & \frac{-1}{\sin^2x}\\
+ & = & -\csc^2x.
+\end{eqnarray*}
+\end{onlysolution}%
+\end{defproblem}
+
+\begin{defproblem}{diffeasy:cosxsqsinx}%
+\begin{onlyproblem}%
+$y = \cos(x^2)\sin x$.%
+\end{onlyproblem}%
+\begin{onlysolution}%
+\[\frac{dy}{dx} = -\sin(x^2)2x\sin x + \cos(x^2)\cos x\]
+\end{onlysolution}%
+\end{defproblem}
+
+\begin{defproblem}{diffeasy:xlnx}%
+\begin{onlyproblem}%
+$y = (x+1)\ln(x+1)$.
+\end{onlyproblem}%
+\begin{onlysolution}%
+\begin{eqnarray*}
+\frac{dy}{dx} & = & \ln(x+1) + \frac{x+1}{x+1}\\
+ & = & 1 + \ln(x+1).
+\end{eqnarray*}
+\end{onlysolution}
+\end{defproblem}
+
+\begin{defproblem}{diffeasy:glng}%
+\begin{onlyproblem}%
+$f(x) = g(x)\ln(g(x))$.
+\end{onlyproblem}
+\begin{onlysolution}%
+\begin{eqnarray*}
+f'(x) & = & g'(x)\ln(g(x)) + \frac{g(x)}{g(x)}g'(x)\\
+ & = & g'(x)(1+\ln(g(x))).
+\end{eqnarray*}
+\end{onlysolution}%
+\end{defproblem}
+
+\begin{defproblem}{diffeasy:sinx/x}
+\begin{onlyproblem}%
+$y = \frac{\sin x}{x}$.
+\end{onlyproblem}
+\begin{onlysolution}%
+\[\frac{dy}{dx} = \frac{\cos x}{x} - \frac{\sin x}{x^2}\]
+\end{onlysolution}%
+\end{defproblem}
+
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</easy2.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*implicit.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+ % These are all implicit differentiation problems
+
+\newproblem{imd:circ}{%
+Find the gradient of the unit circle ($x^2 + y^2 = 1$).}{%
+Differentiating with respect to $x$ gives:
+\begin{eqnarray*}
+2x + 2y\frac{dy}{dx} & = & 0\\
+\frac{dy}{dx} & = & \frac{-2x}{2y}\\
+ & = & \frac{-x}{\sqrt{1-x^2}}.
+\end{eqnarray*}}
+
+\newproblem{imd:ysq:xcuov2mx}{%
+Find $\frac{dy}{dx}$, given
+\begin{displaymath}
+y^2 = \frac{x^3}{2-x}
+\end{displaymath}}{%
+Differentiating both sides w.r.t.\ $x$:
+\begin{eqnarray*}
+2y\frac{dy}{dx} & = & \frac{(2-x)3x^2 - x^3(-1)}{(2-x)^2}\\
+ & = & \frac{3x^2(2-x) + x^3}{(2-x)^2}\\
+ & = & \frac{6x^2 - 3x^3 + x^3}{(2-x)^2}\\
+ & = & \frac{6x^2-2x^3}{(2-x)^2}\\
+ & = & 2x^2\frac{3-x}{(2-x)^2}
+\end{eqnarray*}
+Therefore
+\begin{displaymath}
+y\frac{dy}{dx} = x^2\frac{3-x}{(2-x)^2}
+\end{displaymath}}
+
+\newproblem{imd:exy:IIxay}{%
+Differentiate w.r.t.\ $x$:
+\begin{displaymath}
+e^{xy} = 2x + y
+\end{displaymath}}{%
+Differentiating both sides w.r.t.\ $x$:
+\begin{eqnarray*}
+e^{xy}(1y + x\frac{dy}{dx}) & = & 2 + \frac{dy}{dx}\\
+xe^{xy}\frac{dy}{dx} - \frac{dy}{dx} & = & 2 - ye^{xy} \\
+\frac{dy}{dx}(xe^{xy}-1) & = & 2 - ye^{xy}\\
+\frac{dy}{dx} & = & \frac{2-ye^{xy}}{xe^{xy}-1}
+\end{eqnarray*}}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</implicit.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*mchoice.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+\newproblem{mc:prod}{%
+Which of the following is the derivative of $x\sin(x)$?
+(Circle the correct answer.)
+\ifthenelse{\boolean{showanswers}}{}%
+{\begin{description}
+\item[A] $\sin(x)$
+\item[B] $x\cos(x)$
+\item[C] $\sin(x) + x\cos(x)$
+\end{description}
+}}{%
+\begin{description}
+\item[A] $\sin(x)$
+\item[B] $x\cos(x)$
+\item[\textcircled{C}] $\sin(x) + x\cos(x)$ (product rule).
+\end{description}
+}
+
+\newproblem{mc:quot}{%
+Which of the following is the derivative of $\frac{\sin(x)}{x}$?
+(Circle the correct answer.)
+\ifthenelse{\boolean{showanswers}}{}%
+{\begin{description}
+\item[A] $\sin(x)$
+\item[B] $\cos(x)$
+\item[C] $\frac{\cos(x)x-\sin(x)}{x^2}$
+\end{description}
+}}{%
+\begin{description}
+\item[A] $\sin(x)$
+\item[B] $\cos(x)$
+\item[\textcircled{C}] $\frac{\cos(x)x-\sin(x)}{x^2}$
+(quotient rule)
+\end{description}
+}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</mchoice.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*newdata.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+\begin{defproblem}{sample}
+\begin{onlyproblem}
+Differentiate $y=\sin x$
+\end{onlyproblem}
+\begin{onlysolution}
+$y'=\cos x$
+\end{onlysolution}
+\end{defproblem}
+
+\begin{defproblem}[1]{sample2}
+\begin{onlyproblem}
+Differentiate $y = \sin(#1x)$
+\end{onlyproblem}
+\begin{onlysolution}
+$y'=#1\cos #1x$
+\end{onlysolution}
+\end{defproblem}
+
+\begin{defproblem}{sample3}
+\begin{onlyproblem}
+Differentiate $y = x^2$.
+\end{onlyproblem}
+\begin{onlysolution}
+$y' = 2x$
+\end{onlysolution}
+\end{defproblem}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</newdata.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*nosoln.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+ % these problems don't have solutions
+
+\newproblem*{oop}{Describe what is meant by object-oriented
+programming.}
+
+\newproblem*{inheritance}{Describe what is meant by the term
+\emph{inheritance} in object-oriented programming. Use examples.}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</nosoln.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*probspaces.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+ % Finite probability spaces
+\newproblem{weightedcoin}{%
+A coin is weighted so that heads is four times as likely
+as tails. Find the probability that:
+\begin{textenum}
+\item tails appears,
+\item heads appears
+\end{textenum}}{%
+Let $p=P(T)$, then $P(H)=4p$. We require $P(H)+P(T)=1$,
+so $4p+p=1$, hence $p=\frac{1}{5}$. Therefore:
+\begin{textenum}
+\item $P(T)=\frac{1}{5}$,
+\item $P(H)=\frac{4}{5}$
+\end{textenum}}
+
+\newproblem*{validprobspaces}{%
+Under which of the following functions does
+$S=\{a_1,a_2\}$ become a probability space?
+\par
+\begin{textenum}
+\begin{tabular}{ll}
+\incorrectitem $P(a_1)=\frac{1}{3}$, $P(a_2)=\frac{1}{2}$
+&
+\correctitem $P(a_1)=\frac{3}{4}$, $P(a_2)=\frac{1}{4}$
+\\
+\correctitem $P(a_1)=1$, $P(a_2)=0$
+&
+\incorrectitem $P(a_1)=\frac{5}{4}$, $P(a_2)=-\frac{1}{4}$
+\end{tabular}
+\end{textenum}
+}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</probspaces.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*probspaces2.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+ % Finite probability spaces
+\begin{defproblem}{weightedcoin}
+\begin{onlyproblem}%
+A coin is weighted so that heads is four times as likely
+as tails. Find the probability that:
+\begin{textenum}
+\item tails appears,
+\item heads appears
+\end{textenum}
+\end{onlyproblem}
+\begin{onlysolution}%
+Let $p=P(T)$, then $P(H)=4p$. We require $P(H)+P(T)=1$,
+so $4p+p=1$, hence $p=\frac{1}{5}$. Therefore:
+\begin{textenum}
+\item $P(T)=\frac{1}{5}$,
+\item $P(H)=\frac{4}{5}$
+\end{textenum}
+\end{onlysolution}
+\end{defproblem}
+
+\begin{defproblem}{validprobspaces}
+\begin{onlyproblem}%
+Under which of the following functions does
+$S=\{a_1,a_2\}$ become a probability space?
+\par
+\begin{textenum}
+\begin{tabular}{ll}
+\item $P(a_1)=\frac{1}{3}$, $P(a_2)=\frac{1}{2}$
+&
+\item\label{validprobspacescorrect1} $P(a_1)=\frac{3}{4}$, $P(a_2)=\frac{1}{4}$
+\\
+\item\label{validprobspacescorrect2} $P(a_1)=1$, $P(a_2)=0$
+&
+\item $P(a_1)=\frac{5}{4}$, $P(a_2)=-\frac{1}{4}$
+\end{tabular}
+\end{textenum}
+\end{onlyproblem}%
+\begin{onlysolution}%
+\ref{validprobspacescorrect1} and \ref{validprobspacescorrect2}%
+\end{onlysolution}
+\end{defproblem}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</probspaces2.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*sample.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+\documentclass[a4paper]{article}
+
+\usepackage{probsoln}
+ %uncomment the following line to display the answers
+\showanswers
+
+ % The following will generate a different set of
+ % problems in subsequent years
+ %\PSNrandseed{\year}
+\PSNrandseed{2007}
+
+\begin{document}
+\title{Sample Problem Sheet}
+\author{Nicola Talbot}
+\maketitle
+
+\begin{enumerate}
+ % Differentiation from first principles
+\selectrandomly{1stprncp}{1}
+
+\item Differentiate the following functions:
+\newcount\oldseed
+\PSNgetrandseed\oldseed
+\begin{enumerate}
+\selectrandomly{easy}{5}
+\end{enumerate}
+\PSNrandseed\oldseed
+
+ % Implicit differentiation
+\selectrandomly{implicit}{2}
+
+ % Finite probability spaces
+\selectrandomly{probspaces}{2}
+
+ % Multiple choice question
+\selectrandomly{mchoice}{1}
+
+ % select one essay style question that doesn't come with a solution
+
+\selectrandomly{nosoln}{1}
+\end{enumerate}
+\end{document}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</sample.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*sample2.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+\documentclass[a4paper]{article}
+
+\usepackage{probsoln}
+ %uncomment the following line to display the answers
+\showanswers
+
+ % The following will generate a different set of
+ % problems in subsequent years
+ %\PSNrandseed{\year}
+
+ % The following will generate a different set of
+ % problems on every run (where each run is at
+ % least a minute apart from the previous one)
+\PSNrandseed{\time}
+
+\begin{document}
+\title{Sample Problem Sheet}
+\author{Nicola Talbot}
+\maketitle
+
+\begin{enumerate}
+
+\newcounter{numproblems}
+ % store a random number from 1 to 3 in the counter numproblems
+\random{numproblems}{1}{3}
+
+ % selects 1,2 or 3 problems from 1 of the given files:
+\doforrandN{1}{\file}{1stprncp,implicit}{\selectrandomly{\file}{\value{numproblems}}}
+
+\item Differentiate the following functions:
+\input{args}% load database
+\begin{enumerate}
+\newcounter{A}
+\newcounter{B}
+\newcounter{C}
+\random{A}{-4}{5}
+\random{B}{-3}{3}
+\random{C}{-1}{10}
+\item \useproblem{diff:quad}{\arabic{A}}{\arabic{B}}{\arabic{C}}
+
+\random{A}{-5}{5}
+ % make sure its not 0
+\whiledo{\value{A}=0}{\random{A}{-5}{5}}
+\item \useproblem{diff:sin}{\arabic{A}}
+\end{enumerate}
+\end{enumerate}
+\end{document}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</sample2.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*sample3.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+\documentclass[a4paper]{article}
+
+\usepackage{longtable}
+\usepackage{probsoln}
+
+ %\showanswers
+
+\newcounter{problem}
+\renewcommand{\PSNitem}{\refstepcounter{problem}%
+\theproblem. }
+\renewcommand{\endPSNitem}{\\}
+
+\renewenvironment{solution}{}{}
+
+\newcommand{\selected}{\fbox{$\times$}}
+\newcommand{\notselected}{\fbox{\phantom{$\times$}}}
+
+\begin{document}
+\begin{longtable}{lrrrl}
+\bfseries Question & \bfseries A & \bfseries B &
+\bfseries C & \ifshowanswers \bfseries Reason\fi\\
+\selectrandomly{tabmchoice}{2}
+\end{longtable}
+\end{document}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</sample3.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*sample4.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+\documentclass[a4paper]{article}
+
+\usepackage{probsoln}
+
+ % Sample file illustrating use of \selectallproblems
+ % All problems defined in specified file will be used
+ % in order of definition
+
+\showanswers
+
+\begin{document}
+Differentiate the following functions:
+\begin{enumerate}
+\selectallproblems{easy}
+\end{enumerate}
+\end{document}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</sample4.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*sample5.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+\documentclass[a4paper]{report}
+
+\usepackage{probsoln}
+
+\begin{document}
+
+\hideanswers
+
+\chapter{Easy Problems}
+\loadrandomproblems[easyproblems]{5}{easy2}
+
+\renewcommand{\theenumi}{\thechapter.\arabic{enumi}}
+\begin{enumerate}
+\foreachproblem[easyproblems]{\item\label{prob:\thisproblemlabel}\thisproblem}
+\end{enumerate}
+
+\chapter{Probability Spaces}
+\loadrandomproblems[probspaces]{2}{probspaces2}
+
+\renewcommand{\theenumi}{\thechapter.\arabic{enumi}}
+\begin{enumerate}
+\foreachproblem[probspaces]{\item\label{prob:\thisproblemlabel}\thisproblem}
+\end{enumerate}
+
+\appendix
+\chapter{Solutions}
+\showanswers
+\begin{enumerate}
+\foreachdataset{\thisdataset}{%
+\foreachproblem[\thisdataset]{\item[\ref{prob:\thisproblemlabel}]\thisproblem}
+}
+\end{enumerate}
+
+\end{document}
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</sample5.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%<*tabmchoice.tex>
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+ % These problems are designed to be placed in a
+ % tabular environment
+ %
+\newproblem{tab:1}{%
+What is $(3+2)\times5$? &
+25 \ifshowanswers\selected\else\notselected\fi &
+13 \notselected &
+10 \notselected &
+}{Brackets come first}%
+
+\newproblem{tab:2}{%
+What is $-1+2\times3$? &
+3 \notselected &
+-7 \notselected &
+5 \ifshowanswers\selected\else\notselected\fi &
+}{Multiplication comes first}%
+% \end{macrocode}
+%\fi
+%\iffalse
+% \begin{macrocode}
+%</tabmchoice.tex>
+% \end{macrocode}
+%\fi
%\Finale
\endinput