%\iffalse % probsoln.dtx generated using makedtx version 1.1 (c) Nicola Talbot % Command line args: % -doc "probsoln-manual.tex" % -src "(.+)\.(sty)\Z=>\1.\2" % -src "(sample.*)\.(tex)\Z=>\1.\2" % -src "(prob-.*)\.(tex)\Z=>\1.\2" % -comment ".+\.tex" % -macrocode ".+\.tex" % -author "Nicola Talbot" % probsoln % Created on 2017/7/10 11:58 %\fi %\iffalse %<*package> %% \CharacterTable %% {Upper-case \A\B\C\D\E\F\G\H\I\J\K\L\M\N\O\P\Q\R\S\T\U\V\W\X\Y\Z %% Lower-case \a\b\c\d\e\f\g\h\i\j\k\l\m\n\o\p\q\r\s\t\u\v\w\x\y\z %% Digits \0\1\2\3\4\5\6\7\8\9 %% Exclamation \! Double quote \" Hash (number) \# %% Dollar \$ Percent \% Ampersand \& %% Acute accent \' Left paren \( Right paren \) %% Asterisk \* Plus \+ Comma \, %% Minus \- Point \. Solidus \/ %% Colon \: Semicolon \; Less than \< %% Equals \= Greater than \> Question mark \? %% Commercial at \@ Left bracket \[ Backslash \\ %% Right bracket \] Circumflex \^ Underscore \_ %% Grave accent \` Left brace \{ Vertical bar \| %% Right brace \} Tilde \~} % %\fi % \iffalse % Doc-Source file to use with LaTeX2e % Copyright (C) 2017 Nicola Talbot, all rights reserved. % \fi % \iffalse %<*driver> \documentclass[a4paper]{nlctdoc} \usepackage[utf8]{inputenc} \usepackage[T1]{fontenc} \usepackage{lmodern} \usepackage{color} \usepackage{probsoln} \usepackage[colorlinks, bookmarks, hyperindex=false, pdfauthor={Nicola L.C. Talbot}, pdftitle={probsoln: creating problem sheets optionally with solutions}]{hyperref} \doxitem{Option}{option}{package options} \RecordChanges \PageIndex \CheckSum{1830} \newcommand*{\dq}[1]{``#1''} \begin{document} \DocInput{probsoln.dtx} \end{document} % %\fi %\MakeShortVerb{"} %\DeleteShortVerb{\|} % % \title{probsoln v3.05: %creating problem sheets optionally with solutions} % \author{Nicola L.C. Talbot\\ %\url{http://www.dickimaw-books.com/}} % % \date{2017-07-10} % \maketitle %\tableofcontents % % \section{Introduction} %The \styfmt{probsoln} package is designed for teachers or lecturers %who want to create problem sheets for their students. This package %was designed with mathematics problems in mind, but can be used for %other subjects as well. The idea is to create a file containing a %large number of problems with their solutions which can be read in %by \LaTeX, and then select a number of problems to typeset. This %means that once the database has been set up, each year you can %easily create a new problem sheet that is sufficiently different %from the previous year, thus preventing the temptation of current %students seeking out the previous year's students, and checking out %their answers. There is also an option that can be passed to the %package to determine whether or not the solutions should be printed. %In this way, one file can either produce the student's version or %the teacher's version. % %You may want to consider using \sty{datatool} with \app{datatooltk} %instead of \styfmt{probsoln}. See %\href{http://www.dickimaw-books.com/latex/admin/html/datatoolexam.shtml}{Using %the \styfmt{datatool} Package for Exams or Assignment Sheets}. % %\section{Package Options}\label{sec:pkgopt} %The following options may be passed to this package: %\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 %\item[\pkgopt{usedefaultargs}] Make \ics{thisproblem} use the %default arguments supplied in the problem definition. %\item[\pkgopt{nousedefaultargs}] Make \ics{thisproblem} prompt for %problem arguments (default). %\end{description} % %\section{Verbatim}\label{sec:verbatim} % %As from version 3.02, problems and solutions may contain verbatim %text, but you must use the \iterm{fragile}\texttt{fragile} (or %\texttt{fragile=true}) option for the associated environments. % %Alternatively, if most of your problems contain verbatim, you can %globally set this option using: %\begin{verbatim} %\setkeys{probsoln}{fragile} %\end{verbatim} %You can switch off this option using \texttt{fragile=false}. % %The \texttt{fragile} option writes information to a temporary file. %This defaults to "\jobname.vrb" but the name may be changed. The %extension (".vrb") is given by: %\begin{definition}[\DescribeMacro{\ProbSolnFragileExt}] %\cs{ProbSolnFragileExt} %\end{definition} %The base name (\cs{jobname}) is given by: %\begin{definition}[\DescribeMacro{\ProbSolnFragileFile}] %\cs{ProbSolnFragileFile} %\end{definition} % %\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 %\begin{definition}[\DescribeMacro{\showanswers}] %\cs{showanswers} %\end{definition} %and %\begin{definition}[\DescribeMacro{\hideanswers}] %\cs{hideanswers} %\end{definition} %respectively. % %The boolean variable \bool{showanswers} determines whether the %answers should be displayed. You can use this value with the %\sty{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 %\begin{definition}[\DescribeEnv{onlyproblem}] %\cs{begin}\marg{onlyproblem}\oarg{option} %\end{definition} %and %\begin{definition}[\DescribeEnv{onlysolution}] %\cs{begin}\marg{onlysolution}\oarg{option} %\end{definition} %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} %What is the derivative of $f(x) = x^2$? %\begin{onlysolution}% %Solution: $f'(x) = 2x$ %\end{onlysolution} %\end{verbatim} % %\begin{important} %If you want to include verbatim text in the body of %\env{onlyproblem} or \env{onlysolution}, you need to specify %\texttt{fragile} in the optional argument of the environment. %(See \sectionref{sec:verbatim} for further details.) %\end{important} % %If you use \envfmt{onlysolution} within the \env{defproblem} %environment, the problem will be tagged as having a solution %and will be added to the list used by \ics{foreachsolution}. %The optional argument of \envfmt{onlysolution} (and \env{onlyproblem}) %is inherited from the parent \env{defproblem} setting. % %\section{General Formatting Commands}\label{sec:formatting} % %The commands and environments described in this section are %provided to assist formatting problems and their solutions. %\begin{definition}[\DescribeEnv{solution}] %\verb|\begin{solution}|\meta{text}\verb|\end{solution}| %\end{definition} %By default, this is equivalent to %\begin{display} %\verb|\par\noindent\textbf{\solutionname}: |\meta{text} %\end{display} %where \DescribeMacro{\solutionname}\cs{solutionname} defaults %to \dq{\solutionname}. Note that you must place the \env{solution} %environment inside the \envfmt{onlysolution} environment or %between \ics{ifshowanswers}\ldots\cs{fi} to ensure that it %is suppressed when the solutions are not wanted. (See %\sectionref{sec:showanswers}.) % % %Note that the \styfmt{probsoln} package will only define the %\env{solution} environment if it is not already defined. % %\begin{definition}[\DescribeEnv{textenum}] %\verb|\begin{textenum}|\ldots\verb|\end{textenum}| %\end{definition} %The \envfmt{textenum} environment is like the \env{enumerate} %environment but is in-line. It uses the same counter that the %\envfmt{enumerate} environment would use at that level so the %question can be compact but the answer can use \envfmt{enumerate} %instead. For example: %\begin{verbatim} %\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 %\env{enumerate} environment would result in a lot of unnecessary %white space, but the answers require more space, so an %\envfmt{enumerate} environment is more appropriate. Since the %\envfmt{textenum} environment uses the same counters as the %\envfmt{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 %\urlfootref{http://www.tex.ac.uk/tex-archive/help/Catalogue/bytopic.html\#enumeration}{TeX %Catalogue} for further details. % %\DescribeMacro{\correctitem}\DescribeMacro{\incorrectitem} %\begin{definition} %\cs{correctitem}\\ %\cs{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} %\cs{correctitemformat}\marg{label}\\ %\cs{incorrectitemformat}\marg{label} %\end{definition} %For example: %\begin{verbatim} %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} %The default definition of \cs{correctitemformat} puts a frame around %the label. % %\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 \styfmt{probsoln} %package has a default data set labelled \dq{default} in which you %can store problems. Alternatively, 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 \env{onlyproblem}, \env{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). % %\begin{definition}[\DescribeEnv{defproblem}] %\verb|\begin{defproblem}|\oarg{n}\oarg{default args}\marg{label}\oarg{option}\newline %\meta{definition}\newline %\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 or a comma. (Active characters include the special characters %such as \$ and \&, but some packages may make other symbols active, %such as the colon (:) character. For example, the \sty{ngerman} and %\sty{babel} packages make certain punctuation active. Check the %relevant package documentation for details.) % %\begin{important} %The final optional argument \meta{option} may be \texttt{fragile} to %indicate that the problem contains verbatim text. Any occurrences of %\env{onlyproblem} or \env{onlysolution} contained within %\envfmt{defproblem} are inherited from \envfmt{defproblem}. (See %\sectionref{sec:verbatim} for further details.) %\end{important} % %If \env{defproblem} occurs in the document or is included via %\ics{input} or \ics{include}, then the problem will be added to %the default data set. If \envfmt{defproblem} occurs in an external %file that is loaded using one of the commands defined in %\sectionref{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 \sectionref{sec:showanswers} and %\sectionref{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} % %The second optional argument \meta{default args} supplies %default problem arguments that will automatically be used within %\ics{thisproblem} when used in \ics{foreachproblem} in conjunction %with the package option \pkgopt{usedefaultargs}. (See \sectionref{sec:foreach}.) %For example: %\begin{verbatim} %\begin{defproblem}[1][{2}]{diffsin} %Differentiate $f(x)=\sin(#1x)$. %\begin{onlysolution}% % \begin{solution} % $f'(x) = #1\cos(#1x)$ % \end{solution} %\end{onlysolution} %\end{defproblem} %\end{verbatim} %\begin{important} %If you don't use \cs{thisproblem} or you don't %use the package option \pkgopt{usedefaultargs}, then you must supply %the arguments. %\end{important} % %\begin{definition}[\DescribeMacro{\newproblem}] %\cs{newproblem}\oarg{n}\oarg{default args}\marg{label}\marg{problem}\marg{solution} %\end{definition} %This is a shortcut command for: %\begin{ttfamily}\obeylines %\cs{begin}\{defproblem\}\oarg{n}\oarg{default args}\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]{diffcos}{% % \(f(x) = \cos(#1x)\) %}% %{% % \(f'(x) = -#1\sin(#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 %\sty{fp} or \sty{pgfmath} packages.) % %Alternatively, if you want to supply default arguments to use when %iterating through problems with \ics{foreachproblem}: %\begin{verbatim} %\newproblem[1][{3}]{diffsin}{% % \(f(x) = \sin(#1x)\) %}% %{% % \(f'(x) = #1\cos(#1x)\) %} %\end{verbatim} % % %\begin{definition}[\DescribeMacro{\newproblem*}] %\cs{newproblem*}\oarg{n}\oarg{default args}\marg{label}\marg{definition} %\end{definition} %This is a shortcut for: %\begin{ttfamily}\obeylines %\cs{begin}\{defproblem\}\oarg{n}\oarg{default args}\marg{label}\% %\meta{definition}\% %\cs{end}\{defproblem\} %\end{ttfamily} % %\begin{important} %Note that you can't use verbatim text with \cs{newproblem} or %\cs{newproblem*}. Use the \env{defproblem} environment instead with %the \texttt{fragile option}. %\end{important} % %\section{Using a Problem}\label{sec:useproblem} % %Once you have defined a problem using \env{defproblem} or %\ics{newproblem} (see \sectionref{sec:defproblem}), you can %later display the problem using: %\begin{definition}[\DescribeMacro{\useproblem}] %\cs{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} %\useproblem{diffcos}{3} %\end{verbatim} %This will be equivalent to: %\begin{verbatim} %\(f(x) = \cos(3x)\) %\begin{onlysolution}% %\begin{solution}% %\(f'(x) = -3\sin(3x)\) %\end{solution}% %\end{onlysolution}% %\end{verbatim} % %\section{Loading Problems From External Files}\label{sec:load} % %You can store all your problem definitions (see %\sectionref{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 \sectionref{sec:foreach}. Note that the commands below %will create a new data set, if the named data set doesn't %exist. % %\begin{definition}[\DescribeMacro{\loadallproblems}] %\cs{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. % %\begin{definition}[\DescribeMacro{\loadselectedproblems}] %\cs{loadselectedproblems}\oarg{data set}\marg{labels}\marg{filename} %\end{definition} %This is like \cs{loadallproblems}, 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} %\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. % %\begin{definition}[\DescribeMacro{\loadexceptproblems}] %\cs{loadexceptproblems}\oarg{data set}\marg{exception list}\marg{filename} %\end{definition} %This is the reverse of \cs{loadselectedproblems}. This loads all %problems except those whose labels are listed in \meta{exception %list}. % %\begin{definition}[\DescribeMacro{\loadrandomproblems}] %\cs{loadrandomproblems}\oarg{data set}\marg{n}\marg{filenames} %\end{definition} %This randomly loads \meta{n} problems from the comma-separated %list\footnote{The list form was added to v3.05. Earlier versions %only allow a single filename.} %of \meta{filenames} 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 across the given list of files. % %Note that there's a difference between %\begin{verbatim} %\loadrandomproblems{5}{problemset1} %\loadrandomproblems{5}{problemset2} %\end{verbatim} %and %\begin{verbatim} %\loadrandomproblems{10}{problemset1,problemset2} %\end{verbatim} %In the first case, the data set will contain 5 problems randomly %selected from \texttt{problemset1} and 5 problems randomly selected %from \texttt{problemset2}. Whereas in the second case, the data set %will contain 10 problems randomly selected across both files. % %\begin{definition}[\DescribeMacro{\loadrandomexcept}] %\cs{loadrandomexcept}\oarg{data set}\marg{n}\marg{filenames}\marg{exception list} %\end{definition} %This is similar to \cs{loadrandomproblems} except that it won't load %those problems whose labels are listed in \meta{exception list}. %\textbf{If you want to automatically exclude problems included in %previous documents, see \sectionref{sec:exprev}.} % %Note that the random number generator has been modified in version %3.01 in order to fix a bug. If you want to ensure that your random %numbers are compatible with earlier versions, you can switch to the %old generator using %\begin{definition}[\DescribeMacro{\PSNuseoldrandom}] %\cs{PSNuseoldrandom} %\end{definition} % %\begin{important} %It is generally not a good idea to place anything in %\meta{filename} that is not inside the body of \env{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 command 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} % %\subsection{Randomly Selecting Problems Not Selected in Previous %Documents} %\label{sec:exprev} % %Suppose you have a large set of questions that you want to randomly %select for assignments and exams. The chances are, you don't want to %include questions that have been previously set for, say, the last %three years. That is, you don't want to select questions the %students may already have seen. As from version 3.03, you can now do %this. % %The \sty{probsoln} package defaults to the UK academic year, which %starts in September. If this isn't appropriate, you can change it %using: %\begin{definition}[\DescribeMacro{\SetStartMonth}] %\cs{SetStartMonth}\marg{n} %\end{definition} %where \meta{n} is the number of the month. (1 = January, 2 = %February, etc.) % %The \emph{start year} is the calender year in effect when the %academic year started. For example, if this is the academic year %2011/12, then the start year is 2011. This is automatically set to %the start of the current academic year. It is also updated when %\cs{SetStartMonth} is used.\footnote{So don't use \cs{SetStartMonth} %after \cs{SetStartYear}.} If you want to set it to a specific year, %you can use: %\begin{definition}[\DescribeMacro{\SetStartYear}] %\cs{SetStartYear}\marg{year} %\end{definition} %For example: \verb|\SetStartYear{2008}| indicates the academic year %2008/9. % %There are two files concerned with previously used labels. They are: %\begin{description} % % \item[The previously used labels file] This keeps track of all % problems used in previous years, as well as problems used by % other documents that have this as their previously used labels % file, and it contains the problem labels from the last run of % the current document. % % \item[The current used labels file] This defaults to %\cs{jobname}\texttt{.prb}, but the name can be changed using: % \begin{definition}[\DescribeMacro{\SetUsedFileName}] % \cs{SetUsedFileName}\marg{name} % \end{definition} % This file keeps track of all the labels used in the current % document from the previous \LaTeX\ run. Note that if you want to % delete this file, first clear it using % \begin{definition}[\DescribeMacro{\ClearUsedFile}] % \cs{ClearUsedFile}\marg{file} % \end{definition} % in place of \cs{ExcludePreviousFile}\marg{file}, described below. % The argument \meta{file} is the previously used labels file % described above. \cs{ClearUsedFile} will remove all labels in % the current used labels file from the previously used labels file % and clear the current used labels file. Once this file is empty, % it may then be deleted. % %\end{description} % %Before loading randomly selected problems, first specify the %previously used labels file with the command: %\begin{definition}[\DescribeMacro{\ExcludePreviousFile}] %\cs{ExcludePreviousFile}\oarg{number of years}\marg{file name} %\end{definition} %where \meta{file name} is the name of the previously used file. The %optional argument \meta{number of years} specifies the year cut-off. %This defaults to 3, which means that only those labels used this %year or the previous 2 years will be kept. Any problems used before %then may be reused. % %Suppose I'm lecturing a first year undergraduate mathematics course %(designated, say, mth101). I want to set assignments on each topic %and an exam at the end of the year (as well as a resit or second %sitting paper). I've got databases with problems for each topic, but %the first and second sitting exams mustn't include any of the %problems used in the assignments or any problems used in assignments %or exams for the previous two academic years. I'm going to arrange %my directory structure as follows: %\begin{itemize} %\item \texttt{mth101/} % \begin{itemize} % \item \texttt{assignment1/} (differentiation) % \begin{itemize} % \item \texttt{assignment1.tex} % \end{itemize} % \item \texttt{assignment2/} (probability spaces) % \begin{itemize} % \item \texttt{assignment2.tex} % \end{itemize} % \item \texttt{assignment3/} (linear algebra) % \begin{itemize} % \item \texttt{assignment3.tex} % \end{itemize} % \item \texttt{exams/} % \begin{itemize} % \item \texttt{exam.tex} (first sitting) % \item \texttt{resit.tex} (second sitting) % \end{itemize} % \item \texttt{databases/} % \begin{itemize} % \item \texttt{differentiation.tex} % \item \texttt{probabilityspaces.tex} % \item \texttt{linearalgebra.tex} % \end{itemize} % \item \texttt{previouslabels.tex} (created by \sty{probsoln}) % \end{itemize} %\end{itemize} % %\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 %\sectionref{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. % %\begin{definition}[\DescribeMacro{\foreachproblem}] %\cs{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 %\begin{definition}[\DescribeMacro{\thisproblem}] %\cs{thisproblem} %\end{definition} %to use the current problem and %\begin{definition}[\DescribeMacro{\thisproblemlabel}] %\cs{thisproblemlabel} %\end{definition} %to access the current label. If the problem requires arguments, %and no default arguments were supplied in the problem definition or %the package option \pkgopt{usedefaultargs} was not used, then %you will be prompted for arguments, 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} %\foreachproblem{\item\thisproblem} %\end{enumerate} %\end{verbatim} % %\begin{definition}[\DescribeMacro{\foreachsolution}] %\cs{foreachsolution}\oarg{data set}\marg{body} %\end{definition} %This is equivalent to \cs{foreachproblem}, but only iterates %through problems that contain the \env{onlysolution} environment. %Note that you still need to use \ics{showanswers} or the %\pkgopt{answers} package option for the contents of the %\env{onlysolution} environment to appear. % %\begin{definition}[\DescribeMacro{\foreachdataset}] %\cs{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} %\foreachdataset{\thisdataset}{% %\foreachproblem[\thisdataset]{\item\thisproblem}} %\end{enumerate} %\end{verbatim} % %Suppose I have two external files called %\texttt{derivatives.tex} and \texttt{probspaces.tex} which %define problems using both \env{onlyproblem} and %\env{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 \env{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} %\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} %\foreachproblem[deriv]{\item\label{prob:\thisproblemlabel}\thisproblem} %\end{enumerate} %% You may need to change \theenumi back here % %\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} %% You may need to change \theenumi back here % %\appendix % %\chapter{Solutions} %\showanswers %\begin{itemize} %\foreachdataset{\thisdataset}{% %\foreachproblem[\thisdataset]{\item[\ref{prob:\thisproblemlabel}]\thisproblem} %} %\end{itemize} % %\end{document} %\end{verbatim} % %\section{Random Number Generator}\label{sec:random} % %This package provides a pseudo-random number generator that is used %by \ics{loadrandomproblems}. As noted earlier the random number %generator has been modified in version 3.01 in order to fix a bug. %If you want to ensure that your random numbers are compatible with %earlier versions, you can switch to the old generator using %\begin{definition}[\DescribeMacro{\PSNuseoldrandom}] %\cs{PSNuseoldrandom} %\end{definition} % %\begin{definition}[\DescribeMacro{\PSNrandseed}] %\cs{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} %\PSNrandseed{\time} %\end{verbatim} %or to generate a different set of random numbers every year you %\LaTeX\ your document: %\begin{verbatim} %\PSNrandseed{\year} %\end{verbatim} % %\begin{definition}[\DescribeMacro{\PSNgetrandseed}] %\cs{PSNgetrandseed}\marg{register} %\end{definition} %This stores the current seed in the count register specified by %\meta{register}. %For example: %\begin{verbatim} %\newcount\myseed %\PSNgetrandseed{\myseed} %\end{verbatim} % %\begin{definition}[\DescribeMacro{\PSNrandom}] %\cs{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} %\newcount\myreg %\PSNrandom{\myreg}{10} %\end{verbatim} % %\begin{definition}[\DescribeMacro{\random}] %\cs{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} %\newcounter{myrand} %\random{myrand}{3}{8} %\end{verbatim} % %\begin{definition}[\DescribeMacro{\doforrandN}] %\cs{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} %\doforrandN{2}{\thisfile}{file1,file2,file3}{% %\loadrandomproblems{1}{\thisfile}} %\end{verbatim} % %\section{Compatibility With Versions Prior to 3.0} % %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. % %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 Solve the following: %\begin{enumerate} %\selectrandomly{file2}{4} %\end{enumerate} % %\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 Solve the following: %\newcount\oldseed %\PSNgetrandseed{\oldseed} %\begin{enumerate} %\selectrandomly{file2}{4} %\end{enumerate} %\PSNrandseed{\oldseed} % %\selectrandomly{file3}{2} %\end{enumerate} %\end{verbatim} % %\begin{definition}[\DescribeMacro{\selectrandomly}] %\cs{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}\{\cs{PSNitem}\cs{thisproblem}\cs{endPSNitem}\} %\end{ttfamily} % %\begin{definition}[\DescribeMacro{\selectallproblems}] %\cs{selectallproblems}\marg{filename} %\end{definition} %This is now equivalent to: %\begin{ttfamily}\obeylines %\{\cs{loadallproblems}\oarg{filename}\marg{filename}\}\% %\cs{foreachproblem}\oarg{filename}\{\cs{PSNitem}\cs{thisproblem}\cs{endPSNitem}\} %\end{ttfamily} % %Note that in both the above cases, a new data set is created %with the same name as the file name. % % \StopEventually{\clearpage\phantomsection\addcontentsline{toc}{section}{Index}\PrintIndex} % % % %\section{The Code} %\iffalse % \begin{macrocode} %<*probsoln.sty> % \end{macrocode} %\fi %\subsection{Package Definition} % This package requires \LaTeXe. % \begin{macrocode} \NeedsTeXFormat{LaTeX2e} % \end{macrocode} % Identify this package and version: % \begin{macrocode} \ProvidesPackage{probsoln}[2017/07/10 v3.05 (NLCT)] % \end{macrocode} % Required packages: %\changes{3.01}{2011/08/22}{substr package no longer required} % \begin{macrocode} \RequirePackage{ifthen} \RequirePackage{amsmath} % \end{macrocode} %\changes{3.03}{2011/01/16}{added etoolbox to list of required %packages} % \begin{macrocode} \RequirePackage{etoolbox} % \end{macrocode} % \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} \newif\ifshowanswers \showanswersfalse % \end{macrocode} %\end{macro} %\begin{macro}{\showanswers} % Define synonym for \cs{showanswerstrue} % \begin{macrocode} \let\showanswers\showanswerstrue % \end{macrocode} %\end{macro} %\begin{macro}{\hideanswers} % Define synonym for \cs{showanswersfalse} % \begin{macrocode} \let\hideanswers\showanswersfalse % \end{macrocode} %\end{macro} % 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} % \end{macrocode} % Determine whether or not to use default arguments for problems. %\begin{macro}{\ifusedefaultprobargs} % \begin{macrocode} \newif\ifusedefaultprobargs % \end{macrocode} %\end{macro} %\begin{option}{usedefaultargs} % \begin{macrocode} \DeclareOption{usedefaultargs}{\usedefaultprobargstrue} % \end{macrocode} %\end{option} %\begin{option}{usedefaultargs} % \begin{macrocode} \DeclareOption{nousedefaultargs}{\usedefaultprobargsfalse} \usedefaultprobargsfalse % \end{macrocode} %\end{option} % %\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} %\changes{3.02}{2011/12/10}{added xkeyval to required package list} % \begin{macrocode} \RequirePackage{xkeyval} % \end{macrocode} %\begin{macro}{\if@prob@fragile} %\changes{3.02}{2011/12/10}{new} %Need a conditional to determine whether \cs{long@collect@body} %needs to be aware of verbatim contents. % \begin{macrocode} \define@boolkey{probsoln}[@prob@]{fragile}[true]{} % \end{macrocode} %\end{macro} %\begin{macro}{\ProbSolnFragileExt} %\changes{3.02}{2011/12/10}{new} % The extension used for temporary files dealing with fragile % contents. % \begin{macrocode} \newcommand*{\ProbSolnFragileExt}{vrb} % \end{macrocode} %\end{macro} %\begin{macro}{\ProbSolnFragileFile} %\changes{3.02}{2011/12/10}{new} % The filename used for temporary files dealing with fragile % contents. % \begin{macrocode} \newcommand*{\ProbSolnFragileFile}{\jobname} % \end{macrocode} %\end{macro} %\begin{macro}{\probsoln@write} %\changes{3.02}{2011/12/10}{new} %File handle for temporary files. % \begin{macrocode} \newwrite\probsoln@write % \end{macrocode} %\end{macro} % %\begin{macro}{\probsoln@startyear} %\changes{3.03}{2011/01/16}{new} % The year as at the start of the new academic year. (For example, % if the academic year starts in September and today is any date % between 2011-09-01 and 2012-08-30, then the start year is 2011.) % \begin{macrocode} \newcount\probsoln@startyear % \end{macrocode} %\end{macro} % %\begin{macro}{\SetStartYear} %\changes{3.03}{2011/01/16}{new} % Provide command to set the starting year manually. % \begin{macrocode} \newcommand*{\SetStartYear}[1]{% \probsoln@startyear=#1\relax \renewcommand\SetStartMonth[1]{% \PackageError{probsoln}{\string\SetStartMonth\space can't be used after \string\SetStartYear}{}}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\GetStartYear} % Gets the value of the start year count register: % \begin{macrocode} \newcommand*{\GetStartYear}{\probsoln@startyear} % \end{macrocode} %\end{macro} % %\begin{macro}{\probsoln@startmonth} %\changes{3.03}{2011/01/16}{new} % The month starting the academic year. (1=January, 2=February, % etc). % \begin{macrocode} \newcount\probsoln@startmonth % \end{macrocode} %\end{macro} %\begin{macro}{\SetStartMonth} %\changes{3.03}{2011/01/16}{new} % Define command to set the month starting the academic year. This % also sets the starting year. % \begin{macrocode} \newcommand*{\SetStartMonth}[1]{% \probsoln@startmonth=#1\relax \probsoln@startyear=\year\relax \ifnum\month<\probsoln@startmonth \advance\probsoln@startyear by -1\relax \fi } % \end{macrocode} %\end{macro} % % Set the default starting month to 9 (September): % \begin{macrocode} \SetStartMonth{9} % \end{macrocode} % %\begin{macro}{\probsoln@prev} %\changes{3.03}{2011/01/16}{new} % File handle for file containing previous labels. % \begin{macrocode} \newwrite\probsoln@prev % \end{macrocode} %\end{macro} % %\begin{macro}{\probsoln@used} %\changes{3.03}{2011/01/16}{new} % File handle for file containing previous used. % \begin{macrocode} \newwrite\probsoln@used % \end{macrocode} %\end{macro} % %\begin{macro}{\probsoln@prev@cutoff} %\changes{3.03}{2011/01/16}{new} % Cut-off year. Problems excluded if the year they were set is % greater than the cut-off year. % \begin{macrocode} \newcount\probsoln@prev@cutoff % \end{macrocode} %\end{macro} % %\begin{macro}{\@probsoln@usedfilename} % Stores the file name for the used problems file. (Defaults to % \cs{jobname}\texttt{.prb}) % \begin{macrocode} \newcommand*{\@probsoln@usedfilename}{\jobname.prb} % \end{macrocode} %\end{macro} % %\begin{macro}{\SetUsedFileName} % Set the name of the used problems file. % \begin{macrocode} \newcommand*{\SetUsedFileName}[1]{% \renewcommand*{\@probsoln@usedfilename}{#1}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\ClearUsedFile} %\changes{3.03}{2011/01/16}{new} % Clear the contents of the used file (\cs{@probsoln@usedfilename}) % and remove corresponding entries from the previous file (as % specified in \cs{ExcludePreviousFile}). % Not to be used after \cs{ExcludePreviousFile}. % \begin{macrocode} \newcommand*{\ClearUsedFile}[1]{% \probsoln@prev@cutoff=0\relax \@probsoln@readprev{#1}% % \end{macrocode} % Only write labels that aren't in the used file. % \begin{macrocode} \@for\@this@db:=\prob@databases\do{% {% \edef\@prev@list{\csname probsoln@prev@list@\@this@db\endcsname}% \ifdefempty{\@prev@list}% {}% {% \@for\@this@label:=\@prev@list\do{% \ifcsundef{@used@problem@\@this@db @\@this@label}% {% \immediate\write\probsoln@prev{% \string\previousproblem{\@this@label}{\@this@db}% {\csname @prev@problem@\@this@db @\@this@label\endcsname}}% }% {}% }% }% }% }% \immediate\closeout\probsoln@prev \immediate\closeout\probsoln@used \@disable@exclude@prev } % \end{macrocode} %\end{macro} % %\begin{macro}{\ExcludePreviousFile} %\changes{3.03}{2011/01/16}{new} % Exclude problems used in the last \meta{n} years. % \begin{macrocode} \newcommand*{\ExcludePreviousFile}[2][3]{% \probsoln@prev@cutoff=\probsoln@startyear\relax \advance\probsoln@prev@cutoff by -#1\relax \@probsoln@readprev{#2}% \@write@prev \def\ExcludePreviousFile[2][3]{\PackageError{probsoln}{Only one instance of \string\ExcludePreviousFile\space allowed}{You've already used this command. You are only allowed to use it once}}% \def\ClearUsedFile[1]{% \PackageError{probsoln}% {\string\ClearUsedFile\space may not be used after \string\ExcludePreviousFile}{}}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@probsoln@readprev} % Read contents of previous and used files and open for writing. % \begin{macrocode} \newcommand*{\@probsoln@readprev}[1]{% \@enable@exclude@prev \InputIfFileExists{#1}% {\PackageInfo{probsoln}% {Excluded problem file `#1' found}}% {\PackageInfo{probsoln}% {Excluded problem file `#1' not found. A new one will be created}}% \InputIfFileExists{\@probsoln@usedfilename}% {\PackageInfo{probsoln}% {Current problems file `\@probsoln@usedfilename' found}}% {\PackageInfo{probsoln}% {No current problem file `\@probsoln@usedfilename' found. A new one will be created}}% \immediate\openout\probsoln@prev=#1 \immediate\openout\probsoln@used=\@probsoln@usedfilename } % \end{macrocode} %\end{macro} % %\begin{macro}{\probsoln@prev@list} %\changes{3.03}{2011/01/16}{new} % Maintain a list of all previous problem labels: % \begin{macrocode} \newcommand*{\probsoln@prev@list@default}{} % \end{macrocode} %\end{macro} % %\begin{macro}{\@write@prev} %\changes{3.03}{2011/01/16}{new} % Write all previous labels to file. % \begin{macrocode} \newcommand*{\@write@prev}{% \@for\@this@db:=\prob@databases\do{% {% \edef\@prev@list{\csname probsoln@prev@list@\@this@db\endcsname}% \ifdefempty{\@prev@list}% {}% {% \@for\@this@label:=\@prev@list\do{% \immediate\write\probsoln@prev{% \string\previousproblem{\@this@label}{\@this@db}% {\csname @prev@problem@\@this@db @\@this@label\endcsname}}% }% }% }% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@enable@exclude@prev} %\changes{3.03}{2011/01/16}{new} % Enable commands for excluding previously selected problems. % \begin{macrocode} \newcommand*{\@enable@exclude@prev}{% % \end{macrocode} % Redefine macro that adds used problem to used problem file and % previous problem file. % \begin{macrocode} \renewcommand*{\@add@used@problem}[2]{% \immediate\write\probsoln@used{\string\usedproblem{##1}{##2}{\number\probsoln@startyear}}% \ifcsundef{@prev@problem@##2@##1}% {% \immediate\write\probsoln@prev{% \string\previousproblem{##1}{##2}{\number\probsoln@startyear}}% \expandafter\xdef\csname @prev@problem@##2@##1\endcsname{% \number\probsoln@startyear}% }% {% \expandafter\ifnum\csname @prev@problem@##2@##1\endcsname <\probsoln@startyear \immediate\write\probsoln@prev{% \string\previousproblem{##1}{##2}{\number\probsoln@startyear}}% \expandafter\xdef\csname @prev@problem@##2@##1\endcsname{% \number\probsoln@startyear}% \fi }% }% % \end{macrocode} % Redefine macro that fetches the exclusion list. (First argument is % the macro in which to store the list, the second argument is the % database.) % \begin{macrocode} \renewcommand*{\@fetch@excluded@list}[2]{% \def##1{}% \ifcsdef{probsoln@prev@list@##2}% {% \edef\@prev@list{\csname probsoln@prev@list@##2\endcsname}% \@for\@this@label:=\@prev@list\do{% % \end{macrocode} % If it isn't one of the used problems, it can be added to the % exclusion list: % \begin{macrocode} \ifcsundef{@used@problem@##2@\@this@label}% {% % \end{macrocode} % It isn't, so label can be added to the exclusion list: % \begin{macrocode} \ifcsempty{##1}% {\edef##1{\@this@label}}% {\edef##1{##1,\@this@label}}% }% {}% }% }% {}% }% % \end{macrocode} % Add new previous list for given database: % \begin{macrocode} \renewcommand*{\@add@newprevlist}[1]{% \expandafter\gdef\csname probsoln@prev@list@##1\endcsname{}% }% % \end{macrocode} % Redefine macro that closes the exclusion-related files. % \begin{macrocode} \renewcommand*{\close@probsoln@prev}{% \closeout\probsoln@prev \closeout\probsoln@used }% } % \end{macrocode} %\end{macro} %\begin{macro}{\@disable@exclude@prev} %\changes{3.03}{2011/01/16}{new} % Disable commands for excluding previously selected problems. % \begin{macrocode} \newcommand*{\@disable@exclude@prev}{% \renewcommand*{\@add@used@problem}[2]{}% \renewcommand*{\@fetch@excluded@list}[2]{\def##1{}}% \renewcommand*{\@add@newprevlist}[1]{}% \renewcommand*{\close@probsoln@prev}{}% } % \end{macrocode} %\end{macro} % % By default, the commands for excluding previously selected % problems are disabled. %\begin{macro}{\@add@used@problem} %\changes{3.03}{2011/01/16}{new} % Adds problem to used problems list. (First argument is the label, % the second argument is the database name.) % \begin{macrocode} \newcommand*{\@add@used@problem}[2]{} % \end{macrocode} %\end{macro} % %\begin{macro}{\@fetch@excluded@list} %\changes{3.03}{2011/01/16}{new} % Fetches the excluded list. (First argument macro in which to store % the list. The second argument is the database name.) % \begin{macrocode} \newcommand*{\@fetch@excluded@list}[2]{% \def#1{}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@add@newprevlist} %\changes{3.03}{2011/01/16}{new} % Adds a new previous list for the given database: % \begin{macrocode} \newcommand*{\@add@newprevlist}[1]{} % \end{macrocode} %\end{macro} % %\begin{macro}{\close@probsoln@prev} %\changes{3.03}{2011/01/16}{new} % Close file used for previous labels % \begin{macrocode} \newcommand*{\close@probsoln@prev}{} % \end{macrocode} %\end{macro} % % At the end of the document, close file if required: % \begin{macrocode} \AtEndDocument{\close@probsoln@prev} % \end{macrocode} % %\begin{macro}{\previousproblem} %\changes{3.03}{2011/01/16}{new} % Identifies problem that has been selected and the year it was % selected. (First argument label, second argument database name, % third argument year.) % \begin{macrocode} \newcommand*{\previousproblem}[3]{% \ifnum#3>\probsoln@prev@cutoff % \end{macrocode} % If data set hasn't been defined, define it: % \begin{macrocode} \ifcsundef{prob@db@#2}{\prob@newdb{#2}}{}% % \end{macrocode} % Define command that stores the year the problem was used: % \begin{macrocode} \expandafter\gdef\csname @prev@problem@#2@#1\endcsname{#3}% % \end{macrocode} % Add label to the previous list for this data set: % \begin{macrocode} \edef\@prev@list{\csname probsoln@prev@list@#2\endcsname}% \ifdefempty{\@prev@list}% {% \expandafter\xdef\csname probsoln@prev@list@#2\endcsname{#1}% }% {% \expandafter\xdef\csname probsoln@prev@list@#2\endcsname{% \@prev@list,#1}% }% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\usedproblem} %\changes{3.03}{2011/01/16}{new} % Don't want to exclude problems that were selected in the previous % run of this document for the current year, so they need to be % identified in the aux file. % \begin{macrocode} \newcommand*{\usedproblem}[3]{% \ifnum#3=\probsoln@startyear \expandafter\def\csname @used@problem@#2@#1\endcsname{#3}% \fi } % \end{macrocode} %\end{macro} % %\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{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} % %\begin{macro}{\prob@databases} % Store a list of all the defined data bases. % \begin{macrocode} \newcommand*{\prob@databases}{default} % \end{macrocode} %\end{macro} % Each defined database has a list of undisplayed solutions. % \begin{macrocode} \newcommand*{\prob@db@default@solutions}{} % \end{macrocode} % %\begin{macro}{\prob@newdb} %\begin{definition} %\cs{prob@newdb}\marg{name} %\end{definition} % Creates a new (empty) data base. % \begin{macrocode} \newcommand*{\prob@newdb}[1]{% \ifcsundef{prob@db@#1}% {% \expandafter\gdef\csname prob@db@#1\endcsname{}% \xdef\prob@databases{\prob@databases,#1}% \expandafter\gdef\csname prob@db@#1@solutions\endcsname{}% \@add@newprevlist{#1}% }% {% \PackageError{probsoln}{Data set `#1' is already defined}% {Data set names must be unique}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\prob@currentdb} % Keep a track of the current data base % \begin{macrocode} \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 }% }% } % \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} \ifcsempty{prob@db@#3}% {% \expandafter\xdef\csname prob@db@#3\endcsname{#1}% }% {% \expandafter\xdef\csname prob@db@#3\endcsname{% \csname prob@db@#3\endcsname,#1}% }% % \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} % %\subsection{Defining New Problems} %\begin{macro}{\prob@newproblem} %\changes{3.01}{2011/08/22}{added extra argument to supply defaults} %\begin{definition} %\cs{prob@newproblem}\marg{n}\marg{db %name}\marg{label}\marg{definition}\marg{default args} %\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{\prob@newproblem}[5]{% % \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 \expandafter\xdef\csname prob@db@#2\endcsname{% \csname prob@db@#2\endcsname,#3}% \fi % \end{macrocode} % If default arguments supplied, set them % \begin{macrocode} \ifx\@empty#5\@empty \else \edef\thisprob@currentdb{#2}% \edef\thisprob@currentlabel{#3}% \expandafter\@setdefaultprobargs\expandafter{#5}% \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. \csname @prob@getargs@eg@\romannumeral#1\endcsname):}% \read-1to\@tmp \expandafter\global\expandafter\let \csname prob@args@#2@#3\endcsname=\@tmp } \def\@prob@getargs@eg@i{{12}} \def\@prob@getargs@eg@ii{{5}{3}} \def\@prob@getargs@eg@iii{{4}{5}{2}} \def\@prob@getargs@eg@iv{{5}{3}{10}{8}} \def\@prob@getargs@eg@v{{5}{3}{10}{8}{4}} \def\@prob@getargs@eg@vi{{5}{3}{10}{8}{4}{24}} \def\@prob@getargs@eg@vii{{5}{3}{10}{8}{4}{24}{32}} \def\@prob@getargs@eg@viii{{5}{3}{10}{8}{4}{24}{32}{9}} \def\@prob@getargs@eg@ix{{5}{3}{10}{8}{4}{24}{32}{9}{2}} % \end{macrocode} %\end{macro} %\begin{macro}{\@prob@do@getargs} % \begin{macrocode} \let\@prob@do@getargs\@prob@gobblethree % \end{macrocode} %\end{macro} % %\begin{macro}{\setprobargs} %\begin{definition} %\cs{setprobargs}\oarg{db name}\marg{label}\marg{args} %\end{definition} % Sets the arguments for the given problem. Each of the arguments % within \meta{args} should be grouped, e.g. % "\setprobargs{label}{{5}{3}}". Inner braces are still required if % there is only one argument, e.g. "\setprobargs{label}{{25}}" % \begin{macrocode} \newcommand*{\setprobargs}[3][default]{% \expandafter\gdef\csname prob@args@#1@#2\endcsname{#3}% } % \end{macrocode} %\end{macro} % %\begin{macro}{\@setdefaultprobargs} % Like \cs{setprobargs} but only sets the arguments if % \ics{usedefaultprobargstrue}. The database is given % by \cs{thisprob@currentdb} (the current database) and % the problem label is given by \cs{thisprob@currentlabel}. % This command should only be used within \env{defproblem}. % \begin{macrocode} \newcommand*{\@setdefaultprobargs}[1]{% \ifusedefaultprobargs \setprobargs[\thisprob@currentdb]{\thisprob@currentlabel}{#1}% \fi } % \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 \if@prob@fragile \obeylines\obeyspaces \@makeother\# \@makeother\% \fi \@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} %\changes{3.01}{2011/08/22}{modified to allow for floats in the body of the %environment} % \begin{macrocode} \long\def\long@addto@envbody#1{% \toks@{#1}% \edef\@psn@tmp{\the\@envbody\the\toks@}% \global\@envbody\@xp{\@psn@tmp}% } % \end{macrocode} %\end{macro} %\begin{macro}{\long@collect@@body} % \begin{macrocode} \long\def\long@collect@@body#1\end#2{% % \end{macrocode} %\changes{3.01}{2011/08/22}{changed \cs{edef} to \cs{protected@edef}} % \begin{macrocode} \protected@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} % % Fragile contents are sanitized, written to file and read back in. % However, we don't want the new line character sanitized. Also, % the \env{verbatim} environment doesn't like a space after % \cs{begin} or \cs{end}, so these need to be replaced. %\begin{macro}{\@char@M} %\changes{3.02}{2011/12/10}{new} % First define a macro that contains the % newline marker: % \begin{macrocode} {\obeylines \gdef\@char@M{^^M}% } \@onelevel@sanitize\@char@M % \end{macrocode} %\end{macro} % %\begin{macro}{\@beg@env@string} %\changes{3.02}{2011/12/10}{new} % Define a macro that contains the begin environment marker: % \begin{macrocode} \def\@beg@env@string{\begin} \@onelevel@sanitize\@beg@env@string % \end{macrocode} %\end{macro} %\begin{macro}{\@end@env@string} %\changes{3.02}{2011/12/10}{new} % Define a macro that contains the end environment marker: % \begin{macrocode} \def\@end@env@string{\end} \@onelevel@sanitize\@end@env@string % \end{macrocode} %\end{macro} % %\begin{macro}{\def@replace@markers} %\changes{3.02}{2011/12/10}{new} % Things start to get a bit complicated here. The substitution % macros need the markers as part of their definition. The easiest % way to do this is to define a command (using \cs{edef}) that defines the % substitution macros. The markers and replacements are the only % things to be expanded. % \begin{macrocode} \edef\def@replace@markers{% % \end{macrocode} % First define the command that replaces the newline marker: % \begin{macrocode} \noexpand\def\noexpand\do@replace@charM##1\@char@M##2\noexpand\end@replace@marker{% \noexpand\expandafter\noexpand\toks@\noexpand\expandafter{\noexpand\replace@text}% \noexpand\ifx\noexpand\relax##2\noexpand\relax \noexpand\edef\noexpand\replace@text{\noexpand\the\noexpand\toks@##1}% \noexpand\let\noexpand\do@replacenext\noexpand\replace@mark@noop \noexpand\else \noexpand\edef\noexpand\replace@text{\noexpand\the\noexpand\toks@##1^^J}% \noexpand\let\noexpand\do@replacenext\noexpand\do@replace@charM \noexpand\fi \noexpand\do@replacenext##2\noexpand\end@replace@marker }% % \end{macrocode} % Next define the command that replaces the begin environment marker: % \begin{macrocode} \noexpand\def\noexpand\doreplace@begverb##1\@beg@env@string##2\noexpand\end@replace@marker{% \noexpand\expandafter\noexpand\toks@\noexpand\expandafter{\noexpand\replace@text}% \noexpand\ifx\noexpand\relax##2\noexpand\relax \noexpand\edef\noexpand\replace@text{\noexpand\the\noexpand\toks@##1}% \noexpand\let\noexpand\do@replacenext\noexpand\replace@mark@noop \noexpand\else \noexpand\edef\noexpand\replace@text{\noexpand\the\noexpand\toks@ ##1\expandafter\@gobble\string\\begin}% \noexpand\let\noexpand\do@replacenext\noexpand\doreplace@begverb \noexpand\fi \noexpand\do@replacenext##2\noexpand\end@replace@marker }% % \end{macrocode} % Next define the command that replaces the end environment marker: % \begin{macrocode} \noexpand\def\noexpand\doreplace@endverb##1\@end@env@string##2\noexpand\end@replace@marker{% \noexpand\expandafter\noexpand\toks@\noexpand\expandafter{\noexpand\replace@text}% \noexpand\ifx\noexpand\relax##2\noexpand\relax \noexpand\edef\noexpand\replace@text{\noexpand\the\noexpand\toks@##1}% \noexpand\let\noexpand\do@replacenext\noexpand\replace@mark@noop \noexpand\else \noexpand\edef\noexpand\replace@text{\noexpand\the\noexpand\toks@ ##1\expandafter\@gobble\string\\end}% \noexpand\let\noexpand\do@replacenext\noexpand\doreplace@endverb \noexpand\fi \noexpand\do@replacenext##2\noexpand\end@replace@marker }% % \end{macrocode} % Finally, define a higher-level command that calls all three of the above: % \begin{macrocode} \noexpand\def\noexpand\replace@markers##1{% \noexpand\def\noexpand\replace@text{}% \noexpand\expandafter\noexpand\do@replace@charM##1\@char@M\relax\noexpand\end@replace@marker \noexpand\let##1\noexpand\replace@text \noexpand\def\noexpand\replace@text{}% \noexpand\expandafter\noexpand\doreplace@begverb##1\@beg@env@string\relax\noexpand\end@replace@marker \noexpand\let##1\noexpand\replace@text \noexpand\def\noexpand\replace@text{}% \noexpand\expandafter\noexpand\doreplace@endverb##1\@end@env@string\relax\noexpand\end@replace@marker \noexpand\let##1\noexpand\replace@text } } % \end{macrocode} % Define the substitution loop terminator: % \begin{macrocode} \def\replace@mark@noop#1\end@replace@marker{} % \end{macrocode} % Now define all the marker substitution macros: % \begin{macrocode} \def@replace@markers % \end{macrocode} %\end{macro} % %\begin{environment}{defproblem} %\changes{3.01}{2011/08/22}{added second optional argument} %\changes{3.02}{2011/12/11}{added key-val optional argument} %\begin{definition} %"\begin{defproblem}"\oarg{n}\oarg{default args}\marg{label}\oarg{key-val options} %\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}[1][0]{% \edef\@prob@currentargN{\number0#1}% \@defproblem@beginenv }{} % \end{macrocode} % Gather second optional argument and mandatory argument: % \begin{macrocode} \newcommand*{\@defproblem@beginenv}[2][]{% \def\@prob@currentdefaultargs{#1}% \def\@prob@currentlabel{#2}% \@defproblem@beginenv@ } % \end{macrocode} % Get final optional argument and process % \begin{macrocode} \newcommand*{\@defproblem@beginenv@}[1][]{% \setkeys{probsoln}{#1}% \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]{% \if@prob@fragile \probsoln@process@fragile{#1}% \protected@edef\do@def@new@problem{% \noexpand\prob@newproblem {\@prob@currentargN}% {\prob@currentdb}% {\@prob@currentlabel}% {% \noexpand\probsoln@write@tmp{\@prob@tmp@problem}% \noexpand\probsoln@read@tmp }% {\@prob@currentdefaultargs}% }% \else \toks@{#1}% \protected@edef\do@def@new@problem{% \noexpand\prob@newproblem {\@prob@currentargN}% {\prob@currentdb}% {\@prob@currentlabel}% {\the\toks@}% {\@prob@currentdefaultargs}% }% \fi \do@def@new@problem } % \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}[1][]{% \setkeys{probsoln}{#1}% \long@collect@body\do@onlysolution }{} % \end{macrocode} %\end{environment} %\begin{macro}{\do@onlysolution} %\changes{3.02}{2011/12/10}{added \cs{probsoln@do@body}} % \begin{macrocode} \newcommand{\do@onlysolution}[1]{% \ifshowanswers \probsoln@do@body{#1}% \fi % \end{macrocode} % Add to the list of solutions % \begin{macrocode} \@ifundefined{@prob@currentlabel} {}% {% \expandafter \psn@add@unique@label \csname prob@db@\prob@currentdb @solutions\endcsname{% \@prob@currentlabel }% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\psn@add@unique@label} %\changes{3.01}{2011/08/22}{new} %\begin{definition} %\cs{psn@add@unique@label}\marg{list cs}\marg{label} %\end{definition} % Globally adds label to list if not already in list. % \begin{macrocode} \newcommand*{\psn@add@unique@label}[2]{% \ifx#1\@empty \xdef#1{#2}% \else \edef\@tmp@label{#2}% \expandafter\DTLifinlist\expandafter{\@tmp@label}{#1}% {}% ignore {\xdef#1{#1,\@tmp@label}}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\DTLifinlist} % This is defined in \sty{datatool}, but there's no sense loading % the entire package just for this, so define if not already % defined. %\changes{3.01}{2011/08/22}{new} % \begin{macrocode} \providecommand{\DTLifinlist}[4]{% \def\@dtl@doifinlist##1,#1,##2\end@dtl@doifinlist{% \def\@before{##1}% \def\@after{##2}% }% \expandafter\@dtl@doifinlist\expandafter,#2,#1,\@nil \end@dtl@doifinlist \ifx\@after\@nnil % not found #4% \else % found #3% \fi } % \end{macrocode} %\end{macro} % %\begin{environment}{onlyproblem} % Define an environment that only displays its contents if the % solutions should not be displayed. %\changes{3.02}{2011/12/10}{added optional argument.} % \begin{macrocode} \newenvironment{onlyproblem}[1][]{% \setkeys{probsoln}{#1}% \long@collect@body\do@onlyproblem }{} % \end{macrocode} %\end{environment} %\begin{macro}{\do@onlyproblem} %\changes{3.02}{2011/12/10}{added \cs{probsoln@do@body}} % \begin{macrocode} \newcommand{\do@onlyproblem}[1]{% \ifshowanswers \else \probsoln@do@body{#1}% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\probsoln@do@body} % Either does argument or sanitizes, writes and reads. %\changes{3.02}{2011/12/10}{new} % \begin{macrocode} \newcommand{\probsoln@do@body}[1]{% \if@prob@fragile \probsoln@process@fragile{#1}% \probsoln@write@tmp{\@prob@tmp@problem}% \probsoln@read@tmp \else #1% \fi } % \end{macrocode} %\end{macro} % %\begin{macro}{\probsoln@process@fragile} % Sanitizes and replaces markers. Result stored in % \cs{@prob@tmp@problem} %\changes{3.02}{2011/12/10}{new} % \begin{macrocode} \newcommand{\probsoln@process@fragile}[1]{% \def\@prob@tmp@problem{#1}% \@onelevel@sanitize\@prob@tmp@problem \replace@markers\@prob@tmp@problem } % \end{macrocode} %\end{macro} % %\begin{macro}{\probsoln@write@tmp} %\changes{3.02}{2011/12/10}{new} % Writes argument to temporary file (including opening and closing % file.) % \begin{macrocode} \newcommand{\probsoln@write@tmp}[1]{% \immediate\openout\probsoln@write=\ProbSolnFragileFile.\ProbSolnFragileExt \immediate\write\probsoln@write{#1}% \immediate\closeout\probsoln@write } % \end{macrocode} %\end{macro} % %\begin{macro}{\probsoln@read@tmp} %\changes{3.02}{2011/12/10}{new} % Inputs temporary file. % \begin{macrocode} \newcommand{\probsoln@read@tmp}{% \input{\ProbSolnFragileFile.\ProbSolnFragileExt}% } % \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. %\changes{3.01}{2011/08/22}{changed \cs{@next} to \cs{@useprob@next}} % \begin{macrocode} \newcommand{\useproblem}[2][default]{% \def\@prob@currentlabel{#2}% \def\prob@currentdb{#1}% \prob@showdraftlabel{#1}{#2}% \@add@used@problem{#2}{#1}% \let\@useprob@next=\relax \@ifundefined{prob@data@#1@#2}% {% \PackageError{probsoln}% {Problem `#2' is not defined in data set `#1'}{}% }% {% \def\@useprob@next{\csname prob@data@#1@#2\endcsname}% }% \@useprob@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}.) %\changes{3.01}{2011/08/22}{replaced \cs{IFSubStringInString} with %\cs{DTLifinlist}} % \begin{macrocode} \newcommand{\prob@do@selectedproblem}[1]{% \expandafter\DTLifinlist\expandafter{\@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@do@exceptedproblem} % Only define problem if the label isn't listed in % \cs{prob@selectedlabels}. (The current label is % given by \cs{@prob@currentlabel}.) % \begin{macrocode} \newcommand{\prob@do@exceptedproblem}[1]{% \expandafter\DTLifinlist\expandafter{\@prob@currentlabel}{\prob@selectedlabels}% {}% {% \prob@do@newproblem{#1}% }% } % \end{macrocode} %\end{macro} % %\begin{macro}{\loadexceptproblems} %\begin{definition} %\cs{loadexceptproblems}\oarg{db name}\marg{list}\marg{filename} %\end{definition} % Loads only those problems whose labels are not listed in % \meta{list}. %\changes{3.01}{2011/08/22}{new} % \begin{macrocode} \newcommand{\loadexceptproblems}[3][default]{% \bgroup \let\par\relax \edef\prob@currentdb{#1}% \edef\prob@selectedlabels{#2}% \let\prob@do@defproblem=\prob@do@exceptedproblem \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}{\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}. %\changes{3.03}{2011/01/16}{fetch exclusion list} % \begin{macrocode} \newcommand{\loadrandomproblems}[3][default]{% \@fetch@excluded@list{\@excl@list}{#1}% \@loadrandomproblems{#1}{#2}{#3}{\@excl@list}% } % \end{macrocode} %\end{macro} %\begin{macro}{\loadrandomexcept} %\begin{definition} %\cs{loadrandomexcept}\oarg{db %name}\marg{n}\marg{filename}\marg{exception list} %\end{definition} % Loads \meta{n} randomly selected problems from \meta{filename}, % excluding labels listed in \meta{exception list}. % \begin{macrocode} \newcommand{\loadrandomexcept}[4][default]{% \@loadrandomproblems{#1}{#2}{#3}{#4}% } % \end{macrocode} %\end{macro} %\begin{macro}{\@loadrandomproblems} % Internal workings of \cs{loadrandomproblems} and % \cs{loadrandomexcept}. % 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}[4]{% \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 % \end{macrocode} %\changes{3.05}{2017/07/10}{allow comma-separated list of file names} %Allow a comma-separated list of file names. % \begin{macrocode} \@for\@thisfile:=#3\do{\input{\@thisfile}}% % \end{macrocode} % Shuffle labels. % \begin{macrocode} \@probselN=0\relax \@for\@thislabel:=\prob@selectedlabels\do{% % \end{macrocode} %\changes{3.03}{2011/01/16}{ensure arguments expanded in %\cs{DTLifinlist}} % \begin{macrocode} \edef\@if@in@list{\noexpand\DTLifinlist{\@thislabel}{#4}}% \@if@in@list {}% {% \advance\@probselN by 1\relax \expandafter \edef\csname @prob@tmp@\romannumeral\@probselN\endcsname{% \@thislabel}% }% }% % \end{macrocode} %\changes{3.03}{2012/01/16}{added exclusion list to warning messages} % \begin{macrocode} \edef\@do@excludedlist{#4}% \ifdefempty{\@do@excludedlist}% {}% {\def\@do@excludedlist{(Excluded list: #4.) }}% % \end{macrocode} %\changes{3.03}{2012/01/16}{added check for 0 available problems} % \begin{macrocode} \ifnum\@probselN=0\relax \PackageWarning{probsoln}{You have requested \number#2\space\space problem(s) but there are no available problems in `#3'. \@do@excludedlist No problems will be selected}% \else \shuffle{@prob@tmp@}{\@probselN}% \ifnum\@probselN<#2\relax % \end{macrocode} %\changes{3.01}{2011/08/22}{changed error to warning} % \begin{macrocode} \ifnum\@probselN=1\relax \PackageWarning{probsoln}{You have requested \number#2\space\space problem(s) but there is only 1 problem available in `#3'. \@do@excludedlist Only 1 problem will be selected}% \else \PackageWarning{probsoln}{You have requested \number#2\space\space problem(s) but there are only \number\@probselN\space problems available in `#3'. \@do@excludedlist Only \number\@probselN\space problems will be selected}% \fi \else \@probselN=#2\relax \fi \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} \let\prob@do@defproblem=\prob@do@selectedproblem \firstpassfalse \@for\@thisfile:=#3\do{\input{\@thisfile}}% % \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} % %\begin{macro}{\foreachsolution} %\begin{definition} %\cs{foreachsolution}\oarg{db name}\marg{body} %\end{definition} % Does \meta{body} for each problem defined in the data base % \meta{db name} that has a solution contained within % \env{onlysolution}. 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{\foreachsolution}[2][default]{% \@ifundefined{prob@db@#1}{% \PackageError{probsoln}{Data base `#1' is not defined}{}% }{% \expandafter\let\expandafter\@tmp\csname prob@db@#1@solutions\endcsname \@for\thisproblemlabel:=\@tmp\do{% \ifx\thisproblemlabel\@empty \else \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% \fi }% }% } % \end{macrocode} %\end{macro} % %\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 \newcount\r@ndcur \newcount\@ps@randtmp \r@ndcur=1\relax % \end{macrocode} %\begin{macro}{\PSNrandseed} % Set the random generator seed % \begin{macrocode} \newcommand*{\PSNrandseed}[1]{% \ifnum#1=0\relax \PackageWarning{probsoln}{Can't have 0 as random seed, changing to 1}% \global\r@ndcur=1\relax \else \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} \newcommand*{\PSNrand}{% \@ps@randtmp=\r@ndcur \multiply\@ps@randtmp by 16811\relax \r@ndcur=\@ps@randtmp \global\divide\r@ndcur by 39989\relax \global\multiply\r@ndcur by 39989\relax \advance\@ps@randtmp by -\r@ndcur \global\r@ndcur = \@ps@randtmp \ifnum\r@ndcur=0\relax \global\r@ndcur=1\relax \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\PSN@old@rand} % Random generator used in v3.0 and earlier % \begin{macrocode} \newcommand*{\PSN@old@rand}{% \@ps@randtmp=\r@ndcur \multiply\@ps@randtmp by 16807\relax \r@ndcur=\@ps@randtmp \global\divide\r@ndcur by 120001\relax \global\multiply\r@ndcur by 120001\relax \advance\@ps@randtmp by -\r@ndcur \global\r@ndcur = \@ps@randtmp \ifnum\r@ndcur=0\relax \global\r@ndcur=1\relax \fi } % \end{macrocode} %\end{macro} %\begin{macro}{\PSNuseoldrandom} % Use the old random number generator % \begin{macrocode} \newcommand*{\PSNuseoldrandom}{% \let\PSNrand\PSN@old@rand } % \end{macrocode} %\end{macro} % %\begin{macro}{\PSNrandom} %\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]{% % \end{macrocode} % generate new random number. % \begin{macrocode} \PSNrand #1=\r@ndcur \@ps@randtmp=\r@ndcur % \end{macrocode} % now set \meta{count} to (\meta{count} mod \meta{n}) + 1 % \begin{macrocode} \divide\@ps@randtmp by #2\relax \multiply\@ps@randtmp by #2\relax \advance#1 by -\@ps@randtmp \advance#1 by 1\relax } % \end{macrocode} %\end{macro} %\begin{macro}{\random} %\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} \newcommand{\random}[3]{% \ifnum#2=1\relax \PSNrandom{\value{#1}}{#3}% \else \@rndselctr=#3% \advance\@rndselctr by -#2\relax \advance\@rndselctr by 1\relax \PSNrandom{\value{#1}}{\@rndselctr}% \addtocounter{#1}{#2}% \addtocounter{#1}{-1}% \fi } % \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. % \begin{macrocode} \newcount\@shfctr \newcount\@shfA \newcount\@shfB \newcommand{\shuffle}[2]{% \@shfctr=1\relax \whiledo{\@shfctr < 101}% {% \PSNrandom{\@shfA}{#2}\PSNrandom{\@shfB}{#2}% \ifnum\@shfA=\@shfB \else \edef\@@tmpA{\csname#1\romannumeral\@shfA\endcsname}% \let\@tmpA=\@@tmpA \edef\@@tmpB{\csname#1\romannumeral\@shfB\endcsname}% \let\@tmpB=\@@tmpB \expandafter\xdef\csname#1\romannumeral\@shfA\endcsname{\@tmpB}% \expandafter\xdef\csname#1\romannumeral\@shfB\endcsname{\@tmpA}% \fi \advance\@shfctr by 1\relax }% } % \end{macrocode} %\end{macro} %\begin{macro}{\doforrandN} %\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}{% %\loadrandomproblems{1}{\tmp}} %\end{verbatim} % %\changes{3.03}{}{added count register to keep track of level to %allow for nested loops} % \begin{macrocode} \newcount\@ps@forrand \newcount\@ps@forrand@level \newcommand{\doforrandN}[4]{% \global\advance\@ps@forrand@level by 1\relax {% \@ps@forrand=0\relax \@for#2:=#3\do{% \advance\@ps@forrand by 1\relax \expandafter \edef\csname @doforrandN@\number\@ps@forrand@level @\romannumeral\@ps@forrand\endcsname{#2}% }% \ifnum\@ps@forrand<#1\relax \PackageError{probsoln}{Can't randomly select \number#1\space item(s)}{You have requested \number#1\space item(s), but there are only \number\@ps@forrand\space item(s) in the list: #3}% \else \shuffle{@doforrandN@\number\@ps@forrand@level @}{\@ps@forrand}% \ifnum#1>0\relax \@ps@forrand=0\relax \loop \advance\@ps@forrand by 1\relax \edef#2{\csname @doforrandN@\number\@ps@forrand@level @\romannumeral\@ps@forrand\endcsname}% #4% \ifnum\@ps@forrand<#1\relax \repeat \fi \fi }% \global\advance\@ps@forrand@level by -1\relax } % \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} %\changes{3.01}{2011/08/22}{added second optional argument} % Defines a new problem. % \begin{macrocode} \newcommand*{\newproblem}{\@ifstar\@snewproblem\@newproblem} % \end{macrocode} %\end{macro} %\begin{macro}{\@snewproblem} % Store first optional argument % \begin{macrocode} \newcommand{\@snewproblem}[1][0]{% \def\@newprob@argN{#1}% \@s@newproblem }% % \end{macrocode} %\end{macro} %\begin{macro}{\@s@newproblem} % Define a new problem without a solution % \begin{macrocode} \newcommand{\@s@newproblem}[3][]{% \begin{defproblem}[\@newprob@argN][#1]{#2}% #3% \end{defproblem}% } % \end{macrocode} %\end{macro} %\begin{macro}{\@newproblem} % Store first optional argument % \begin{macrocode} \newcommand{\@newproblem}[1][0]{% \def\@newprob@argN{#1}% \@ns@newproblem } % \end{macrocode} %\end{macro} %\begin{macro}{\@ns@newproblsm} % Define problem with a solution: % \begin{macrocode} \newcommand{\@ns@newproblem}[4][]{% \begin{defproblem}[\@newprob@argN][#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} %\changes{3.01}{2011/08/22}{added space after solution tag} % \begin{macrocode} \@ifundefined{solution}{% \newenvironment{solution}{\par\noindent\textbf{\solutionname:}\space \ignorespaces}{}% }{} % \end{macrocode} %\end{environment} %\begin{macro}{\solutionname} % \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} %\changes{2012/08/23}{3.04}{fixed bug that interfered with depth counter} % \begin{macrocode} \newenvironment{textenum}{% \ifnum\@enumdepth>\thr@@ \@toodeep \else \advance\@enumdepth by 1\relax \edef\@enumctr{enum\romannumeral\the\@enumdepth}% \let\@item\@textitem \def\@itemlabel{% \refstepcounter{\@enumctr}% \csname label\@enumctr\endcsname }% \setcounter{\@enumctr}{0}% \fi \ignorespaces }% {% } % \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} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*sample-exclude.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain \documentclass[a4paper]{article} \usepackage{probsoln} %uncomment the following line to display the answers %\showanswers % Set the academic year to be 2011/12 (if omitted assume current % academic year): \SetStartYear{2011} % Set the seed for the random number generator: \PSNrandseed{\GetStartYear} % Exclude problems that have been used this year or the previous % two academic years. (Creates a file called 'excluded.tex' to % store labels of used problems. Also creates a file called % \jobname.prb that stores labels of problems used in this % document, so they don't get excluded on subsequent runs.) \ExcludePreviousFile[3]{excluded} % To clear the used problems file (\jobname.prb) of the labels % generated in the previous run, comment the above and uncomment % below: % \ClearUsedFile{excluded} % Load 1 problem randomly selected from the given file % and store in database 'firstprinciples': \loadrandomproblems[firstprinciples]{1}{prob-1stprncp} % Load 5 problems randomly selected from the given file % and store in database 'easy': \loadrandomproblems[easy]{5}{prob-easy} % Load 2 problems randomly selected from the given file % and store in database 'implicit': \loadrandomproblems[implicit]{2}{prob-implicit} % Load 2 problems randomly selected from the given file % and store in database 'probspaces': \loadrandomproblems[probspaces]{2}{prob-probspaces} % Load 1 problem randomly selected from the given file % and store in database 'mchoice': \loadrandomproblems[mchoice]{1}{prob-mchoice} % Load 1 problem randomly selected from the given file % and store in database 'nosoln': \loadrandomproblems[nosoln]{1}{prob-nosoln} \begin{document} \title{Sample Problem Sheet} \author{Nicola Talbot} \maketitle \begin{enumerate} % Differentiation from first principles \foreachproblem[firstprinciples]{\item \thisproblem} \item Differentiate the following functions: \begin{enumerate} \foreachproblem[easy]{\item \thisproblem} \end{enumerate} % Implicit differentiation \foreachproblem[implicit]{\item \thisproblem} % Finite probability spaces \foreachproblem[probspaces]{\item \thisproblem} % Multiple choice question \foreachproblem[mchoice]{\item \thisproblem} % select one essay style question that doesn't come with a solution \foreachproblem[nosoln]{\item \thisproblem} \end{enumerate} \end{document} % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*sample.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain \documentclass[a4paper]{article} \usepackage{probsoln} % uncomment the following line to display the answers % \showanswers % The following will generate a different set of % problems each year %\PSNrandseed{\year} % Load 1 problem randomly selected from the given file % and store in database 'firstprinciples': \loadrandomproblems[firstprinciples]{1}{prob-1stprncp} % Load 5 problems randomly selected from the given file % and store in database 'easy': \loadrandomproblems[easy]{5}{prob-easy} % Load 2 problems randomly selected from the given file % and store in database 'implicit': \loadrandomproblems[implicit]{2}{prob-implicit} % Load 2 problems randomly selected from the given file % and store in database 'probspaces': \loadrandomproblems[probspaces]{2}{prob-probspaces} % Load 1 problem randomly selected from the given file % and store in database 'mchoice': \loadrandomproblems[mchoice]{1}{prob-mchoice} % Load 1 problem randomly selected from the given file % and store in database 'nosoln': \loadrandomproblems[nosoln]{1}{prob-nosoln} \begin{document} \title{Sample Problem Sheet} \author{Nicola Talbot} \maketitle \begin{enumerate} % Differentiation from first principles \foreachproblem[firstprinciples]{\item \thisproblem} \item Differentiate the following functions: \begin{enumerate} \foreachproblem[easy]{\item \thisproblem} \end{enumerate} % Implicit differentiation \foreachproblem[implicit]{\item \thisproblem} % Finite probability spaces \foreachproblem[probspaces]{\item \thisproblem} % Multiple choice question \foreachproblem[mchoice]{\item \thisproblem} % select one essay style question that doesn't come with a solution \foreachproblem[nosoln]{\item \thisproblem} \end{enumerate} \end{document} % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*sample2.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain \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}{prob-1stprncp,prob-implicit}{\selectrandomly{\file}{\value{numproblems}}} \item Differentiate the following functions: \input{prob-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} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*sample3.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain \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{prob-tabmchoice}{2} \end{longtable} \end{document} % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*sample4.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain \documentclass[a4paper]{article} \usepackage{probsoln} % Sample file illustrating use of \loadallproblems % All problems defined in specified file will be used % in order of definition \loadallproblems{prob-easy} %\loadselectedproblems{diffeasy:gpowh,diffeasy:arccos}{prob-easy} %\loadexceptproblems{diffeasy:gpowh,diffeasy:arccos}{prob-easy} \showanswers \begin{document} Differentiate the following functions: \begin{enumerate} \foreachproblem{\item \thisproblem} \end{enumerate} \end{document} % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*sample5.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain \documentclass[a4paper]{report} \usepackage{probsoln} \begin{document} \hideanswers \chapter{Easy Problems} \loadrandomproblems[easyproblems]{5}{prob-easy2} \renewcommand{\theenumi}{\thechapter.\arabic{enumi}} \begin{enumerate} \foreachproblem[easyproblems]{\item\label{prob:\thisproblemlabel}\thisproblem} \end{enumerate} \chapter{Probability Spaces} \loadrandomproblems[probspaces]{2}{prob-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} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*sample6.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} \documentclass{article} \usepackage[usedefaultargs]{probsoln} \loadallproblems{prob-args} \begin{document} \begin{enumerate} \foreachproblem{\item \thisproblem} \end{enumerate} \end{document} % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*sample7.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} \documentclass{article} \usepackage{tikz} \usepackage{probsoln} \loadallproblems{prob-mixed} \begin{document} \section{Exercises} \begin{enumerate} \foreachproblem{\item\label{q-\thisproblemlabel} \thisproblem} \end{enumerate} \section{Solutions} \showanswers \begin{enumerate} \foreachsolution{\item[\ref{q-\thisproblemlabel}] \thisproblem} \end{enumerate} \end{document} % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*sample8.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} \documentclass{article} \usepackage{listings} \usepackage{probsoln} \setkeys{probsoln}{fragile} \loadallproblems{prob-verb} \showanswers \begin{document} \begin{enumerate} \foreachproblem{\item \thisproblem} \end{enumerate} \end{document} % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*sample9.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain \documentclass[a4paper]{article} \usepackage{probsoln} % uncomment the following line to display the answers % \showanswers % Load 10 problems randomly selected from the given files \loadrandomproblems{10}{prob-1stprncp,prob-easy,prob-implicit,prob-probspaces} \begin{document} \title{Sample Problem Sheet} \author{Nicola Talbot} \maketitle \begin{enumerate} \foreachproblem{\item \thisproblem} \end{enumerate} \end{document} % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*prob-1stprncp.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain % % These problems 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} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*prob-args.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain % % These problems require arguments % % Arguments: #1->a_2, #2->a_1 and #3->a_0 % (Arguments must be integers) \newcount\ctr \newproblem[3][{1}{2}{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 \) } \begin{defproblem}[1][{6}]{diff:sin} \begin{onlyproblem} \(f(x) = \sin(#1x)\) \end{onlyproblem} \begin{onlysolution} \(f'(x) = #1\cos(#1x)\) \end{onlysolution} \end{defproblem} % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*prob-easy.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain % % 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}\]} \newproblem{diffeasy:exp4x}{% $y = \exp(4x)$ }% {% \[\frac{dy}{dx} = 4\exp(4x)\] } \newproblem{diffeasy:exp3x+2}{% $y = \exp(3x+2)$ }% {% \[\frac{dy}{dx} = 3\exp(3x+2)\] } \newproblem{diffeasy:cubic}{% $y=x^3 + 4x^2 - x + 3$ }% {% \[\frac{dy}{dx} = 3x^2 + 8x - 1\] } \newproblem{diffeasy:quad}{% $y=2x^3 + 6x -1$ }% {% \[\frac{dy}{dx} = 6x + 6 = 6(x+1)\] } % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*prob-easy2.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain % % 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} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*prob-implicit.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain % % 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:ellipse}{% Find the gradient of the ellipse given by $4x^2 + 3y^2 = 25$.}{% Differentiating with respect to $x$ gives: \begin{eqnarray*} 8x + 6y\frac{dy}{dx} & = & 0\\ \frac{dy}{dx} & = & \frac{-8x}{6y}\\ & = & \frac{-4x}{\sqrt{25-4x^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} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*prob-mchoice.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain % % These problems are for multiple choice questions \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} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*prob-mixed.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain % % These problems are a mixture of essay-style and questions with % answers. One of these problems requires the tikz package \newproblem*{oop}{Describe what is meant by object-oriented programming.} \begin{defproblem}{inheritance} Describe what is meant by the term \emph{inheritance} in object-oriented programming. Use examples. \end{defproblem} \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} \begin{defproblem}{digraph} \begin{onlyproblem}\label{ex:digraph} Identify, if any, the sinks and sources of the digraph shown in Figure~\ref{fig:digraph}. \begin{figure}[tbh] \centering \begin{tikzpicture}[every node/.style={draw,circle}] \path (0,0) node (A) {$A$} (1,0) node (B) {$B$} (0,1) node (C) {$C$}; \draw[->] (A) -- (B); \draw[->] (B) -- (C); \draw[->] (A) -- (C); \end{tikzpicture} \par \caption{Digraph for Question~\ref{ex:digraph}} \label{fig:digraph} \end{figure} \end{onlyproblem} \begin{onlysolution} $A$ is a souce and $C$ is a sink. \end{onlysolution} \end{defproblem} % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*prob-newdata.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain \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} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*prob-nosoln.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain % % 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} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*prob-probspaces.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain % % 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} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*prob-probspaces2.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain % % 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} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*prob-tabmchoice.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % This file is public domain % % 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} % % \end{macrocode} %\fi %\iffalse % \begin{macrocode} %<*prob-verb.tex> % \end{macrocode} %\fi %\iffalse % \begin{macrocode} \begin{defproblem}{code-helloworld} This problem has a code fragment. \begin{onlyproblem} \lstset{language=Java} \begin{lstlisting} public class HelloWorld { public static void main(String[] args) { System.out.println("Hello World!"); } } \end{lstlisting} \end{onlyproblem} \begin{onlysolution} \lstset{language=Java} \begin{lstlisting} public class HelloWorld { public static void main(String[] args) { System.out.println("Hello " + (args.length==0 ? "anon" : args[0])+"!"); } } \end{lstlisting} \end{onlysolution} \end{defproblem} % \end{macrocode} %\fi %\iffalse % \begin{macrocode} % % \end{macrocode} %\fi %\Finale \endinput