[Tex/LaTex] How to sanely format conditionals in clrscode package

algorithmsindentation

clrscode can produce some really nice-looking algorithm texts, but if you have nested conditionals, things start to look ugly. clrscode has the peculiar preference that the \Then keyword at the end of an \If statement should go on a second line, indented.

Not only is this not very compact (needed for a paper in two-column format!), it runs counter to the convention in most mainstream programming languages. If you try to place the \Then at the end of the same line that the \If is on, the package often overprints the \Then on top of the conditional expression!

To be clear, you need to do this

\li \If $a = b$
\li   \Then foo

but I would really like to do

\li \If $a = b$ \Then foo

or

\li \If $a = b$ \Then
\li   foo

Furthermore, I would like to be able to line up \Else statements with the preceding \If (not the preceding \Then!), and this does not seem to be possible, either.

Any pointers?

Best Answer

clrscode sets the algorithm inside a box (lrbox) of fixed with (using a minipage environment), and aligns the algorithm content using tabbing. The following updates \Then and \Else (and \Until) fits within your requirements (I think):

enter image description here

\documentclass{article}
\usepackage{clrscode}% http://www.cs.dartmouth.edu/~thc/clrscode/
\begin{document}
\begin{codebox}
  \Procname{$\proc{Hash-Insert}(T,k)$}
  \li $i \gets 0$
  \li \Repeat
  \li   $j \gets h(k,i)$
  \li   \If $T[j] == \const{nil}$
  \li   \Then
          $T[j] \gets k$
  \li     \Return $j$
  \li   \Else
          $i \gets i+1$
        \End
  \li \Until $i == m$
  \li \Error ``hash table overflow''
\end{codebox}

% Updates to \Then and \Else
\renewcommand{\Then}{%
  \textbf{then}\stepcounter{indent} }
\renewcommand{\Else}{%
  \kill\addtocounter{indent}{-1}%
  \liprint\textbf{else}\>\>\stepcounter{indent}}
\renewcommand{\Until}{%
  \addtocounter{indent}{-1}%
  \kill\liprint\textbf{until} }

\begin{codebox}
  \Procname{$\proc{Hash-Insert}(T,k)$}
  \li $i \gets 0$
  \li \Repeat
  \li   $j \gets h(k,i)$
  \li   \If $T[j] == \const{nil}$ \Then
  \li     $T[j] \gets k$
  \li     \Return $j$
  \li   \Else $i \gets i+1$
        \End
  \li \Until $i == m$
  \li \Error ``hash table overflow''
\end{codebox}

\end{document}

Of course, more corrections in terms of the input is possible, depending on some clarification.

Also, clrscode3e exists which is a "third edition" update of clrscode (used in editions 1 and 2 of Introduction to Algorithms). This update, as stated in the clrscode3e documentation contains a number of user-feedback improvements. Specific to the \If-\Then clauses (section Typesetting if statements, p 8):

In the first two editions of the book, the keyword then appeared in pseudocode, but — again mindful of requests from our readers to make our pseudocode more like C, C++, and Java — we eliminated the keyword then in the third edition. The \Then command remains, however, in order to indent the code that runs when the test in the if clause evaluates to TRUE.

From clrscode.sty, here's the formal definition of all the keywords:

% All of our favorite keywords.
\newcommand{\For}{\textbf{for} }
\newcommand{\To}{\textbf{to} }
\newcommand{\By}{\textbf{by} }
\newcommand{\Downto}{\textbf{downto} }
\newcommand{\While}{\textbf{while} }
\newcommand{\Repeat}{\textbf{repeat}\>\>\addtocounter{indent}{1}}
\newcommand{\Until}{\kill\addtocounter{indent}{-1}\liprint\>\>\textbf{until}\hspace*{-0.7em}\'}
\newcommand{\If}{\textbf{if} }
\newcommand{\Then}{\>\textbf{then}\>\addtocounter{indent}{1}}
\newcommand{\Else}{\kill\addtocounter{indent}{-1}\liprint\>\textbf{else}\>\addtocounter{indent}{1}}
\newcommand{\End}{\addtocounter{indent}{-1}}
\newcommand{\ElseIf}{\kill\addtocounter{indent}{-1}\liprint\textbf{elseif} }
\newcommand{\ElseNoIf}{\kill\addtocounter{indent}{-1}\liprint\textbf{else} \addtocounter{indent}{1}}
\newcommand{\Do}{\>\>\textbf{do}\hspace*{-0.7em}\'\addtocounter{indent}{1}}
\newcommand{\Return}{\textbf{return} }
\newcommand{\Comment}{$\hspace*{-0.075em}\rhd$ }
\newcommand{\RComment}{\`\Comment}
\newcommand{\Goto}{\textbf{goto} }
\newcommand{\Error}{\textbf{error} } % optionally followed by string argument