2

I am very new to this website, and am still in the learning stage of LaTeX/TeX. Recently i stumbled upon the Ackermann Function exercise, and i still can't figure out how to complete it properly. That is when i started to lookup online if a solution already exists, but i could find anything expect for this question here.

My problem is that i do not know how to use expl3, because we still haven't learnt it, so we were told to just create a 'basic' solution, that could compute so of the lower terms of the Ackermann Function.

Just to recap, the Ackermann Function is defined as follows

enter image description here

It seems like a very innocent recursive function, but very fast, it will cause a time out because of how big the number are.

This brings me back to computing The Ackermann Function. Many solutions were given to compute the solution, but i was wondering if it would be possible 'update' the macros, so that it displays to different stages. For example, calling \Ackermann{2}{0} would yield enter image description here.

Or calling `\Ackermann{2}{2} would yield enter image description here

Once again, i repeat myself, we were told to create a 'basic' macro, so no need to worry about computing \A{10}{49}

I hope this was clear, and thank you in advance. Lea

EDIT: I tried to progress a little bit by analysing the solutions of this question, and i managed to understand (or so i thought), one of the solution. I was able to replicate @wipet 's solution, but without using \afterfi because i don't really understand it. Here is the code

\begin{document}

\makeatletter
\def\A#1#2{%
    \ifnum#1=\z@
        \number\numexpr#2+1\relax%
    \else 
        \ifnum#2=\z@
            \A@i{\numexpr#1-1\relax}{1}%
    \else
        \A@i{\numexpr#1-1\relax}{\expanded{\A@i{#1}{\numexpr#2-1\relax}}}%
    \fi\fi%
}
\def\A@i#1#2{\expanded{\noexpand\A{#1}{#2}}}

\def\acker@values{}
\def\update@values#1{%
    \edef\acker@values{\acker@values #1}
}
\makeatother

\end{document}

I wanted to use \acker@values and \update@values to store the different step, but i cannot figure it out. My problem now is not being able to display the steps.

1
  • Would a solution using pythontex be considered cheating? I think it would probably be both easier to read and easier to write... :-) – Willie Wong Feb 24 at 1:54
3

Here another attempt—this time without \romannumeral-expansion.
Instead, the routine \Ackermann uses \expanded.

It is faster than the \romannumeral-attempt in my other answer.

Nonetheless be warned:

\Ackermannsteps{3}{3} produces 53 A4-pages with many lines exceeding the width of the A4 paper.
\Ackermannsteps{3}{4} yields ! TeX capacity exceeded, sorry [main memory size=5000000].

\documentclass{article}
\usepackage{amsmath}
\usepackage{bigintcalc}

\newcommand\UDfirstoftwo[2]{#1}%
\newcommand\UDsecondoftwo[2]{#2}%
\newcommand\UDPassFirstToSecond[2]{#2{#1}}%

\DeclareMathOperator{\AckermannFunction}{A}

% -------------------------------------------------------------------------------
% Ackermann-function:
%
% A(m,n) :=  if m = 0 : n+1
%            if m > 0 and n = 0: A(m-1, 1)
%            if m > 0 and n > 0: A(m-1, A(m, n-1))
% m non-negative integer 
% n non-negative integer
%--------------------------------------------------------------------------------
%%
%================================================================================
%
% \Ackermann{m}{n}
%
% Delivers the solution after two "hits" by \expandafter
%
%--------------------------------------------------------------------------------
\newcommand\Ackermann[2]{%
  \expanded{\Ackermannloop{#1}{#2}}%
}%
\newcommand\Ackermannloop[2]{%
  \ifnum\bigintcalcCmp{#1}{0}=0 \expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
  {\bigintcalcInc{#2}}{%
    \ifnum\bigintcalcCmp{#2}{0}=0 \expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
    {%
      \expandafter\expandafter\expandafter\Ackermannloop
      \expandafter\expandafter\expandafter{\bigintcalcDec{#1}}{1}%
    }%
    {%
      \expandafter\UDPassFirstToSecond\expandafter{%
        \expanded{%
          \expandafter\expandafter\expandafter\UDPassFirstToSecond
          \expandafter\expandafter\expandafter{\bigintcalcDec{#2}}{\Ackermannloop{#1}}%
        }%
      }{%
        \expandafter\expandafter\expandafter\Ackermannloop
        \expandafter\expandafter\expandafter{\bigintcalcDec{#1}}%
      }%
    }%
  }%
}%
%================================================================================
%
% \Ackermannsteps{<m>}{<n>}
%
% Prints the single steps of computing the Ackermann-function.
% Delivers all steps after two "hits" by \expandafter
%
%--------------------------------------------------------------------------------
\newcommand\Ackermannsteps[2]{%
  \noindent\rlap{$\AckermannFunction(#1, #2)$}\Ackermannstepsloop{#1}{#2}{$\phantom{\AckermannFunction(#1, #2){}}=}{$\\}%
}%
\newcommand\Ackermannstepsloop[4]{%
  % #1 = m
  % #2 = n
  % #3 = tokens to prepend to the term developped
  % #3 = tokens to append to the term developped
  \ifnum\bigintcalcCmp{#1}{0}=0 \expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
  {#3\bigintcalcInc{#2}#4}{%
    \ifnum\bigintcalcCmp{#2}{0}=0 \expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
    {%
       #3\AckermannFunction(\bigintcalcDec{#1}, 1)#4%
       \expandafter\expandafter\expandafter\Ackermannstepsloop
       \expandafter\expandafter\expandafter{\bigintcalcDec{#1}}{1}%
    }%
    {%
      #3\AckermannFunction(\bigintcalcDec{#1}, \AckermannFunction(#1, \bigintcalcDec{#2}))#4%
      \expandafter\expandafter\expandafter\UDPassFirstToSecond
      \expandafter\expandafter\expandafter{\bigintcalcDec{#2}}{\Ackermannstepsloop{#1}}%
      {#3\AckermannFunction(\bigintcalcDec{#1}, }{)#4}%
      \expandafter\UDPassFirstToSecond\expandafter{%
        \expanded{%
          \expandafter\expandafter\expandafter\UDPassFirstToSecond
          \expandafter\expandafter\expandafter{\bigintcalcDec{#2}}{\Ackermannloop{#1}}%
        }%
      }{%
        \expandafter\expandafter\expandafter\Ackermannstepsloop
        \expandafter\expandafter\expandafter{\bigintcalcDec{#1}}%
      }%
    }%
    {#3}{#4}%
  }%
}%


\begin{document}

\noindent Testing \verb|\Ackermannsteps|: \bigskip

%\Ackermannsteps{0}{0} \bigskip

\Ackermannsteps{2}{0} \bigskip

%\Ackermannsteps{2}{1} \bigskip

\Ackermannsteps{2}{2} \bigskip

%\Ackermannsteps{2}{3} \bigskip

%\Ackermannsteps{2}{4} \bigskip

%\Ackermannsteps{3}{2} \bigskip

%\Ackermannsteps{3}{1} \bigskip

%\Ackermannsteps{3}{2} \bigskip

%\Ackermannsteps{3}{3} \bigskip

% \Ackermannsteps{3}{4}
% I suppose the above yields something like:
% ! TeX capacity exceeded, sorry [main memory size=5000000].


\newpage

\noindent Testing \verb|\Ackermann|: \bigskip

$\AckermannFunction(0, 0)=\Ackermann{0}{0}$

$\AckermannFunction(1, 0)=\Ackermann{1}{0}$

$\AckermannFunction(2, 0)=\Ackermann{2}{0}$

$\AckermannFunction(0, 1)=\Ackermann{0}{1}$

$\AckermannFunction(0, 2)=\Ackermann{0}{2}$

$\AckermannFunction(1, 1)=\Ackermann{1}{1}$

$\AckermannFunction(2, 2)=\Ackermann{2}{2}$

$\AckermannFunction(2, 3)=\Ackermann{2}{3}$

$\AckermannFunction(3, 2)=\Ackermann{3}{2}$

$\AckermannFunction(3, 3)=\Ackermann{3}{3}$

$\AckermannFunction(3, 4)=\Ackermann{3}{4}$

% \Ackermann{4}{2}
% I suppose the above yields something like:
% ! TeX capacity exceeded, sorry [input stack size=5000].


\end{document}

enter image description here

enter image description here



A slight modification can be:

If you want to, you can keep record of argument-pairs whose Ackermann-function-values were already calculated. Then shortcut by just delivering the result instead of delivering all steps can be done in case an argument-pair is already recorded.

Recording can be done, e.g., by defining macros whose names are of pattern Ack(⟨m⟩)(⟨n⟩). Then shortcuts can be done by calling these macros if defined.

This relies on

  • the integer-parameter \globaldefs not having a positive value.
  • the command-namespace \Ack(⟨non-negative integer 1⟩)(⟨non-negative integer 2⟩) being freely available.

As record of already calculated Ackermann-function-values is kept by means of locally defining macros, \Ackermannsteps is not expandable and more memory is needed. TeX-Capacity-exceeded-errors are more likely to occur. Instead of storing already calculated Ackermann-function-values (which might be very big values and therefore might be a large amount of tokens to store so that storing might consume a lot of memory) one could maintain a list of argument-value-pairs and in case the arguments passed to \Ackermannstepsloop are already in the list just call \Ackermannloop for obtaining the number instead of doing the entire recursive step-printing-routine. This way not every Ackermann-function-value already calculated would be stored. Therefore this might require less memory. But the same Ackermann-function-values would be calculated repeatedly. Therefore this would be more time-consuming.

\documentclass{article}
\usepackage{amsmath}
\usepackage{bigintcalc}

\newcommand\UDfirstoftwo[2]{#1}%
\newcommand\UDsecondoftwo[2]{#2}%
\newcommand\UDPassFirstToSecond[2]{#2{#1}}%
\newcommand\UDexchange[2]{#2#1}%
\makeatletter
\@ifdefinable\Stopromannumeral{\chardef\Stopromannumeral=`\^^00}%
\@ifdefinable\CsNameToCsToken{%
  \long\def\CsNameToCsToken#1#{\romannumeral\InnerCsNameToCsToken{#1}}%
}%
\newcommand\InnerCsNameToCsToken[2]{%
  \expandafter\UDexchange\expandafter{\csname#2\endcsname}{\Stopromannumeral#1}%
}%
\makeatother


% -------------------------------------------------------------------------------
% Ackermann-function:
%
% A(m,n) :=  if m = 0 : n+1
%            if m > 0 and n = 0: A(m-1, 1)
%            if m > 0 and n > 0: A(m-1, A(m, n-1))
% m non-negative integer 
% n non-negative integer
%--------------------------------------------------------------------------------
%%
%================================================================================
%
% \Ackermann{m}{n}
%
% Delivers the solution after two "hits" by \expandafter
%
%--------------------------------------------------------------------------------
\newcommand\Ackermann[2]{%
  \expanded{\Ackermannloop{#1}{#2}}%
}%
\newcommand\Ackermannloop[2]{%
  \ifnum\bigintcalcCmp{#1}{0}=0 \expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
  {\bigintcalcInc{#2}}{%
    \ifnum\bigintcalcCmp{#2}{0}=0 \expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
    {%
      \expandafter\expandafter\expandafter\Ackermannloop
      \expandafter\expandafter\expandafter{\bigintcalcDec{#1}}{1}%
    }%
    {%
      \expandafter\UDPassFirstToSecond\expandafter{%
        \expanded{%
          \expandafter\expandafter\expandafter\UDPassFirstToSecond
          \expandafter\expandafter\expandafter{\bigintcalcDec{#2}}{\Ackermannloop{#1}}%
        }%
      }{%
        \expandafter\expandafter\expandafter\Ackermannloop
        \expandafter\expandafter\expandafter{\bigintcalcDec{#1}}%
      }%
    }%
  }%
}%
%================================================================================
%
% \Ackermannsteps{<m>}{<n>}
%
% Prints the single steps of computing the Ackermann-function.
% Delivers all steps after two "hits" by \expandafter
%
%--------------------------------------------------------------------------------
\DeclareMathOperator{\AckermannFunction}{A}%
\newcommand\Ackermannsteps[2]{%
  \begingroup
  \noindent\rlap{$\AckermannFunction(#1, #2)$}\Ackermannstepsloop{#1}{#2}{$\phantom{\AckermannFunction(#1, #2){}}=}{$\\}%
  \endgroup
}%
\newcommand\Ackermannstepsloop[4]{%
  % #1 = m
  % #2 = n
  % #3 = tokens to prepend to the term developped
  % #3 = tokens to append to the term developped
  \CsNameToCsToken{@ifundefined}{Ack(#1)(#2)}{%
    \CsNameToCsToken\edef{Ack(#1)(#2)}{\Ackermannloop{#1}{#2}}%
    \ifnum\bigintcalcCmp{#1}{0}=0 \expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
    {#3\bigintcalcInc{#2}#4}{%
      \ifnum\bigintcalcCmp{#2}{0}=0 \expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
      {%
         #3\AckermannFunction(\bigintcalcDec{#1}, 1)#4%
         \expandafter\expandafter\expandafter\Ackermannstepsloop
         \expandafter\expandafter\expandafter{\bigintcalcDec{#1}}{1}%
      }%
      {%
        #3\AckermannFunction(\bigintcalcDec{#1}, \AckermannFunction(#1, \bigintcalcDec{#2}))#4%
        \expandafter\expandafter\expandafter\UDPassFirstToSecond
        \expandafter\expandafter\expandafter{\bigintcalcDec{#2}}{\Ackermannstepsloop{#1}}%
        {#3\AckermannFunction(\bigintcalcDec{#1}, }{)#4}%
        \expandafter\UDPassFirstToSecond\expandafter{%
          \expanded{%
            \CsNameToCsToken{@ifundefined}{Ack(#1)(\bigintcalcDec{#2})}{%
              \expandafter\expandafter\expandafter\UDPassFirstToSecond
              \expandafter\expandafter\expandafter{\bigintcalcDec{#2}}{\Ackermannloop{#1}}%
            }{%
              \CsNameToCsToken{Ack(#1)(\bigintcalcDec{#2})}%
            }%
          }%
        }{%
          \expandafter\expandafter\expandafter\Ackermannstepsloop
          \expandafter\expandafter\expandafter{\bigintcalcDec{#1}}%
        }%
      }%
      {#3}{#4}%
    }%
  }{%
    #3\CsNameToCsToken{Ack(#1)(#2)}#4%
  }%
}%




\begin{document}

\noindent Testing \verb|\Ackermannsteps|: \bigskip

%\Ackermannsteps{0}{0} \bigskip

\Ackermannsteps{2}{0} \bigskip

%\Ackermannsteps{2}{1} \bigskip

\Ackermannsteps{2}{2} \bigskip

%\Ackermannsteps{2}{3} \bigskip

%\Ackermannsteps{2}{4} \bigskip

%\Ackermannsteps{3}{2} \bigskip

%\Ackermannsteps{3}{1} \bigskip

%\Ackermannsteps{3}{2} \bigskip

%\Ackermannsteps{3}{3} \bigskip

% \Ackermannsteps{3}{4}
% I suppose the above yields something like:
% ! TeX capacity exceeded, sorry [main memory size=5000000].

\end{document}

enter image description here

2
  • thank you so so much for all of this, my only 'question' for you is: could you change it so that everytime it prints one of the step, it aligns it like i showed in the picture? If that is too difficult don't mind it. But seriously thank you so much for this! – Lea Hubert Feb 24 at 13:46
  • 1
    @LeaHubert Now I added doing shortcuts. Seems this is the diabolical exercise of Jason Gross' exercise sheet. I think exercise 1.3 (self-typesetter) is much more diabolic if you take into account that the code of the document might be split over many files or due to using the -jobname-option the name of the main tex file might deviate from \jobname so that relying on \jobname is not sufficient. – Ulrich Diez Feb 25 at 1:31
4

I sugest a \romannumeral-expansion-driven tail-recursive macro which maintains a list of the terms calculated so far and where you can specify arguments which denote the tokens between which each item of the list of the terms calculated so far shall be nested when iteration is done.

\romannumeral-expansion so that you know exactly the amount of \expandafter for obtaining the result which is important for obatining the results of nested calls.

Be warned: This is very slow and \Ackermannsteps{3}{3} will get you a ! TeX capacity exceeded, sorry [main memory size=5000000]-error or the like.

Also this does not take shortcuts by re-using Ackermann-function-values already calculated.

If you want this, look at my other answer.

You could do this expandably, too, but this would imply a lot of list-accumulating and -iterating for detecting if a value is already calcluated. Since with Ackermann one is threatened by memory overflow anyway, there is no need to increase the risk by concocting macro arguments that are supposed to hold long lists of tokens denoting very large numbers under certain circumstances.

\documentclass{article}
\usepackage{amsmath}
\usepackage{bigintcalc}

\newcommand\UDfirstoftwo[2]{#1}%
\newcommand\UDsecondoftwo[2]{#2}%
\newcommand\UDExchange[2]{#2#1}%
\newcommand\UDPassFirstToSecond[2]{#2{#1}}%
\csname @ifdefinable\endcsname\UDstopromannumeral{\chardef\UDstopromannumeral=`\^^00}%


% -------------------------------------------------------------------------------
% Ackermann-function:
%
% A(m,n) :=  if m = 0 : n+1
%            if m > 0 and n = 0: A(m-1, 1)
%            if m > 0 and n > 0: A(m-1, A(m, n-1))
% m non-negative integer 
% n non-negative integer
%--------------------------------------------------------------------------------
%%
%================================================================================
%
% \Ackermann{m}{n}
%
% Delivers the solution after two "hits" by \expandafter
%
%--------------------------------------------------------------------------------
\newcommand\Ackermann{%
  \romannumeral\Ackermannloop
}%
\newcommand\Ackermannloop[2]{%
  \ifnum\bigintcalcCmp{#1}{0}=0 \expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
  {\expandafter\expandafter\expandafter\UDstopromannumeral\bigintcalcInc{#2}}{%
    \ifnum\bigintcalcCmp{#2}{0}=0 \expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
    {%
       \expandafter\expandafter\expandafter\Ackermannloop\expandafter\expandafter\expandafter{\bigintcalcDec{#1}}{1}%
    }%
    {%
       \expandafter\UDPassFirstToSecond\expandafter{%
         \romannumeral
         \expandafter\expandafter\expandafter\UDPassFirstToSecond
         \expandafter\expandafter\expandafter{\bigintcalcDec{#2}}{\Ackermannloop{#1}}}{%
         \expandafter\expandafter\expandafter\Ackermannloop\expandafter\expandafter\expandafter{\bigintcalcDec{#1}}%
      }%
    }%
  }%
}%
%================================================================================
%
% \Ackermannsteps{<m>}{<n>}
%
% Prints the single steps of computing the Ackermann-function.
% Delivers all steps after two "hits" by \expandafter
%
%--------------------------------------------------------------------------------
%
% \Ackermannsteps does: \romannumeral\Ackermannstepsloop{<m>}{<n>}{}{\\&=}{}{tablehead}{tablefoot}{\UDfirstoftwo}
%
% Syntax of \Ackermannstepsloop:
%
% \romannumeral
% \Ackermannstepsloop{<m>}%
%                    {<n>}%
%                    {<list of terms developed so far>}%
%                    {Outermost instance: <tokens to put between list items> 
%                     Nested instances: <tokens to prepend to each list item>}%
%                    {Outermost instance: <more tokens to put between list items>
%                     Nested instances: <tokens to append to each list item>}%
%                    {<tokens to prepend to entire list>}%
%                    {<tokens to append to entire list>}%
%                    {<marker for outermost loop/nested loop: \UDfirstoftwo/UDsecondoftwo>}%
%
% Pseudocode of \Ackermannstepsloop:
%
% If <m> = 0:           ( This case is done by the macro \AckermannstepsCaseA )
%                       Iterate on <list of terms developed so far>{<n>+1}, putting things between
%                       the list items. Deliver the result thereof, wrapped between 
%                       <tokens to prepend to entire list> and 
%                       <tokens to append to entire list>.
%              
% If m > 0 and  n = 0:  ( This is done by the macro \AckermannstepsCaseB )
%                       Call \Ackermannstepsloop with arguments changed as follows:
%                         - <list of terms developed so far> := <list of terms developed so far> + {A(<m>-1, 1)} 
%                         - n := 1
%                         - <m> := <m>-1
%                         The other arguments remain unchanged.
%
% If m > 0 and n > 0:   ( This is done by the macro \AckermannstepsCaseC )
%                       Call \Ackermannstepsloop with arguments changed as follows:
%                         - <list of terms developed so far> :=
%                               <list of terms developed so far> + {A(<m-1>, A(<m>, <n-1>))} +
%                               \romannumeral\Ackermannstepsloop{<m>}{<n-1>}{}{A(<m-1>,}{)}{}{}{\UDsecondoftwo}
%                         - <n> := Ackermann(<m>, <n>-1)
%                         - <m> := <m>-1
%                         The other arguments remain unchanged.
%
\DeclareMathOperator{\AckermannFunction}{A}
\newcommand\Ackermannsteps[2]{%
  \romannumeral\Ackermannstepsloop{#1}{#2}{}{$\\$\phantom{\AckermannFunction(#1, #2){}}=}{}{\noindent$\AckermannFunction(#1, #2)=}{$}{\UDfirstoftwo}%
}%
\newcommand\Ackermannstepsloop[8]{%
  % #1 = <m>
  % #2 = <n>
  % #3 = <list of terms developed so far>
  % #4 = Outermost instance: <tokens to put between list items> Nested instances: <tokens to prepend to each list item>
  % #5 = Outermost instance: <more tokens to put between list items> Nested instances: <tokens to append to each list item>
  % #6 = <tokens to prepend to entire list>
  % #7 = <tokens to append to entire list>
  % #8 = <marker for outermost loop/nested loop: \UDfirstoftwo/UDsecondoftwo>
  \ifnum\bigintcalcCmp{#1}{0}=0 \expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
  {%
    \expandafter\expandafter\expandafter\AckermannstepsCaseA
    \expandafter\expandafter\expandafter{\bigintcalcInc{#2}}{#3}%
  }{%
    \ifnum\bigintcalcCmp{#2}{0}=0 \expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
    {%
      \expandafter\expandafter\expandafter\AckermannstepsCaseB
      \expandafter\expandafter\expandafter{\bigintcalcDec{#1}}{#3}%
    }%
    {%
      \expandafter\expandafter\expandafter\UDPassFirstToSecond
      \expandafter\expandafter\expandafter{\bigintcalcDec{#2}}{%
        \expandafter\expandafter\expandafter\AckermannstepsCaseC
        \expandafter\expandafter\expandafter{\bigintcalcDec{#1}}%
      }{#1}{#3}%
    }%
  }%
  {#4}{#5}{#6}{#7}{#8}%
}%
\newcommand\AckermannstepsCaseA[7]{%
  % #1 = <n>+1
  % #2 = <list of terms developed so far>
  % #3 = Outermost instance: <tokens to put between list items> Nested instances: <tokens to prepend to each list item>
  % #4 = Outermost instance: <more tokens to put between list items> Nested instances: <tokens to append to each list item>
  % #5 = <tokens to prepend to entire list>
  % #6 = <tokens to append to entire list>
  % #7 = <marker for outermost loop/nested loop: \UDfirstoftwo/UDsecondoftwo>
  \expandafter\UDExchange
  \expandafter{%
    \romannumeral#7{\AckermannstepsCaseAOutermostLoop{}{#3#4}}{\AckermannstepsCaseANestedLoop{#3}{#4}}{}#2{#1}\relax
  }{\UDstopromannumeral#5}#6%
}%
\newcommand\AckermannstepsCaseANestedLoop[4]{%
  % #1 = <tokens to prepend to each list item>
  % #2 = <tokens to append to each list item>
  % #3 = <output created so far>
  % #4 = <current item of <list of terms developed so far>> or \relax
  \ifx\relax#4\expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
  {\UDstopromannumeral#3}{%
    \AckermannstepsCaseANestedLoop{#1}{#2}{#3{#2#4#1}}%
  }%
}%
\newcommand\AckermannstepsCaseAOutermostLoop[4]{%
  % #1 = <tokens to prepend in this iteration>
  % #2 = <tokens to prepend in next iteration>
  % #3 = <output created so far>
  % #4 = <current item of <list of terms developed so far>> or \relax
  \ifx\relax#4\expandafter\UDfirstoftwo\else\expandafter\UDsecondoftwo\fi
  {\UDstopromannumeral#3}{%
    \AckermannstepsCaseAOutermostLoop{#2}{#2}{#3#1#4}%
  }%
}%
\newcommand\AckermannstepsCaseB[2]{%
  % #1 = <m>-1
  % #2 = <list of terms developed so far>
  \Ackermannstepsloop{#1}{1}{#2{\AckermannFunction(#1, 1)}}%
}%
\newcommand\AckermannstepsCaseC[4]{%
   % #1 = <m>-1
   % #2 = <n>-1
   % #3 = <m>
   % #4 = <list of terms developed so far>
   \expandafter\UDPassFirstToSecond\expandafter{%
     \romannumeral\expandafter\UDExchange\expandafter{%
       \romannumeral\Ackermannstepsloop{#3}{#2}{}{)}{\AckermannFunction(#1, }{}{}{\UDsecondoftwo}%
     }{\UDstopromannumeral#4{\AckermannFunction(#1, \AckermannFunction(#3, #2))}}%
   }{%
     \expandafter\UDPassFirstToSecond\expandafter{\romannumeral\Ackermannloop{#3}{#2}}{%
        \Ackermannstepsloop{#1}%
     }%
   }%
}%
%================================================================================


\begin{document}

\noindent Testing \verb|\Ackermannsteps|: \bigskip

%\Ackermannsteps{0}{0} \bigskip

\Ackermannsteps{2}{0} \bigskip

%\Ackermannsteps{2}{1} \bigskip

\Ackermannsteps{2}{2} \bigskip

%\Ackermannsteps{2}{3} \bigskip

%\Ackermannsteps{2}{4} \bigskip

%\Ackermannsteps{3}{0} \bigskip

%\Ackermannsteps{3}{1} \bigskip

%\Ackermannsteps{3}{2} \bigskip

% \Ackermannsteps{3}{3}
% I suppose the above yields something like:
% ! TeX capacity exceeded, sorry [main memory size=5000000].


\newpage

\noindent Testing \verb|\Ackermann|: \bigskip

$\AckermannFunction(0, 0)=\Ackermann{0}{0}$

$\AckermannFunction(1, 0)=\Ackermann{1}{0}$

$\AckermannFunction(2, 0)=\Ackermann{2}{0}$

$\AckermannFunction(0, 1)=\Ackermann{0}{1}$

$\AckermannFunction(0, 2)=\Ackermann{0}{2}$

$\AckermannFunction(1, 1)=\Ackermann{1}{1}$

$\AckermannFunction(2, 2)=\Ackermann{2}{2}$

$\AckermannFunction(2, 3)=\Ackermann{2}{3}$

$\AckermannFunction(3, 2)=\Ackermann{3}{2}$

$\AckermannFunction(3, 3)=\Ackermann{3}{3}$

$\AckermannFunction(3, 4)=\Ackermann{3}{4}$

% \Ackermann{4}{2}
% I suppose the above yields something like:
% ! TeX capacity exceeded, sorry [input stack size=5000].


\end{document}

enter image description here

enter image description here

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.