Take the 2-minute tour ×
TeX - LaTeX Stack Exchange is a question and answer site for users of TeX, LaTeX, ConTeXt, and related typesetting systems. It's 100% free, no registration required.

I have code to automatically align the four choices of a multiple choice question and put the answer after the question with dotted lines. It works quite well with the exam document class (see the screenshot of the output below).

image shot

The minimal sample code is below:

\documentclass[answers,a4paper]{exam}
\usepackage{graphicx}
\usepackage{environ}
\usepackage[normalem]{ulem}
\usepackage{etoolbox}
\usepackage{enumitem}
%
\renewcommand{\choiceshook}{%
    \setlength{\leftmargin}{10pt}%
}

\newlength\answerspace
\setlength\answerspace{0.5in}
\newcommand\dottedanswerline[1][{}]{%
  % One optional argument, the default value of which is empty.
  \unskip\linebreak[0]\enspace
  \hbox{}\nobreak\dotfill 
  \ifprintanswers
    \hbox to \answerspace{(\hfil#1\hfil)}%
  \else
    \hbox{(\hskip 0.5in)}%
  \fi
}% dottedanswerline

\makeatletter
\newlength\choiceitemwidth
\newif\ifshowsolution \showsolutiontrue
\newcounter{choiceitem}%

\def\thechoiceitem{\Alph{choiceitem}}%
\setlength{\fboxsep}{0pt}
%\def\makechoicelabel#1{#1\uline{\thechoiceitem.}\else\thechoiceitem.\fi\space} %underline the answer item label if we want to print the answer
\def\makechoicelabel#1{#1\fbox{\thechoiceitem.}\else\thechoiceitem.\fi\space} %underline the answer item label if we want to print the answer

\def\choice@mesureitem#1{\cr\stepcounter{choiceitem}\makechoicelabel#1}%

%measure the choices, this is the first time we need to parse the \BODY
\def\choicemesureitem{\@ifstar
  {\choice@mesureitem\ifprintanswers \xappto\theanswer{\thechoiceitem}\ignorespaces}%
  {\choice@mesureitem\iffalse}}%

\def\choice@blockitem#1{%
  \ifnum\value{choiceitem}>0\hfill\fi
  \egroup\hskip0pt
  \hbox to \choiceitemwidth\bgroup\hss\refstepcounter{choiceitem}\makechoicelabel#1}

\def\choiceblockitem{\@ifstar
  {\choice@blockitem\ifprintanswers\ignorespaces}%
  {\choice@blockitem\iffalse}}

\def\choice@paraitem#1{%
  \par\refstepcounter{choiceitem}\makechoicelabel#1}

\def\choiceparaitem{\@ifstar
  {\choice@paraitem\ifprintanswers\ignorespaces}%
  {\choice@paraitem\iffalse}}


\NewEnviron{items}{%
  \def\theanswer{}
  \begingroup
    \let\item\choicemesureitem
    \setcounter{choiceitem}{0}%
    \settowidth{\global\choiceitemwidth}{\vbox{\halign{##\hfil\cr\BODY\crcr}}}%
  \endgroup \dottedanswerline[\theanswer]
  \setlist[trivlist]{nosep}
  \trivlist\item\relax%  
  \parindent0pt%
  \setcounter{choiceitem}{0}%
  \ifdim\choiceitemwidth<0.25\columnwidth
    \choiceitemwidth=0.25\columnwidth
    \let\item\choiceblockitem
    \bgroup\BODY\hfill\egroup
  \else\ifdim\choiceitemwidth<0.5\columnwidth
    \choiceitemwidth=0.5\columnwidth
    \let\item\choiceblockitem
    \bgroup\BODY\hfill\egroup
  \else % \choiceitemwidth > 0.5\columnwidth
    \let\item\choiceparaitem
    \BODY
  \fi\fi
  \endtrivlist
}
\makeatother


\begin{document}

\section{multiply choice questions}
\begin{questions}

\question this is a question
\begin{items}
\item wrong choice
\item wrong choice
\item wrong choice
\item * right choice
\end{items}

\question this is a question
\begin{items}
\includegraphics[width=5cm,height=5cm]{example-image}\\
\item wrong choice
\item wrong choice
\item wrong choice
\item * right choice
\end{items}

\question this is a question
\begin{items}
\includegraphics[width=5cm,height=5cm]{example-image}\\
\item wrong choice
\item wrong choice wrong choice wrong choice wrong choice
\item * right choice
\item wrong choice

\end{items}

\end{questions}

\end{document}

You see I have put a figure in the question. However, I want to save space, which means I want to put the figure in the right side of the choices (as the the red arrows show). How can this be done?

Note that the four choices were typeset in a compact way, which means they can either be put in one row, or two rows, or four rows, depending on their max length of the choice. Details can be found in the solved question here: automatically align the four choices of a multiple choice question and put the answer after the question with dotted lines.

EDIT: In my TeX code, the image width is used to calculate the maximum length of the choices, so, if I use the following code:

\question this is a question
\begin{items}
\includegraphics[width=15cm,height=5cm]{example-image}\\
\item wrong choice
\item wrong choice
\item wrong choice
\item * right choice
\end{items}

Note that the image has width of 15cm, now the result choices were typeset in one column, but it is expected in two columns, see the second question of the screen shot.

EDIT2: I have an issue with nickie's solution, if I have such code:

\question this is a question
\begin{items}[{\includegraphics[width=15cm,height=2cm]{example-image}}]
\item wrong choice
\item wrong choice
\item wrong choice
\item * right choice
\end{items}

I will get the image here:

image is too wide, so the choices does not look good

So, in this case(I guess the image is larger then 0.75\columnwidth), we should put all the four choices below the figure.

share|improve this question
add comment

1 Answer 1

up vote 3 down vote accepted

Here's what I came up with. I changed your items environment, which now takes an optional parameter: whatever has to be right aligned with the answers.

\usepackage[export]{adjustbox}
\newdimen\qanswd
\newdimen\qanswdtmp
\newbox\qimgbox
\NewEnviron{items}[1][]{%
  \def\theanswer{}
  \begingroup
    \let\item\choicemesureitem
    \setcounter{choiceitem}{0}%
    \settowidth{\global\choiceitemwidth}{\vbox{\halign{##\hfil\cr\BODY\crcr}}}%
  \endgroup \dottedanswerline[\theanswer]
  \setbox\qimgbox\hbox{#1}%
  \setlist[trivlist]{nosep}
  \trivlist\item\relax%
  \qanswd=\linewidth%
  \advance\qanswd-\wd\qimgbox%
  % handle large images (leaving less than 30% space)
  \qanswdtmp=0.3\linewidth%
  \ifnum\qanswd<\qanswdtmp%
    %\strut\hfill% uncomment to right-align large images
    \unhbox\qimgbox%
    %\hfill\strut% uncomment this too to center them
    \par%
    \qanswd=\linewidth%
    \setbox\qimgbox\hbox{}%
  \fi%
  % end of handling for large images
  \begin{minipage}[t]{\qanswd}
  \trivlist\item\relax%
  \parindent0pt%
  \setcounter{choiceitem}{0}%
  \ifdim\choiceitemwidth<0.25\columnwidth
    \choiceitemwidth=0.25\columnwidth
    \let\item\choiceblockitem
    \bgroup\BODY\hfill\egroup
  \else\ifdim\choiceitemwidth<0.5\columnwidth
    \choiceitemwidth=0.5\columnwidth
    \let\item\choiceblockitem
    \bgroup\BODY\hfill\egroup
  \else % \choiceitemwidth > 0.5\columnwidth
    \let\item\choiceparaitem
    \BODY
  \fi\fi
  \endtrivlist
  \end{minipage}%
  \adjustbox{valign=t}{\unhbox\qimgbox}
  \endtrivlist
}

You have to use it like this:

\question this is a question
\begin{items}[{\includegraphics[width=5cm,height=5cm]{example-image}}]
\item wrong choice
\item wrong choice
\item wrong choice
\item * right choice
\end{items}

Notice the extra braces around your \includegraphics, which protect the nested brackets.

I'm getting an underfull \hbox but it was there to begin with.

result

share|improve this answer
    
Hi, thanks for the answer, it works quite well, but there is one issue remaining, I have updated my original question (add a new section named EDIT2) to show this issue. Thanks. –  ollydbg23 Nov 2 '13 at 12:08
    
You are right about your EDIT2 issue. I had assumed that your image would be small enough to fit on the right side next to the answers. I fixed it too now: the image will be before the answers if the space remaining for the answers is less than 30% of the line width. Fix the condition if you want something else. Large images will be left-aligned; this can be fixed: see the code. Cheers. –  nickie Nov 2 '13 at 14:13
    
Hi, nickie, many thanks for the quick fix! It works OK on large images. –  ollydbg23 Nov 2 '13 at 15:50
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.