This is a short package that we created to typeset exams for a high school math competition that our department organizes. It is designed to make entering the questions very easy, the package mostly takes care of the formatting and spacing, one just has to enter the questions. It is very inflexible, it only allows exactly 5 choices per question, but I am throwing it in as an example that you can start with.
% File: mchoice.sty
%
% Author: Jan Hlavacek (jhlavace@svsu.edu)
% Changes:
% v. 0.1 initial version
% v. 1.1 automatic markings of correct answer
\NeedsTeXFormat{LaTeX2e}
\ProvidesPackage{mchoice}[2007/01/07 Package for typeseting simple multiple
choice tests, version 1.1]
\makeatletter
\newif\ifsolution
\solutionfalse
\DeclareOption{solutions}{\solutiontrue}
\ProcessOptions\relax
\newwrite\MCwrite
\AtBeginDocument{\immediate\openout\MCwrite=\jobname.mca}
\newskip\mcitemsep % glue separating the (.) from the text of each option (can be modified by user)
\mcitemsep=.5em
\newskip\mcinteritemskip % glue that goes between items on each line (can be modified by user)
\mcinteritemskip=2em
\newcommand{\NOTAtext}{None of the above} % Use \renewcommand to change this
\newcounter{mccount}
\def\mcitembox(#1)#2{\hbox{\textbf{(#1)}\hspace\mcitemsep#2}}
\newbox\mcnotabox
\AtBeginDocument{\setbox\mcnotabox\mcitembox(e){\NOTAtext}}
% Identify correct solution
\newtoks\MCSolutions
\MCSolutions={}
\newcounter{mcs@lcount}
\def\isc@rrect{%
\addtocounter{mcs@lcount}{1}%
\def\n@xt{\ifx\n@@xt!\expandafter\c@rrect\fi}%
\futurelet\n@@xt\n@xt}
\def\c@rrect#1{\edef\@ct{\global\MCSolutions={\the\MCSolutions
\Alph{mcs@lcount}}}\@ct}
\newcommand{\MultChoiceNOTA}[5][0]{%
\setcounter{mcs@lcount}{0}
\MCSolutions={}
\ifnum #1=0
\multch@icenota{\isc@rrect#2}{\isc@rrect#3}{\isc@rrect#4}{\isc@rrect#5}
\else
\multch@iceloosenota{\isc@rrect#2}{\isc@rrect#3}{\isc@rrect#4}{\isc@rrect#5}
\fi
\edef\t@st{\the\MCSolutions}\edef\t@@st{}
\ifx\t@st\t@@st\global\MCSolutions={E}\fi
\immediate\write\MCwrite{\the\MCSolutions}}
\newcommand{\multch@icenota}[4]{%
\setbox0\mcitembox(a){#1}%
\setbox2\mcitembox(b){#2}%
\setbox4\mcitembox(c){#3}%
\setbox6\mcitembox(d){#4}%
\setbox8\copy\mcnotabox%
%
% Find the maximal length:
%
\dimen0=\wd0 \ifdim\wd2>\dimen0 \dimen0=\wd2 \fi\ifdim\wd4>\dimen0
\dimen0=\wd4 \fi\ifdim\wd6>\dimen0 \dimen0=\wd6 \fi%
%
% If the resulting length is more than \textwidth, we have to unbox the items and typeset them differently:
%
\ifdim\dimen0>\textwidth
\bgroup%
\begin{list}{\textbf{(\alph{mccount})}}{\usecounter{mccount}\setlength\labelsep\mcitemsep\setbox0=\hbox{\textbf{(a)}\hspace\mcitemsep}\setlength\labelwidth{\wd0}}
\item #1
\item #2
\item #3
\item #4
\item \NOTAtext
\end{list}
\egroup%
\else
%
% Now check the NOTA box. If it is shorter than the rest, make it match. If
% it is not much longer, make the rest match it.
%
\dimen2=\dimen0
\advance\dimen2 by .5in
\ifdim\wd8<\dimen0 \wd8=\dimen0 \else
\ifdim\wd8<\dimen2 \dimen0=\wd8 \fi\fi
%
% Make all the boxes of the same length:
%
\wd0=\dimen0 \wd2=\dimen0 \wd4=\dimen0 \wd6=\dimen0%
\bgroup%
\par%
\openup\baselineskip
\tolerance=10000
\noindent\box0\hskip\mcinteritemskip\penalty9000\box2\hskip\mcinteritemskip\penalty6000\box4\hskip\mcinteritemskip\penalty3000\box6\hskip\mcinteritemskip\penalty1000\box8\hfill\par\egroup%
\fi\medskip}
\newcommand{\multch@iceloosenota}[4]{%
\setbox0\mcitembox(a){#1}%
\setbox2\mcitembox(b){#2}%
\setbox4\mcitembox(c){#3}%
\setbox6\mcitembox(d){#4}%
\setbox8\copy\mcnotabox%
\bgroup%
\par%
\openup\baselineskip
\tolerance=10000
\raggedright
\noindent\box0\hskip\mcinteritemskip\quad\penalty9000\box2\hskip\mcinteritemskip\quad\penalty6000\box4\hskip\mcinteritemskip\quad\penalty3000\box6\hskip\mcinteritemskip\quad\penalty1000\box8\quad\par\egroup%
\medskip}
\newcommand{\MultChoice}[6][0]{%
\setcounter{mcs@lcount}{0}
\MCSolutions={}
\ifnum #1=0
\multch@ice{\isc@rrect#2}{\isc@rrect#3}{\isc@rrect#4}{\isc@rrect#5}{\isc@rrect#6}
\else
\multch@ice{\isc@rrect#2}{\isc@rrect#3}{\isc@rrect#4}{\isc@rrect#5}{\isc@rrect#6}
%currently there is no loose form of regular multiple choice.
\fi
\edef\t@st{\the\MCSolutions}\edef\t@@st{}
\ifx\t@st\t@@st\global\MCSolutions={X}\fi
\immediate\write\MCwrite{\the\MCSolutions}}
\newcommand{\multch@ice}[5]{%
\setbox0\mcitembox(a){#1}%
\setbox2\mcitembox(b){#2}%
\setbox4\mcitembox(c){#3}%
\setbox6\mcitembox(d){#4}%
\setbox8\mcitembox(e){#5}%
%
% Find the maximal length:
%
\dimen0=\wd0 \ifdim\wd2>\dimen0 \dimen0=\wd2 \fi\ifdim\wd4>\dimen0
\dimen0=\wd4 \fi\ifdim\wd6>\dimen0 \dimen0=\wd6 \fi\ifdim\wd8>\dimen0
\dimen0=\wd8 \fi%
%
% If the resulting length is more than \textwidth, we have to unbox the items and typeset them differently:
%
\ifdim\dimen0>\textwidth
\bgroup%
\begin{list}{\textbf{(\alph{mccount})}}{\usecounter{mccount}\setlength\labelsep\mcitemsep\setbox0=\hbox{\textbf{(a)}\hspace\mcitemsep}\setlength\labelwidth{\wd0}}
\item #1
\item #2
\item #3
\item #4
\item #5
\end{list}
\egroup%
\else
%
% Make all the boxes of the same length:
%
\wd0=\dimen0 \wd2=\dimen0 \wd4=\dimen0 \wd6=\dimen0 \wd8=\dimen0%
\bgroup%
\par%
\openup\baselineskip
\tolerance=10000
\noindent\box0\hskip\mcinteritemskip\penalty9000\box2\hskip\mcinteritemskip\penalty6000\box4\hskip\mcinteritemskip\penalty3000\box6\hskip\mcinteritemskip\penalty1000\box8\hfill\par\egroup%
\fi\medskip}
\def\solutiontext#1.{\textsc{Solution~}\textbf{(\lowercase{#1})}:}
\newenvironment{solution}{\ifsolution\par\noindent\expandafter\solutiontext\the\MCSolutions.%
\else\bgroup\setbox0\vbox\bgroup\fi}{\ifsolution\par\else\egroup\egroup\fi\vspace{\fill}}
\def\solutionm@rk#1.{\textbf{(\lowercase{#1})}}
\def\lastsolution{\expandafter\solutionm@rk\the\MCSolutions.}
\makeatother
You would use it like this:
\documentclass{article}
\usepackage[solutions]{mchoice}
\begin{document}
\begin{enumerate}
\item How many different ways are there to pay a $\$9.75$ bill if only
dimes and quarters are available?
\MultChoiceNOTA% "NOTA" means "none of the above" will the fifth choice
{39}
{19}
{!20}% The correct answer is marked with !
{40}
\begin{solution}
We need to find the number of non-negative integer solutions of the
equation $10x + 25y = 975$, or $2x + 5y = 195$, or $2x = 195 - 5y$.
Because the right hand side is divisible by $5$, $x$ must also be
divisible by $5$, so $x=5d$ for some non-negative integer $d$. Then
the equation becomes $10d = 195 - 5y$ or $2d = 39 - y$. So the number
of solutions will be the number of non-negative even integers less
than or equal to $39$. There are $\frac{39+1}{2} = 20$ such numbers.
\end{solution}
\item The digits of the whole numbers from $1$ to $99$ are concatenated in
order to form the number $N$:
\[N = 1234567891011121314\dots979899\]
Which of the following is true?
\MultChoiceNOTA%
{$N$ is divisible by $3$ but not by $6$ and $9$}
{$N$ is divisible by $3$ and $6$ but not by $9$}
{!$N$ is divisible by $3$ and $9$ but not by $6$}
{$N$ is not divisible by any of $3$, $6$ or $9$}
\begin{solution}
The sum of the digits on $N$ is $10(1 + 2 + 3 + \dots + 9) + 10(1 + 2 +
3 + \dots + 9) = 20\cdot 45 = 900$ which is
divisible ny $3$ and $9$, so $N$ is divisible by both $3$ and $9$.
$N$ is not divisible by $2$ since it ends in $9$, so $N$ cannot be
divisible by $6$.
\end{solution}
\item A circular table has exactly $60$ chairs around it. There are $N$
people seated around the table. The next person coming to the table will
have to be seated next to an occupied seat. Find the smallest possible
value of $N$.
\MultChoice%
{$15$}
{!$20$}
{$30$}
{$40$}
{$58$}
\begin{solution}
For the next person to have to sit next to an occupied seat, there
cannot be three consecutive chairs currently unoccupied (otherwise
the next person would simply sit in the middle of the three empty
chairs). Therefore for every three consecutive chairs at least one of them
has to be occupied. Since we are looking for the smallest $N$,
exactly one of the three will have to be occupied, and each two
people will have to have two empty seats between them. Therefore the
number of people sitting at the table is $1/3$ of the number of
seats, or $20$ people.
\end{solution}
\end{enumerate}
\end{document}
The package also automatically create a .mca file (Multiple Choice Answers)
that contains the list of correct answers for all the questions. We use that in
our automated grading scripts. You can see samples of exams prepared this way
here (2007 - 2008, older exams were prepared using Word, newer use
ConTeXt, with a module that is based on this package).
examdoc.pdf, which is supposed to be pretty readable. – Phil Hirschhorn Mar 3 '11 at 22:59