2

A desired feature for the latex-templates that we're using for exercises is to give hints in a way that the students have the option of trying to solve the exercise without it (i.e. not directly below the problem formulation).

endnotes (or rather, the newer enotez), seemed like a good starting point for this. However, I'd like the mark of each endnote to be a reference back to the subproblem for which the hint is given. My idea was to automatically label all subproblems with a counter derived from \thesubproblem, and thus reconstruct the right label without having to manually feed the label to the \hint-command I'd like to have (see code below). Unfortunately, I can't manage to:

  • expand the reference in the argument of \endnote
  • feed any reference into the optional argument (which is responsible for the mark). This is secondary however, because by changing the style and removing the marks, I could just put the reference at the beginning of the body of the hint.

I've looked at a few tex.sx questions (How to expand several arguments in an environment?, When to use \edef, \noexpand, and \expandafter?, etc.), but with no success.

Additionally, I'd like to make use of the splitting into sections that enotez offers, ideally by tricking it into thinking that a new problem belongs to a new section (which I do below with a \section*{} that I'd like to get rid of). I've played around with incrementing the counters and so forth, but this didn't work and my expl3-fu is not good enough to parse what enotez.sty is actually doing.

Here's my sample code:

\documentclass{article}
\usepackage[english]{babel}

\usepackage{etoolbox}
\usepackage{enotez}
\usepackage[colorlinks]{hyperref}

\makeatletter
\setenotez{
    list-name=Hints,
    list-style=section,
    mark-cs=\@gobble,
    split=section,
    split-title={Hints for Problem <ref>}
}
\makeatother

