1

I'm writing a book in which each chapter ends with a list of numbered exercises. I would like to persuade LaTeX to count the total number of exercises in the book, to be referred to with \ref or something like it (e.g., \total from totcount). Each chapter is loaded separately using \include, and I want the counts to be correct even when using \includeonly.

It looks like the totcount package might help, provided I somehow jigger the exercise environments to step a suitable counter. But I'm not quite clear on how I can do that in a way that is compatible with the \suspend and \resume commands from package mdwlist.

Any suggestions how I would define an exercises environment that would work with totcount and be compatible with \suspend and \resume? Or suggest another approach entirely?

Here's an MWE in which each exercise is correctly numbered: exercises in chapter 1 are numbered 1 to 4, as are exercises in chapter 2. The problem I'm trying to solve is to accumulate the correct total (8) in the preface.

\documentclass{book}
\usepackage{totcount}
\usepackage{mdwlist}

\newtotcounter{exercises}
\newenvironment{exercises}
   {\enumerate}     % need something here to count each exercise
   {\endenumerate}



\begin{document}

\section*{Preface}

There are \total{exercises} exercises.  (Should be~8.)

% this chapter meant to be in a separate file loaded with \include
\chapter{Diet}

\section{Omnivorous}

\begin{exercises}
\item
Which do you prefer?
\begin{enumerate} 
\item
Fish
\item
Fowl
\end{enumerate}
\item
What won't you touch?
\begin{enumerate}
\item
Snakes
\item
Snails
\end{enumerate}
\suspend{exercises}

\section{Vegetarian}

\resume{exercises}
\item
Which do you prefer?
\begin{enumerate}
\item
Corn
\item
Squash
\end{enumerate}
\item
What won't you touch?
\begin{enumerate}
\item
Broccoli
\item
Cilantro
\end{enumerate}
\end{exercises}


% this chapter meant to be in a separate file loaded with \include
\chapter{Technology}

\section{Typesetting}

\begin{exercises}
\item
Which do you prefer?
\begin{enumerate} 
\item
Plain \TeX
\item
\LaTeX
\end{enumerate}
\item
What won't you touch?
\begin{enumerate}
\item
Word
\item
Scribe
\end{enumerate}
\suspend{exercises}

\section{Operating systems}

\resume{exercises}
\item
Which do you prefer?
\begin{enumerate}
\item
Debian
\item
Arch
\end{enumerate}
\item
What won't you touch?
\begin{enumerate}
\item
BeOS
\item
NeXT
\end{enumerate}
\end{exercises}

\end{document}


5
  • You can also modify/rename an environment to increment a new counter each time. \refsteprcounter and \label to save the last value (plus one). – John Kormylo Aug 4 '20 at 2:51
  • Can you please post a minimal working example that shows what your exercises look like. Your document class, for example, might be relevant to the solution. It sounds like you are using the enumitem package. Is this right? – user30471 Aug 4 '20 at 5:02
  • @Andrew for MWE do you recommend separate file for each chapter? – Norman Ramsey Aug 4 '20 at 15:08
  • I asked for a MWE as it is not clear to me what you are trying to do. A MWE should clarify this and show the packages that you need. Your example code is not so helpful as it's a snippet that is not well explained and does not compile. Can you clearly describe what want. In particular, how are the exercises numbered, how and where do you want to refer back to the number of exercises? Is it essential that you use \suspend and \resume or are these just commands that you think might help? Please add either a MWE or a mock-up of the output you want. – user30471 Aug 5 '20 at 0:51
  • @Andrew ack! Hadn't realized the problem was unclear. Let's hope the MWE at least states precisely what problem I am trying to solve. – Norman Ramsey Aug 7 '20 at 14:12
0

You can define your own environment and counters.

enter image description here

\documentclass{article}
\usepackage{etoolbox}
\usepackage{expl3}
\usepackage{xparse}
\usepackage{enumitem}

\begin{document}

\ExplSyntaxOn

% define and initialize exercise counter
\int_new:N \g_exercise_count_int
\int_gset:Nn \g_exercise_count_int {0}

\NewDocumentEnvironment{exercise}{O{}}{
    % increment counter when environment starts
    \int_gincr:N \g_exercise_count_int
    % forward optional arguments
    \begin{enumerate}[#1]
}{
    \end{enumerate}
}

\newcommand{\exercisecount}{
    \int_use:N \g_exercise_count_int
}

\ExplSyntaxOff


\begin{exercise}[font=\bfseries]
\item Question 1
\item Question 2
\end{exercise}

\begin{exercise}[label=\Roman*.]
\item Question 1
\item Question 2
\end{exercise}

\begin{exercise}
\item Question 1
\item Question 2
\end{exercise}

Number of exercises: \exercisecount


\end{document}
0

A minimal working example was requested, but I decided the time required to prepare one might be better spend on trying to solve the problem. I defined an exercises environment intended to behave like enumerate and also to keep track of the total number of exercises in the book. I also used package totcounter. Here's what I learned:

  • You can't just ask \item to increment a counter for you, because that would increment inside nested lists.

  • It would work to ask to increment a counter at the end of an exercises environment, except the \suspend macro from package mdwlist ends an environment multiple times. I tried a few tricks, like defining a hook for various suspended environments, but in the end a simple \ifsuspended was easier to get working. This condition enables the \end{exercises} to tell the difference between truly ending and just being suspended.

Code below.

\newtotcounter{exercises}

\newif\ifexercising

\makeatletter



\newenvironment{exercises}
  {\ifexercising
      \@latexerr{Nested exercises}{Don't nest exercise environments}%
   \else
     \exercisingtrue
     \ifnum \@listdepth >1\relax
       \@latexerr{Nested exercises}{Don't put exercises inside another list}%
     \fi
   \fi
   \enumerate
  }
  {\ifsuspended\else\addtocounter{exercises}{\value{enumi}}\fi
   \endenumerate
  }

\def\@suspend@exercises{\addtocounter{exercises}{-\value{enumi}}}

\newif\ifsuspended
\suspendedfalse

\def\suspend@i[#1]#2{%
  \edef\@tempa{%
    \noexpand\suspendedtrue
    \noexpand\end{#2}%
    \def\expandafter\noexpand\csname resume.#1\endcsname{%
      \csname c@\@listctr\endcsname\the\csname c@\@listctr\endcsname%
    }%
  }%
  \@tempa%
}


\makeatother

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.