I agree that the documentation of the answers
package is a bit on the terse side. I don't find the exercise
documentation to be very difficult; it can do a lot of things, but is quite well documented, I think. I've never used probsoln
so I won't comment further on that.
Since you ask about the answers
package specifically, here is my attempt at explaining the package, and clarifying at least the simple example given in the documentation.
First, the basic command \Newassociation{xxx}{yyy}{zzz}
does the following things:
- It creates an environment
{xxx}
to be used in your document for the solutions within the problems themselves. This environment will generally not be displayed unless the [nosolutionfiles]
option chosen when the package is loaded.
- It creates an environment
{yyy}
which is the environment that will be used to display the solutions. These solutions are written to a separate file (or files) and then can be input into your document at a later place (e.g. at the end of a chapter, or at the end of the entire book.)
- It creates a file naming schema for the solution file(s) based on
zzz
. Either a single file is used (in which case it will be zzz.tex
) or multiple files are used, in which case zzz
acts as a kind of label that identifies the type of solution it is, and the file names are given explicitly.
Because xxx
, yyy
and zzz
are used as part of environment/macro names, they must only contain letters, since these are the only valid characters for multi-character macro names in TeX. As with other macro names, they are case-sensitive (Xxx
≠xxx
). Furthermore, you should make sure that they do not conflict with existing environments that you may have in your document.
In the documentation, there are three sample documents (ansexam{1|2|3}.tex
) which show how this works in practice. I've taken the simple example here (ansexam1.tex
), and annotated it with some comments. (On TeXLive distributions, these files can be found in /usr/local/texlive/2010/texmf-dist/doc/latex/answers/
).
\documentclass[12pt,a4paper]{article}
% First we load the package.
\usepackage{answers}
% Now we set up a solution set.
% The environment that marks solutions within exercises is {sol}.
% The environment that marks solutions to be displayed is {Solution}
% The solution file type is "ans".
\Newassociation{sol}{Solution}{ans}
% Now we set up a theorem-like environment for exercises (this is)
% standard LaTeX; you could also use any of the more sophisticated
% theorem packages to do this.
\newtheorem{ex}{Exercise}
\begin{document}
% The next command opens a file to store the solutions. Without the second
% argument, the file would be called `ans.tex`. With the second argument
% the file is called `ans1.tex` and it is of the "ans" type.
\Opensolutionfile{ans}[ans1]
% Now we write our problems, and for each problem we write its solution into the
% "sol" environment. The solutions will not be displayed here.
\section{Problems}
\begin{ex}
First exercise
\begin{sol}
First solution.
\end{sol}
\end{ex}
\begin{ex}
Second exercise
\begin{sol}
Second solution.
\end{sol}
\end{ex}
% Now that we are done with our exercises and our solutions,
% we close the solution file
%
\Closesolutionfile{ans}
% Now our document has created a file called "ans1.tex" which contains a bunch of
% "Solution" environments, one for each "sol" environment that we put into the
% exercises. This file can now be \input back into another place in the document,
% here in the section called "Solutions".
\section{Solutions}
\input{ans1}
\end{document}
If you run this document, you will find that it has created a file ans1.tex
which looks like the following:
\begin{Solution}{1}
First solution.
\end{Solution}
\begin{Solution}{2}
Second solution.
\end{Solution}
The Solution
environment is set up by the \Newassociation
command. It has some basic formatting, which you can change as needed, either with hooks provided by the package, or by using \renewenvironment
after you have issued the \Newassociation
command.
For example, there is a hook \solutionstyle
which formats the label of each solution. This is initially set to \bfseries
, so the solution environment produces:
1 First solution
2 Second solution
You could redefine it as follows:
\renewcommand{\solutionstyle}[1]{\bfseries Answer to Exercise #1 }
And now your solutions would appear as:
Answer to Exercise 1 First solution
Answer to Exercise 2 Second solution
More complicated formatting is possible for any of the environments created using the yyy
argument of the \Newassociation
command. There are two hooks, \preyyy
and \postyyy
(in this example, this would be \preSolution
and \postSolution
.) These must be created using \newcommand
by you, and will be prepended or appended to the output solution as needed. For example, if you wanted each solution to end with a bullet, you could use:
\newcommand\postSolution{\hfill\textbullet}
Which would result in a right aligned bullet on its own line (ugly, but just an example.)
If you want your solutions to be more fancily formatted, you would use \renewenvironment
to define the environment the way you like.
Since your question is about storing, maintaining and referencing a large set of exercises (potentially in the order of 10,000), I'm going to concentrate on that, so the style here is very basic.
It's possible to define conditionals using \newif
(or through commands provided by packages such as etoolbox
). For example:
\newif\ifsolutions
\newif\ifcomplete
These default to false, but can be switched on:
\solutionstrue
\completetrue
It's also useful to provide syntactic commands to mark the solution. For example:
\newcommand{\solutionname}{Solution}
\newcommand{\solution}{\par\textbf{\solutionname}:\par}
As has been mentioned in one of the other answers, it's also possible to use environments and the comment
package. For multilingual support, the caption hooks can be used to redefine \solutionname
as appropriate. For example:
\usepackage[USenglish]{babel}
\addto\captionsUSenglish{%
\renewcommand\solutionname{Solution}%
}
Now an exercise can be written using these commands. For example:
$y = \sin(2x)$
\ifsolutions
\solution
\ifcomplete
Intermediate steps, further details etc.
\fi
$y' = 2\cos(2x)$
\fi
Environments provide a more LaTeXy feel, but let's concentrate on storing and accessing the questions.
The simple method, which has already been suggested, is to put each question in a separate file and load it with \input
. For example, if this exercise is in the file exercises/calculus/easy/dsin.tex
then the following MWE works:
\documentclass{article}
\newif\ifsolutions
\newif\ifcomplete
\solutionstrue
\completetrue
\newcommand{\solutionname}{Solution}
\newcommand{\solution}{\par\textbf{\solutionname}:\par}
\begin{document}
\begin{enumerate}
\item \input{exercises/calculus/easy/dsin}
\end{enumerate}
\end{document}
This is a relatively generic method, which can easily be translated to other TeX formats. For example, the Plain TeX equivalent is:
\newif\ifsolutions
\newif\ifcomplete
\solutionstrue
\completetrue
\def\solutionname{Solution}
\long\def\solution{\par{\bf\solutionname}:\par}
\newcount\questionnum
\long\def\question{%
\par
\advance\questionnum by 1\relax
\number\questionnum.
}
\question \input exercises/calculus/easy/dsin
\bye
The problem is that, although this structure is fine for a small number of questions, it can become unmanageable for 10,000. I mentioned datatooltk
in the comments, which can read and write .dbtex
files (datatool
's internal format), but I don't recommend using this format directly. These files just contain LaTeX code that defines the internal registers and control sequences used by datatool
to store the required data. There's no compression and it takes up a huge amount of resources. The datatooltk
application works better as an intermediary that can pull filtered, shuffled or sorted data from external sources in a way that can easily be input in the document. (See the datatool
performance page that compares build times for large databases.)
There are switches, such as --shuffle
or --sort
, which instructs datatooltk
to shuffle or sort the data after it's been pulled from the data source. This uses Java, which is more efficient than TeX, but if the data is stored in a SQL database, it's even more efficient to include these steps in the actual --sql
switch. (Currently, datatooltk
is only configured for MySQL, but it may be possible to use something else if the necessary .jar
file can be added to the class path.)
SQL databases can be optimized to improve performance. Suppose you want to randomly select 20 questions from 500. How do you perform that selection in LaTeX? First you'd need to use the shell to find out all the available files (or have an index file that can be parsed). Then you need to shuffle the list. That will take a while to do with TeX. It's more efficient to do this with SQL. (See, for example, MySQL select 10 random rows from 600K rows fast.)
If you decide to use SQL, the next thing to consider is the table structure.
- You'll need a unique id field. With this you'll be able to specifically select certain questions rather than have a random selection. (An auto increment primary key is best.)
- A field containing the question. (Let's call it
Question
.)
- A field containing the brief answer. (Let's call it
Answer
.)
- A field containing the extended answer. (Let's call it
ExtendedAnswer
.)
- A field identifying the difficulty level. (Let's call it
Level
.) This could be an integer (1 = easy) or an enumeration (easy
, medium
, hard
).
- A field identifying the topic. (Let's call it
Topic
.) An enumeration is probably the simplest type (for example, calculus
, settheory
).
I'm not quite sure about the language. There are two approaches that I can think of: have fields for the other language (For example, QuestionPortuges
, AnswerPortuges
and ExtendedAnswerPortuges
) or have a separate entry for the question in a different language with an extra field for the language.
So the above exercise example, could have
Question
=> $y = \sin(2x)$
Answer
=> $y' = 2\cos(2x)$
ExtendedAnswer
=> Intermediate steps, further details etc. \[y' = 2\cos(2x)\]
Level
=> 1
Topic
=> calculus
Language
=> english
or ExtendedAnswerPortuges
=> Passos intermédios, etc. \[y' = 2\cos(2x)\]
Note that this doesn't include the syntactic command \solution
or the conditionals \ifsolutions
and \ifcomplete
, which makes it easier to arrange the various parts of the question and answer.
It may be that some exercises require a particular package (such as amsmath
or graphicx
), so perhaps there could also be a field for the required packages. For example Packages
=> graphicx,amsmath
.
Any images or verbatim text must be stored outside the database somewhere on the file system. They could be on TeX's path or the database table could have a field with a list of external resources or the question/answer could simply use the full path.
The datatooltk
call can be done before the LaTeX run or using the shell escape. There's also a datatooltk
rule for arara
users. Let's suppose, I use datatooltk
to pull a random selection of questions and save the results in a file called exercises.dbtex
. This can then be loaded in the document using:
\DTLloaddbtex{\exercisedb}{exercises.dbtex}
If the data includes the Packages
field, you can make sure all the required packages are loaded by adding the following to the preamble:
\DTLforeach*{\exercisedb}{\Packages=Packages}
{\DTLifnullorempty{\Packages}{}{\usepackage{\Packages}}}
In the main part of the document:
\begin{enumerate}
\DTLforeach*{\exercisedb}% data base
{\Question=Question,\Answer=Answer,\ExtendedAnswer=ExtendedAnswer}% assignment list
{%
\item \Question
\ifsolutions
\solution
\ifcomplete
\ExtendedAnswer
\else
\Answer
\fi
\fi
}
\end{enumerate}
Further reading: Using the datatool Package for Exams or Assignment Sheets
Best Answer
I didn't use these packages (I have written my own, which I'm redesigning now, and I had a talk about it during EuroBachoTeX 2011 - you can download the slides from http://www.gust.org.pl/bachotex/2011/program#section-5), but I've skimmed through their docs and this is what I can say:
With exercise you can typeset exercises (possibly split in parts) with answers. You can hide (= not typeset) exercises or answers, or typeset exercises or answers in another part of the document (although they are remembered in a vbox, which is imho one of the worst ways usually). With each exercise you can associate its origin and difficulty (and typeset them if you wish). You can customize the way an exercise is displayed, and also you can select exercises to typeset (based on a list of labels). Markup is quite nice, maybe not the best possible (personally, I tend more towards more formalized markup, like in XML, not the free-form known in the LaTeX world), but still.
The answers package seems to be quite sophisticated and powerful, although not very user-friendly. Probably not something you would like to use five minutes before your deadline, but definitely worth checking. Ah, and the name Joseph Wright should guarantee that it works well.
The probsoln package is written by Nicola Talbot (quite a prolific and good package author - you should definitely check her
datatool
bundle!), and seems to be less complicated (and less powerful) thananswers
, but is probably a bit more user-friendly. Also, it has a few quite unique features: you can select a random subset from a pool of exercises, and also you have\correctitem
and\incorectitem
for use inenumerate
-like environments (these commands mark right and wrong answers in choice tests, but only if you typeset your exercises with solutions.).Hope that helps.
I'd also recommend reading my slides (which I mentioned before). They are far from perfect (and may contain mistakes), but they contain some possibly useful information. One of the more important isuues is that when typesetting problem sets you should definitely consider some design problems: do you want to maintain a separate, external problem-database (and if yes, should it be generated manually or with the
extract
package or a similar way) or not? (There are other design issues like that.)(In case you have any questions about those slides, feel free to email me at
mbork
, then the "at" sign, thenmbork
, then dot and finallypl
.)As I mentioned, I'm currently designing my own package with the same purpose, which (I hope) will have some unique features I personally need, too; it will be definitely easier to use than answers, but will have a similar set of features (and even more). Unfortunately, I have no idea when I'll be able to release usable code (a few months seem to be a reasonable time).