4

I'm using the exam package for creating exercise questions of a class and trying to leave empty spaces dynamically according to the length of the solution, instead of setting a static value.

The exam package provides an option to print the solutions or leave an empty space for students to answer when solutions not printed. This option is set by the following commands:

\printanswers

or

\noprintanswers

A question and a solution is formatted as follows:

\begin{questions}
        \question This is a question text
        \begin{solution}[2in] 
            \begin{itemize}
                \item First answer
                \item Second answer
                \item A hundred answers maybe
            \end{itemize}
        \end{solution}
    \end{questions}

Here the solution space is defined in this line:

\begin{solution}[2in]

What I'm currently doing is to set a variable called \solspace and use it for each solution across the document. I can manually set a proper value for the solution space depending on the length of the solution as well, but that's not the best way.

What I want to do is to (ideally) calculate how much space the solution would take (when \printanswers) and use this value in \solution[2in] instead of the static value of 2in. It could also be possible to somehow estimate the length of the solution and use a proper length for the space. Note that solutions are not limited to items or text, could be formulas or images.

Any ideas on how to approach this problem?

Example:

Print answers

No print answers

5
  • 3
    if you distribute the exam on paper you could simply print the solutions in white. (This is not a good plan if the students can access the PDF :-) Mar 31, 2019 at 16:13
  • What about wrapping a vphantom around the whole solution? Apr 1, 2019 at 0:00
  • @grendelsdad doesn't work well as the solution contains itemize env or other envs, the structure of the solutions varies from images to formulas
    – kuzdogan
    Apr 3, 2019 at 9:58
  • 1
    Note that solution and solutionbox use totally different approaches. Apr 3, 2019 at 15:27
  • @JohnKormylo right, edited the sample image accordingly
    – kuzdogan
    Apr 3, 2019 at 19:47

2 Answers 2

4

The problem is that you really don't know how wide \linewidth is until you are in the solution environment, at which point is too late. Besides, handwriting uses more space than typesetting, although I suppose you could just multiply by some factor.

This assumes that all solutions are the same width, which is found using \the\linewidth in a previous run. I also measured the height of an empty solution so that versions with \printanswers and \noprintanswers would line up.

\documentclass{exam}
\noprintanswers
\usepackage{showframe}

\newsavebox\tempbox% note: \solutionbox already used (environment)
\newlength\solutionwidth
\setlength{\solutionwidth}{433.1772pt}
\newlength{\emptyheight}
\setlength{\emptyheight}{41.74443pt}% height of empty solution (printed)

\begin{document}
\begin{questions}
        \question This is a question text
        \savebox\tempbox{\parbox[t]{\solutionwidth}{%
            \begin{itemize}
                \item First answer
                \item Second answer
                \item A hundred answers maybe
            \end{itemize}}}%
        \begin{solution}[\dimexpr \emptyheight+\ht\tempbox+\dp\tempbox]%
          %\the\linewidth% used to set \solutionwidth
          \usebox\tempbox
        \end{solution}
        \question Next question.
    \end{questions}
\end{document}

This is a two-pass solution. It stores the height in the aux file using \saveheight, then in the next pass stores the height in \tempheight using \getheight.

\documentclass{exam}
\noprintanswers
\usepackage{showframe}% debugging tool

\newcounter{tempcount}
\newsavebox\tempbox% note: \solutionbox already used (environment)
\newlength{\tempheight}% reserve global register
\newlength{\emptyheight}
\setlength{\emptyheight}{41.74443pt}% height of empty solution (printed)

\makeatletter
\newcommand{\saveheight}[1]{% text for solution environment
  \setbox\tempbox=\vbox{#1}%
  \tempheight=\dimexpr \ht\tempbox+\dp\tempbox\relax
  \immediate\write\@auxout{\string\newheight{\the\tempheight}}%
  \unvbox\tempbox}

\newcommand{\newheight}[1]{% called automatically from aux file
  \stepcounter{tempcount}%
  \expandafter\gdef\csname height\thetempcount\endcsname{#1}}%

\newcommand{\getheight}{\stepcounter{tempcount}%
  \@ifundefined{height\thetempcount}{\tempheight=1in}%
    {\tempheight=\csname height\thetempcount\endcsname\relax}%
}
\makeatother
\AtBeginDocument{\setcounter{tempcount}{0}}% reset
 
\begin{document}
\begin{questions}
        \question This is a question text
        \getheight%
        \begin{solution}[\dimexpr \emptyheight+\tempheight]
          \saveheight{%
            \begin{itemize}
                \item First answer
                \item Second answer
                \item A hundred answers maybe
            \end{itemize}}%
        \end{solution}
        \question Next question.
    \end{questions}
\end{document}
3
  • Solutions are the same width that's not a big issue. However, my apologies, I didn't understand the structure of the answer. Are these two separate files? Do I run them both? Or two different solutions?
    – kuzdogan
    Apr 3, 2019 at 9:56
  • These are two separate solutions. I didn't think of the second one until after the first was done. Apr 3, 2019 at 15:08
  • Works great with the first approach! One little thing: I need to add an empty line before the solution so \\ is necessary as: \\ \usebox\tempbox otherwise the parbox overflows
    – kuzdogan
    Apr 3, 2019 at 20:05
0

Never be to strict with space for answering the question. :) Some children write big, others write small. The solution of could be extended by some kids, are reduced by others. If my kids are complaining about layout of exams, they mostly complain that they didn't had enough space to answer the questions.

You could work like this:

\documentclass{exam}
\printanswers
\begin{questions}
\question blablabla
\ifprintanswer
      \begin{itemize}
            \item \dotfill
            \item \dotfill
            \item \dotfill
        \end{itemize}
\else
      \begin{itemize}
            \item the answer
            \item the answer
            \item  the answer
        \end{itemize}

\fi
\begin{questions}
\end{document}

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .