# How to get to total number of lines in an environment

While trying to figure a complete answer to this post, I was wondering how I could get the total amount of lines in the algorithmic environment.

Of course this question can be relevant for other environments.

I already tried with the totcount package but when trying to use the final value of a counter with \totalvalue{<counter>} inside a \makeatketter ... \makeatother it fails.

I'm pretty sure I am missing some basic thing so would like to understand this issue better.

Other previous answers e.g. this one for instance address this issue for other environments but I could not figure how to adapt them to this case.

Here is the MWE adapted from the post I am trying to answer.

\documentclass[a4paper,10pt]{IEEEtran}
\usepackage{totcount}
\usepackage{algpseudocode}

\regtotcounter{ALG@line}

% Patch the line numbering to display the first and last line numbers
\makeatletter
\def\ALG@step%
{%
% Beginning of patch
% First line
\ifthenelse{\equal{\arabic{ALG@line}}{1}}%
{\alglinenumber{\arabic{ALG@line}}}%
{}%
% Last line  --> DOES NOT WORK
%   \ifthenelse{\equal{\arabic{ALG@line}}{\arabic{\total{ALG@line}}}}%
%      {\alglinenumber{\arabic{ALG@line}}}%
%      {}%
% End of patch
\ifthenelse{\equal{\arabic{ALG@rem}}{\ALG@numberfreq}}%
{\setcounter{ALG@rem}{0}\alglinenumber{\arabic{ALG@line}}}%
{}%
}%
\makeatother

\begin{document}
See \figurename{~\ref{fig:myalgorithm}} below.

\begin{figure}[!ht]
\noindent\rule{\linewidth}{0.8pt}
\noindent \textbf{Algorithm} itsname
\noindent\hrule
\begin{algorithmic}[3]
\Procedure {BellmanKalaba}{$G$, $u$, $l$, $p$}
\ForAll {$v \in V(G)$}
\State $l(v) \leftarrow \infty$
\EndFor
\State $l(u) \leftarrow 0$
\Repeat
\For {$i \leftarrow 1, n$}
\State $min \leftarrow l(v_i)$
\For {$j \leftarrow 1, n$}
\If {$min > e(v_i, v_j) + l(v_j)$}
\State $min \leftarrow e(v_i, v_j) + l(v_j)$
\State $p(i) \leftarrow v_j$
\EndIf
\EndFor
\State $l'(i) \leftarrow min$
\EndFor
\State $changed \leftarrow l \not= l'$
\State $l \leftarrow l'$
\Until{$\neg changed$}
\EndProcedure
\end{algorithmic}
\noindent\rule{\linewidth}{0.8pt}
\caption{This algorithm was copied from the algorithmicx's package documentation.}\label{fig:myalgorithm}
\end{figure}

Total amount of lines in the algorithm: \total{ALG@line}

\end{document}


• I'd use a two run solution saving the highest counter number of the current environment. How else should the line number printing command know it's the last one. – Skillmon Sep 4 '18 at 12:19
• One could do so by adding stuff to \endalgorithmic (e.g. with etoolbox and \AtEndEnvironment), but you'd have to take care that you get a separate marker for each algorithmic, e.g. by using another counter. – Skillmon Sep 4 '18 at 12:24
• @Skillmon, I would also use a two step process, hence the totcount package. However, I can't figure how to provide the stored value to the definition of \ALG@step so it can be used for some logical test – BambOo Sep 4 '18 at 12:35
• So the goal to fix your \ALG@step, not get the number of lines (\arabic{ALG@line}). – John Kormylo Sep 4 '18 at 13:22
• @JohnKormylo. Well it's both. I know how to patch \ALG@step, but i don't know how to provide the total amount of lines in it. – BambOo Sep 4 '18 at 13:32

The following is a two-run approach solving your issue. I permit you to use it in order to answer the other question, but please give me credit :)

\documentclass[a4paper,10pt]{IEEEtran}
\usepackage{totcount}
\usepackage{algpseudocode}

\usepackage{etoolbox}

\regtotcounter{ALG@line}

% Patch the line numbering to display the first and last line numbers
\makeatletter
% execute this code at \end{algorithmic} but before the group is closed
\AtEndEnvironment{algorithmic}{\@WriteAlgorithmicLastLine}
% execute this code at \begin{algorithmic} just after the group is opened
\AtBeginEnvironment{algorithmic}{\stepcounter{AlgorithmicEnvironmentCounter}}
\newcounter{AlgorithmicEnvironmentCounter}
\newcommand*\@WriteAlgorithmicLastLine
{% this macro writes the definition to the aux file, you have to make sure
% that only the right stuff is expanded (\write expands its argument as
% much as it is able to)
\immediate\write\@auxout
{%
% we don't want \expandafter to disappear
\unexpanded{\expandafter\gdef}%
% we don't want \csname to do its work just here
\unexpanded{\csname @AlgorithmicLastLine@}%
% the counter should be expanded
\the\c@AlgorithmicEnvironmentCounter%
% \endcsname isn't expandable (if you're unsure whether something is
% expandable enclose it by \unexpanded or precede it with \noexpand)
\endcsname%
% this counter should as well be expanded
{\arabic{ALG@line}}%
}%
}
\def\ALG@step%
{%
% Beginning of patch
\ifthenelse{\equal{\arabic{ALG@rem}}{\ALG@numberfreq}}%
{\setcounter{ALG@rem}{0}\alglinenumber{\arabic{ALG@line}}}%
{% if it is no line that already gets a number one of the other rules
% might apply
\ifthenelse{\equal{\arabic{ALG@line}}{1}}%
{\alglinenumber{\arabic{ALG@line}}}%
{% if not the first line, it may be the last
% \ifcsdef is a wrapper around \ifcsname to check whether something
% is defined or not
\ifcsdef
{@AlgorithmicLastLine@\arabic{AlgorithmicEnvironmentCounter}}%
{% if it is defined execute this code
% \ifnum is a TeX primitive comparing the following two numbers
% and executing the true branch if the comparison is true,
% possible comparisons are '=', '>' and '<'.
\ifnum
% csuse is a wrapper around \csname building the
% control-sequence which's name is the argument of \csuse
% (argument is fully expanded)
\csuse
{%
@AlgorithmicLastLine@%
\arabic{AlgorithmicEnvironmentCounter}%
}%
=\c@ALG@line
\alglinenumber{\arabic{ALG@line}}%
\fi
}%
{}% not defined
}%
}%
}%
\makeatother