\DeclareInstance{enotez-list}{custom}{list}{number = #1:}

\newcounter{exsheet}
\newcounter{problem}[exsheet]

\newcommand{\exsheet}[1]
{\setcounter{exsheet}{#1}
\begin{center}  {\Large Homework Problem Sheet #1} \end{center}
}

\setlength{\parindent}{0pt}
\makeatletter
\renewcommand{\theproblem}{\arabic{exsheet}.\arabic{problem}}
\newcommand{\problem}[2][]{%
    % details see tex.stackexchange.com/q/31780
    \@startsection{problem}{1}{\z@}{-3.25ex\@plus -1ex \@minus -.2ex}{1.5ex \@plus .2ex}%
    {\large\bfseries Problem~}[\ifstrempty{#1}{#2}{#1}]{#2}}
\let\problemmark\@gobble

\newcounter{subproblem}[problem]
\renewcommand{\thesubproblem}{(\arabic{exsheet}.\arabic{problem}\alph{subproblem})}
\newcommand{\thesp}{\arabic{exsheet}.\arabic{problem}.\arabic{subproblem}}
\newcommand*{\subproblem}{\@startsection{subproblem}{2}{0em}{1ex}{0pt}{\bfseries}{}%
    \label{sp.\thesp}}
\let\subproblemmark\@gobble
\makeatother

% % % % % % Help needed here: % % % % % % %
%\newcommand{\hint}[#1]{\endnote[...expansion magic...\ref{sp.\thsp}]{#1}}

\let\thesection\theproblem

\begin{document}

\exsheet{1}

\problem{Test}
\subproblem Text
\subproblem Text\endnote[(1.1b)]{Hint} % call should just be \hint{Hint}
\subproblem Text 
\subproblem Text\endnote[(1.1d)]{Hint} %\ref{sp.\thesp} works outside

\section*{Section for splitting endnotes -- shouldn't be here}
\problem{Test}
\subproblem Text\endnote[(1.2a)]{Hint}
\subproblem Text
\subproblem Text
\subproblem Text\endnote[(1.2d)]{Hint}

\vfill % would normally be \newpage
\printendnotes[custom]
\end{document}
  • Just a comment (I didn't look in detail at your question, yet): to be honest I'm not really satisfied with the implementation of the splitting mechanism of enotez. I plan to revise and probably re-implement it one day... I can't when I will find the time, though. Maybe it is easier to use LaTeX's toc-mechansim with a custom list for your task... – clemens Jul 9 '14 at 10:09
  • @cgnieder: Ideally, I'd like to be able to write to different groups of endnotes for different things - i.e. problems, but maybe also "levels" of hints (e.g. almost trivial, substantial, close to the solution), but I don't have any experience with the toc-mechanism, and it seemed a bit daunting to come up with this myself... – Axel Jul 9 '14 at 11:02
  • Something like you've sketched in your question could be solved using the exsheets package. If you're interested I'll post something with it later. – clemens Jul 9 '14 at 12:03
  • @cgnieder: Thanks for the offer, I'd certainly be interested in it. But I haven't checked yet if exsheet breaks some of my custom-built other functionality, so I would prefer a solution with enotez or using the toc-functionality of LaTeX. – Axel Jul 9 '14 at 15:48
  • Two links that might be useful: Collect contents of lists at beginning of document and Chapter name appearing in the endnotes – clemens Jul 9 '14 at 22:05
2

The code below builds the list of hints via LaTeX's mechanism used for building toc, lof and lot and does not use enotez any more. It relies on the hyperref package being loaded so the hints in the list link back to the corresponding subproblem.

The hints are printed as description lists, with \subsection*s between them as headings. The document body

\problem{Test}
\subproblem Text
\subproblem Text\hint{Hint one}
\subproblem Text
\subproblem Text\hint{Hint two}

\problem{Also a test}
\subproblem Text
\subproblem Text
\subproblem Text
\subproblem Text

\problem{Another test}
\subproblem Text\hint{Hint three}
\subproblem Text
\subproblem Text
\subproblem Text\hint{Hint four}

\listofhints

gives

enter image description here

I've added lot's of comments to the code which hopefully explain what everything does. The \null\clearpage and \clearpage\null lines are only there to see that the links jump to the correct position.

\documentclass{article}
\usepackage[english]{babel}

\usepackage{etoolbox}
\usepackage[colorlinks]{hyperref}

\makeatletter
% exercise sheet:
\newcounter{exsheet}
\newcommand{\exsheet}[1]{%
  \setcounter{exsheet}{#1}%
  \begin{center}
    \Large Homework Problem Sheet~\theexsheet
  \end{center}%
}

% problems:
\newcounter{problem}[exsheet]
\renewcommand*\theproblem{\theexsheet.\arabic{problem}}
\newcommand\problem[2][]{%
  % details see tex.stackexchange.com/q/31780
  \@startsection{problem}
    {1}{\z@}{-3.25ex\@plus -1ex \@minus -.2ex}{1.5ex \@plus .2ex}%
    {\large\bfseries Problem~}[\ifstrempty{#1}{#2}{#1}]{#2}%
}
\let\problemmark\@gobble
% avoid hyperrefs bookmark level warning:
\providecommand*\toclevel@problem{0}

% subproblems:
\newcounter{subproblem}[problem]
\renewcommand*\thesubproblem{(\theproblem\alph{subproblem})}
\newcommand*\subproblem{%
  \@startsection{subproblem}
    {2}{0em}{1ex}{0pt}
    {\bfseries}{}%
}
\let\subproblemmark\@gobble
% avoid hyperrefs bookmark level warning:
\providecommand*\toclevel@subproblem{1}

% hints:
% the following code relies on `hyperref' being loaded
%   => \contentsline then has 4 arguments!

\newcounter{hints}
\newrobustcmd\hint[1]{%
  % count the number of hints:
  \stepcounter{hints}%
  % write hint to auxiliary file:
  \addtocontents{hints}{%
    \hintscontentsline
      {subproblem.\theHsubproblem}  % the current subproblem hyperlink destination
      {\thesubproblem}              % the current subproblem number
      {\unexpanded{\unexpanded{#1}}}% the actual hint
      {\arabic{problem}}            % the value of the current problem number
      {\theproblem}%                % the current problem number
  }%
}

\newrobustcmd\hintscontentsline[5]{%
  \contentsline{hints}
    {#2}                        % first argument to \l@hints 
    {\hint@item{#2}{#3}{#4}{#5}}% second argument to \l@hints
    {#1}%                       % hyperlink name
}

\newrobustcmd*\listofhints{%
  \section*{Hints}
  \begingroup
    % get the list of hints:
    \@starttoc{hints}
    \hints@empty{\@latex@warning{Empty list of hints}}%
  \endgroup
}

\let\hints@empty\@firstofone

% \l@hints gets fed by \contentsline
% #1: second argument of \contentsline
% #2: third argument of \contentsline
% => we build \hint@item with five arguments here, the first of \l@hints being
%    the last to \hint@item
\newcommand\l@hints[2]{%
  #2{#1}%
}

\newcounter{problemhints}
\newcounter{hintinlist}
% \hint@item does the actual writing of the hints:
% #1: formatted subproblem number
% #2: hint text
% #3: problem number
% #4: formatted problem number
% #5: subproblem link
\newrobustcmd\hint@item[5]{%
  % \Hy@tocdestname (part of argument #5) needs to survive when the group is
  % closed, else the first link of a problem will lead to a wrong destination:
  \xdef\Hy@tocdestname{\Hy@tocdestname}%
  % check if the hints for a new problem start:
  \ifnumcomp{\value{problemhints}}<{#3}
    {%
      % if this is nit the first problem end the description list:
      \ifnumequal{#3}{1}{}{\end{description}}%
      \subsection*{Hints for problem~#4}
      % start a new description list:
      \begin{description}
    }{}%
  \item[#5] #2%
  % remember to which problem this hint belongs to:
  \setcounter{problemhints}{#3}%
  % check if this is the last hint and if so end the description list:
  \stepcounter{hintinlist}%
  \ifnumequal{\value{hints}}{\value{hintinlist}}
    {%
      \end{description}
      % disable the warning -- the list isn't empty any more:
      \global\let\hints@empty\@gobble
    }{}%
}

\makeatother

\setlength{\parindent}{0pt}

\begin{document}

\null\clearpage

\exsheet{1}

\problem{Test}
\subproblem Text
\subproblem Text\hint{Hint one}
\subproblem Text
\subproblem Text\hint{Hint two}

\problem{Also a test}
\subproblem Text
\subproblem Text
\subproblem Text
\subproblem Text

\problem{Another test}
\subproblem Text\hint{Hint three}
\subproblem Text
\subproblem Text
\subproblem Text\hint{Hint four}

\listofhints

\clearpage\null

\end{document}
  • Wow, this looks really neat! I don't have time to run it myself right now, but it looks like I imagined (which is why I've accepted it already). Thank you very much! – Axel Jul 14 '14 at 6:50
  • I'm sorry it has taken me so long to come back to this, the solution works very well indeed - thanks again! I was just wondering if there's a way such that it can also handle paragraph breaks or is this a built-in limitation of \contentsline? – Axel Aug 27 '14 at 11:26
  • Also, there is a slight limitation in your code that caused it to crash in a few test scenarios, namely, problem 1 has to have a hint, otherwise \ifnumequal{#3}{1}{}{\end{description}} inserts a spurious end of description. I changed this to \iftoggle{firstprobwithhint}{\end{description}}{\toggletrue{firstprobwithhint}} after defining \newtoggle{firstprobwithhint} beforehand. – Axel Aug 27 '14 at 11:27
  • It took me a while to figure out the difference between argument #1 and #5 of \hint@item -- since they both come from #2 of \hintscontentsline -- until I understood that \contentsline does some hyperref-magic that needs to be passed to \hint@item. However, unless I still misunderstand something, the first argument does nothing, so I just took it out and changed \hint@item to 4 arguments - which works too. Unfortunately, I haven't been able to figure out a way to pass a \par to \contentsline. Is this possible at all? Math mode, environments and floats work fine... – Axel Aug 28 '14 at 11:19
  • 1
    I can't remember, why I had the first argument, though. Maybe it is just a leftover from when I played with different options. \contentsline is not a long macro so it can't have a \par in its argument. You can smuggle it with \csname par\endcsname. Or \newcommand*\hiddenpar{\par} and then use \hiddenpar. (See tex.stackexchange.com/questions/1050 for an explanation) – clemens Aug 28 '14 at 20:51

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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