3

Writing lecture notes containing exercises and solutions, I would like to create hyperlinks from the exercises to their solutions and vice versa. I use the packages mdframed, hyperref and answers (and for some reasons I would like to stick at least with the first two). The example below almost does what I want. However, the hyperlink from an exercise to its solution is now the name ("Exercise") of the exercise, while I would like it to be its number ("1"). How can I achieve this?

\documentclass{book}

\usepackage{answers} \usepackage{hyperref} \usepackage[framemethod=tikz]{mdframed}

\Newassociation{sol}{answ}{ans}\Opensolutionfile{ans}

\mdtheorem{ex}{\hyperlink{ex:\theex}{Exercise}\hypertarget{sol:\theex}{}} \renewenvironment{answ}[1]{{\hypertarget{ex:#1}{}\hyperlink{sol:#1}{#1}}\quad}{}

\begin{document}

\begin{ex} This is an exercise. \begin{sol} This is the solution. \end{sol} \end{ex}

\Closesolutionfile{ans} \input{ans}

\end{document}

3 Answers3

5

Although you want to stick to mdframed I propose a solution with tcolorbox because it can provide mdframed+answer behaviour. This solution also uses hyperref for links.

Like answers, tcolorbox offers some commands and environments to define boxes with parts which will be saved on an external file and printed later on.

Following code is a simplification of example in section 8.3 from tcolorbox documentation (something similar can be seen here)

Every ex box will save the solution (text after \tcblower) into an independent file.

Command \tcbstartrecording[file1] will start to save into file1 the name of all exercises to be included into the solutions list.

Command \tcbstoprecording does what it says.

Command \tcbinputrecords[file1] loads all solutions and print them.

About references, I've suposed that every exercise contains a solution and they respective names are references to their solution/exercise.

\documentclass{article}

\usepackage[most]{tcolorbox} \usepackage{hyperref}

\NewTColorBox[auto counter]{ex}{+O{}}{% enhanced, colframe=black, colback=white, sharp corners, attach title to upper=\par, coltitle=black, fonttitle=\bfseries, title={Exercise~\ref{solution@\thetcbcounter}}, label={exercise@\thetcbcounter}, lowerbox=ignored, savelowerto=solutions/exercise-\thetcbcounter.tex, record={\string\solution{\thetcbcounter}% {solutions/exercise-\thetcbcounter.tex}}, #1}

\NewTotalTColorBox[auto counter]{\solution}{mm}{% enhanced, blanker,
coltitle=black, fonttitle=\bfseries, title={\ref{exercise@\thetcbcounter}}, label={solution@\thetcbcounter}, attach title to upper={\ }, }{\input{#2}}

\begin{document}

% We start to record all tcblower parts in file file1 for later processing \tcbstartrecording[file1]

%Every exercise box contains an upper part which is processed and %printed and a lower (solution) which printing is delayed. % \begin{ex} This is an exercise. \tcblower This is the solution for first exercise \end{ex}

\begin{ex} This is an exercise. \tcblower This is the solution for second exercise \end{ex}

\tcbstoprecording

%previous recorded files with solutions are processed and printed \tcbinputrecords[file1]

\end{document}

enter image description here

Ignasi
  • 136,588
  • tcolorbox is great :) – NBur Jan 26 '21 at 07:45
  • Dear @Ignasi, thanks for your answer. It solves my problem. Of course, the downside is that I have to learn how to use tcolorbox to get what I did up to now with mdframed, but maybe that is a good idea anyway. – Fred Rohrer Jan 27 '21 at 15:48
  • @Ignasi: There is a small problem. If I set a label to an ex-environment and refer to it with \ref, this does not work anymore (i.e., results in questions marks). Do you know why? – Fred Rohrer Jan 27 '21 at 15:50
  • @FredRohrer If you look at the code, every ex and sol declare its own label which are exercise@\thetcbcounter and solution@\thetcbcounter, you can use them or change it according your convenience. – Ignasi Jan 27 '21 at 15:55
  • @FredRohrer About changing from mdframed to tcolorbox should be not too difficult. You already know where to find help ;-) – Ignasi Jan 27 '21 at 15:57
  • Ah, now I understand the issue with the label. But it seems to be not stable, i.e., a reference to Exercise 1 is \ref{exercise@1} (needs me to look up the number) and has to be changed if I insert an exercise before Exercise 1. – Fred Rohrer Jan 27 '21 at 16:09
  • @FredRohrer Please look at updated code. Now every ex has a mandatory parameter which is the label. \begin{ex}{first} -> \ref{first}. My test worked, but I don't know in your work case. – Ignasi Jan 27 '21 at 17:39
  • Dear @Ignasi, thanks again for your answer and the additional information. It was not easy for me to choose who gets the bounty. – Fred Rohrer Jan 28 '21 at 18:47
3

You can redefine \theex at the beginning of the mdtheorem, using startcode option:

\documentclass{book}

\usepackage{answers} \usepackage{hyperref} \usepackage[framemethod=tikz]{mdframed}

\Newassociation{sol}{answ}{ans}\Opensolutionfile{ans}

\mdtheorem[startcode={\let\theexold\theex\renewcommand{\theex}{\hyperlink{ex:\theexold}{\theexold}\hypertarget{sol:\theexold}{}}}]{ex}{Exercise} \renewenvironment{answ}[1]{{\hypertarget{ex:#1}{}\hyperlink{sol:#1}{#1}}\quad}{}

\begin{document}

\begin{ex}
    This is an exercise.
    \begin{sol}
        This is the solution.
    \end{sol}
\end{ex}

\begin{ex}
    This is an exercise.
    \begin{sol}
        This is the solution.
    \end{sol}
\end{ex}
\Closesolutionfile{ans}
\input{ans}

\end{document}

enter image description here

NBur
  • 4,326
  • 10
  • 27
  • Dear @NBur, thanks a lot! This seems to do what I want. I have to wait to award the bounty, but I will wait anyway some time to see whether there are other suggestions. (But it seems to be hard to find one that is more elegant.) – Fred Rohrer Jan 22 '21 at 09:35
  • Maybe there is a more elegant solution: I'm a bit disappointed having to redefine \theex each time the environment is called. – NBur Jan 22 '21 at 13:03
  • Dear @NBur, thanks again for your answer. It was not easy for me to choose who gets the bounty. – Fred Rohrer Jan 28 '21 at 18:47
0

Another proposal using xsim instead of answers but using your requirement mdframed:

\documentclass{book}

\usepackage[framemethod=tikz]{mdframed} \usepackage{xsim} \usepackage{hyperref}

\DeclareExerciseEnvironmentTemplate{myex}{% \begin{mdframed}[% frametitle={% \hypertarget{ex:\ExerciseID}{\XSIMmixedcase{\GetExerciseName}} \hyperlink{sol:\ExerciseID}{\GetExerciseProperty{counter}}% }]% }{\end{mdframed}}

\DeclareExerciseEnvironmentTemplate{mysol}{% \par\noindent \hyperlink {ex:\ExerciseID} {\hypertarget{sol:\ExerciseID}{\GetExerciseProperty{counter}}}% \quad }{\par}

\xsimsetup{ exercise/template = myex , solution/template = mysol , print-solutions/headings = false }

\begin{document}

\begin{exercise} This is an exercise. \end{exercise} \begin{solution} This is the solution. \end{solution} \begin{exercise} This is another exercise. \end{exercise} \begin{solution} This is the other solution. \end{solution}

\printsolutions

\end{document}

enter image description here

Should you later want to switch to tcolorbox instead it would only require changing the template definition myex:

\DeclareExerciseEnvironmentTemplate{myex}{%
  \begin{tcolorbox}[sharp corners, colback = white]
    \textbf{%
      \hypertarget{ex:\ExerciseID}{\XSIMmixedcase{\GetExerciseName}}
      \hyperlink{sol:\ExerciseID}{\GetExerciseProperty{counter}}%
    }\par\smallskip
}{\end{tcolorbox}}

It would also be possible to define the environments ex and sol if you'd insist on these names:

Load the package with the blank option, it now does not define exercise and solution

\usepackage[blank]{xsim}

and define ex and sol:

\DeclareExerciseType {exercise} {
  exercise-env      = ex ,
  solution-env      = sol ,
  exercise-name     = \XSIMtranslate {exercise} ,
  exercises-name    = \XSIMtranslate {exercises} ,
  solution-name     = \XSIMtranslate {solution} ,
  solutions-name    = \XSIMtranslate {solutions} ,
  exercise-template = myex ,
  solution-template = mysol
}

As option setup now only \xsimsetup{print-solutions/headings = false} is needed in the above example and the environmants can be changed:

\begin{ex}
  This is an exercise.
\end{ex}
\begin{sol}
  This is the solution.
\end{sol}
\begin{ex}
  This is another exercise.
\end{ex}
\begin{sol}
  This is the other solution.
\end{sol}
cgnieder
  • 66,645
  • Dear @cgnieder, thanks for your answer (and also thanks for your package!). The cluttering of my folder is maybe not optimal, but a brief look at the xsim documentation shows that there seems to be a way around this. I will have to spend some time and get to know your package. – Fred Rohrer Jan 27 '21 at 16:02
  • 1
    @Fred it's easy: \usepackage[no-files]{xsim} – cgnieder Jan 27 '21 at 17:27
  • Dear @cgnieder, thanks for all the additional information and the update. It is hard to choose, but I will reward your answer with the bounty. It seems to me to be the clearest way to get what I want (but this has maybe more to do with my limited understanding of LaTeX). – Fred Rohrer Jan 28 '21 at 18:45