\begin{document}
See \figurename{~\ref{fig:myalgorithm}} below.

\begin{figure}[!ht]
\noindent\rule{\linewidth}{0.8pt}
\noindent \textbf{Algorithm} itsname
\noindent\hrule
\begin{algorithmic}[3]
\Procedure {BellmanKalaba}{$G$, $u$, $l$, $p$}
\ForAll {$v \in V(G)$}
\State $l(v) \leftarrow \infty$
\EndFor
\State $l(u) \leftarrow 0$
\Repeat
\For {$i \leftarrow 1, n$}
\State $min \leftarrow l(v_i)$
\For {$j \leftarrow 1, n$}
\If {$min > e(v_i, v_j) + l(v_j)$}
\State $min \leftarrow e(v_i, v_j) + l(v_j)$
\State $p(i) \leftarrow v_j$
\EndIf
\EndFor
\State $l'(i) \leftarrow min$
\EndFor
\State $changed \leftarrow l \not= l'$
\State $l \leftarrow l'$
\Until{$\neg changed$}
\EndProcedure
\end{algorithmic}
\noindent\rule{\linewidth}{0.8pt}
\caption
{%
This algorithm was copied from the algorithmicx's package documentation.%
\label{fig:myalgorithm}%
}
\end{figure}

Total amount of lines in the algorithm: \total{ALG@line}

\begin{figure}[!ht]
\noindent\rule{\linewidth}{0.8pt}
\noindent \textbf{Algorithm} itsname
\noindent\hrule
\begin{algorithmic}[3]
\Procedure {BellmanKalaba}{$G$, $u$, $l$, $p$}
\ForAll {$v \in V(G)$}
\State $l(v) \leftarrow \infty$
\EndFor
\State $l(u) \leftarrow 0$
\Repeat
\For {$i \leftarrow 1, n$}
\State $min \leftarrow l(v_i)$
\For {$j \leftarrow 1, n$}
\If {$min > e(v_i, v_j) + l(v_j)$}
\State $min \leftarrow e(v_i, v_j) + l(v_j)$
\State $p(i) \leftarrow v_j$
\EndIf
\EndFor
\State $l'(i) \leftarrow min$
\EndFor
\Until{$\neg changed$}
\EndProcedure
\end{algorithmic}
\noindent\rule{\linewidth}{0.8pt}
\caption
{%
This algorithm was copied from the algorithmicx's package documentation.%
\label{fig:myalgorithm2}%
}
\end{figure}

\end{document}


EDIT: I've added some comments in the above code hopefully describing everything.

EDIT 2: Solving the bugs of multiple line numberings.

• Well thanks Skillmon ! I checked etoolbox too but I just don't know enough of such commands to make a solution on my own. If you could just add a few comments, to fully understand what you propose it would be perfect ! I will of course credit you in the initial post ;) – BambOo Sep 4 '18 at 15:14
• @BambOo see my edits, I hope the comments are enough, if anything remains unclear just ask. – Skillmon Sep 4 '18 at 15:30
• Thanks. There is still a small glitch, but let me try to find myself so I can take a bit of credit ^^. FYI, the last line may be print twice due to the redundancy bteween your patch and \ALG@numberfreq – BambOo Sep 4 '18 at 15:34
• @BambOo you're right, but that is easy enough to fix :) – Skillmon Sep 4 '18 at 15:37

Since counters are saved globally, all you need is \arabic{ALG@line}. If you want to access it before it is computed, you can fake a \label.

\documentclass[a4paper,10pt]{IEEEtran}
\usepackage{totcount}
\usepackage{algpseudocode}

\begin{document}
See \figurename{~\ref{fig:myalgorithm}} below (\ref{ALGlines} lines).

\begin{figure}[!ht]
\noindent\rule{\linewidth}{0.8pt}
\noindent \textbf{Algorithm} itsname
\noindent\hrule
\begin{algorithmic}[3]
\Procedure {BellmanKalaba}{$G$, $u$, $l$, $p$}
\ForAll {$v \in V(G)$}
\State $l(v) \leftarrow \infty$
\EndFor
\State $l(u) \leftarrow 0$
\Repeat
\For {$i \leftarrow 1, n$}
\State $min \leftarrow l(v_i)$
\For {$j \leftarrow 1, n$}
\If {$min > e(v_i, v_j) + l(v_j)$}
\State $min \leftarrow e(v_i, v_j) + l(v_j)$
\State $p(i) \leftarrow v_j$
\EndIf
\EndFor
\State $l'(i) \leftarrow min$
\EndFor
\State $changed \leftarrow l \not= l'$
\State $l \leftarrow l'$
\Until{$\neg changed$}
\EndProcedure
\end{algorithmic}
\noindent\rule{\linewidth}{0.8pt}
\caption{This algorithm was copied from the algorithmicx's package documentation.}\label{fig:myalgorithm}

• I guess I wasn't clear enough. The last sentence is there just for example. The issue is in the patch for algorithmicx that I am trying to provide. – BambOo Sep 4 '18 at 13:17