1

For my homework, I use this enviroment:

\newcounter{exercise}
\renewcommand{\theexercise}{\arabic{exercise}}

\newenvironment{exercise}[1] {\smallskip\refstepcounter{exercise}\textbf{Solution to exercise~\theexercise:}\par\vspace{#1}} {\par \hspace*{\fill}$\square$\medskip}

Sometimes, I have that 'Solution to exercise x' is at the end of the page and the solution starts at the next page or that the '$square$' at the end starts at the next page. I wonder if there is a possibility to let tex check if the next line would start at the next page and then force it to put 'Solution to exercise x' also onto the next page, or in the other case that it would check, if the '$square$' would start at the next page and take the line before that also to the next page.

Code that still causes problems:

\begin{center}
        \begin{tikzpicture}[point/.style={fill, circle, inner sep = 1.3pt}]
            %x axis
            \draw[->] (-2,0) -- (6,0) node[below] {$x$};
            \foreach \x in {-1,1,2,...,5}
            \draw[shift={(\x,0)}] (0pt,2pt) -- (0pt,-2pt) node[below] {\footnotesize $\x$};
            %y axis
            \draw[->] (0,-2) -- (0,3) node[left] {$y$};
            \foreach \y in {-1,1,2}
            \draw[shift={(0,\y)}] (2pt,0pt) -- (-2pt,0pt) node[left] {\footnotesize $\y$};
            \node[below left] at (0,0) {\footnotesize $0$};
            % points
            \node (H) [point,label=above:$H$] at (1,1) {};
            \node (F) [point,label=above:$F$] at (4,2) {};
            \node (X) [point,label={[label distance=0.15cm]350:$x^*$}] at (2,0) {};
            % river
            \draw[blue, line width = 0.4mm] (-1.5,0) -- (5.5,0);
            % path
            \draw[dashed] (H) -- (X);
            \draw[dashed] (X) -- (F);
        \end{tikzpicture}
    \end{center}
question
  • 211

2 Answers2

1

As pointed out by @user202729 in the comments, you can use \nopagebreak directly after the \par macro(s) in your code. If you add [4] as parameter to this macro, it will be very unlikely that (La)TeX breaks the page at this point.

If you also want to prevent widows (that is a single line on the next page), you can additionaly set \widowpenalty10000 at the beginning of your code.

The following code contains two extreme examples to show that the page break will be prevented between the header and the body as all as between the body and the square:

\documentclass{article}
\usepackage{amssymb}

\usepackage{lipsum, xcolor} % just for illustrative purposes

\newcounter{exercise} \renewcommand{\theexercise}{\arabic{exercise}}

\newenvironment{exercise}[1] {\widowpenalty10000\smallskip\refstepcounter{exercise}\textbf{Solution to exercise~\theexercise:}\par\nopagebreak[4]\vspace{#1}} {\par\nopagebreak[4]\hspace*{\fill}$\square$\medskip}

\begin{document}

{\color{lightgray}\lipsum[1-3]}

\begin{exercise}{1.6cm} \lipsum[1] \end{exercise}

{\color{lightgray}\lipsum[1-3]}

\begin{exercise}{5cm} \lipsum[1] \end{exercise}

\end{document}

enter image description here

enter image description here

enter image description here

  • Thank you, but in my extreme case, it is still not working. My ecercise ends with a tikz picture and the square is still on the next page. I added it to my question because the code is too long for a comment. – question Dec 11 '21 at 20:52
1

I suggest using amsthm and its built-in mechanism for the square at the end of proofs.

\documentclass{article}
\usepackage{amsthm}
\usepackage{tikz}

\usepackage{showframe,lipsum} % just for this example

\theoremstyle{definition} \newtheorem{innerexercise}{Solution to exercise} \newenvironment{exercise} {\pushQED{\qed}\innerexercise} {\popQED\endinnerexercise}

\begin{document}

\begin{exercise} \lipsum[1][1-4] [ \begin{tikzpicture}[point/.style={fill, circle, inner sep = 1.3pt}] %x axis \draw[->] (-2,0) -- (6,0) node[below] {$x$}; \foreach \x in {-1,1,2,...,5}{ \draw[shift={(\x,0)}] (0pt,2pt) -- (0pt,-2pt) node[below] {\footnotesize $\x$}; } %y axis \draw[->] (0,-2) -- (0,3) node[left] {$y$}; \foreach \y in {-1,1,2}{ \draw[shift={(0,\y)}] (2pt,0pt) -- (-2pt,0pt) node[left] {\footnotesize $\y$}; } \node[below left] at (0,0) {\footnotesize $0$}; % points \node (H) [point,label=above:$H$] at (1,1) {}; \node (F) [point,label=above:$F$] at (4,2) {}; \node (X) [point,label={[label distance=0.15cm]350:$x^*$}] at (2,0) {}; % river \draw[blue, line width = 0.4mm] (-1.5,0) -- (5.5,0); % path \draw[dashed] (H) -- (X); \draw[dashed] (X) -- (F); \end{tikzpicture}\qedhere ] \end{exercise}

\begin{exercise} \lipsum[2][1-9] \end{exercise}

\end{document}

With a math display you're sure that no page break will be taken before the picture.

enter image description here

If you want that the text starts on a new line:

\documentclass{article}
\usepackage{amsthm}
\usepackage{tikz}

\usepackage{showframe,lipsum} % just for this example

\newtheoremstyle{exercise} {\topsep} % ABOVESPACE {\topsep} % BELOWSPACE {\normalfont} % BODYFONT {0pt} % INDENT (empty value is the same as 0pt) {\bfseries} % HEADFONT {:} % HEADPUNCT {\newline} % HEADSPACE {} % CUSTOM-HEAD-SPEC

\theoremstyle{exercise} \newtheorem{innerexercise}{Solution to exercise} \newenvironment{exercise} {\pushQED{\qed}\innerexercise} {\popQED\endinnerexercise}

\begin{document}

\begin{exercise} \lipsum[1][1-4] [ \begin{tikzpicture}[point/.style={fill, circle, inner sep = 1.3pt}] %x axis \draw[->] (-2,0) -- (6,0) node[below] {$x$}; \foreach \x in {-1,1,2,...,5}{ \draw[shift={(\x,0)}] (0pt,2pt) -- (0pt,-2pt) node[below] {\footnotesize $\x$}; } %y axis \draw[->] (0,-2) -- (0,3) node[left] {$y$}; \foreach \y in {-1,1,2}{ \draw[shift={(0,\y)}] (2pt,0pt) -- (-2pt,0pt) node[left] {\footnotesize $\y$}; } \node[below left] at (0,0) {\footnotesize $0$}; % points \node (H) [point,label=above:$H$] at (1,1) {}; \node (F) [point,label=above:$F$] at (4,2) {}; \node (X) [point,label={[label distance=0.15cm]350:$x^*$}] at (2,0) {}; % river \draw[blue, line width = 0.4mm] (-1.5,0) -- (5.5,0); % path \draw[dashed] (H) -- (X); \draw[dashed] (X) -- (F); \end{tikzpicture}\qedhere ] \end{exercise}

\begin{exercise} \lipsum[2][1-9] \end{exercise}

\end{document}

enter image description here

egreg
  • 1,121,712
  • I think this only works because you don't have a new line before the square or am I wrong? I also lose the option to add or remove space after the 'Solution to exercise x', which I need because enviroments like enumerate add some not needed space if I use them directly (I use standalone for the exercises, so I don't want to adjust the space in these files). – question Dec 13 '21 at 15:08
  • @question You don't want the square on a separate line if there's enough space. If the last line is short, the square would seem to hang from nowhere. – egreg Dec 13 '21 at 15:14
  • I think it looks better this way – question Dec 15 '21 at 16:48