The Tower of Hanoi with graphics, in LaTeX
% | |
% bxhanoi.sty : The "Tower of Hanoi" puzzle shown in graphics | |
% | |
%% package declaration | |
\NeedsTeXFormat{LaTeX2e} | |
\ProvidesPackage{bxhanoi}[2012/02/01] | |
%% variables | |
\newcount\bxhp@step | |
\newcount\bxhp@n@disks | |
\newcount\bxhp@n@rodA | |
\newcount\bxhp@n@rodB | |
\newcount\bxhp@n@rodC | |
\newcount\bxhp@xx | |
\newcount\bxhp@yy | |
%%-------------------------------------- solver logic | |
%% initialization | |
\newcommand*\towerofhanoi[1]{% | |
\bxhp@n@disks=#1\relax | |
\bxhp@init | |
\bxhp@cycle\bxhp@exit | |
} | |
\def\bxhp@init{% | |
\bxhp@step=0 | |
\bxhp@n@rodA=0 \let\bxhp@rodA\@empty | |
\bxhp@n@rodB=0 \let\bxhp@rodB\@empty | |
\bxhp@n@rodC=0 \let\bxhp@rodC\@empty | |
\loop | |
\advance\bxhp@n@rodA 1 | |
\edef\bxhp@rodA{\bxhp@rodA\the\bxhp@n@rodA/}% | |
\ifnum \bxhp@n@rodA<\bxhp@n@disks \repeat | |
\ifodd\bxhp@n@disks | |
\let\bxhp@cycle\bxhp@cycle@@odd | |
\else | |
\let\bxhp@cycle\bxhp@cycle@@even | |
\fi | |
\bxhp@show | |
} | |
\def\bxhp@debug@show{% | |
\typeout{% | |
Step \the\bxhp@step^^J% | |
A(\the\bxhp@n@rodA):\bxhp@rodA^^J% | |
B(\the\bxhp@n@rodB):\bxhp@rodB^^J% | |
C(\the\bxhp@n@rodC):\bxhp@rodC | |
}% | |
} | |
%% one step | |
\def\bxhp@cycle@@odd{% | |
\bxhp@move AC% | |
\bxhp@move AB% | |
\bxhp@move BC% | |
\bxhp@cycle | |
} | |
\def\bxhp@cycle@@even{% | |
\bxhp@move AB% | |
\bxhp@move AC% | |
\bxhp@move BC% | |
\bxhp@cycle | |
} | |
\def\bxhp@move#1#2{% | |
\expandafter\bxhp@move@a | |
\csname bxhp@rod#1\expandafter\endcsname | |
\csname bxhp@rod#2\endcsname{#1}{#2}% | |
} | |
\def\bxhp@move@a#1#2#3#4{% | |
%\bxhp@rodX \bxhp@rodY {X} {Y} | |
\advance\bxhp@step 1 | |
\bxhp@let@top\bxhp@topX#1% | |
\bxhp@let@top\bxhp@topY#2% | |
\ifnum\bxhp@topX<\bxhp@topY | |
\def\bxhp@args{#1#2#3#4\bxhp@topX}% | |
\else | |
\def\bxhp@args{#2#1#4#3\bxhp@topY}% | |
\fi | |
\expandafter\bxhp@move@b\bxhp@args | |
} | |
\def\bxhp@move@b#1#2#3#4#5{% | |
\bxhp@pop#1% | |
\advance\csname bxhp@n@rod#3\endcsname -1 | |
\bxhp@push#2#5% | |
\advance\csname bxhp@n@rod#4\endcsname 1 | |
\bxhp@show | |
\bxhp@check | |
} | |
\def\bxhp@check{% | |
\ifnum\bxhp@n@rodC=\bxhp@n@disks | |
\expandafter\bxhp@finalize | |
\fi | |
} | |
\def\bxhp@finalize#1\bxhp@exit{% | |
% no-op | |
} | |
%%-------------------------------------- stack operation | |
%% \bxhp@let@top\CS{<stack>} | |
\def\bxhp@let@top#1#2{% | |
\expandafter\bxhp@let@top@a#2\maxdimen/\bxhp@end#1% | |
} | |
\def\bxhp@let@top@a#1/#2\bxhp@end#3{% | |
\def#3{#1}% | |
} | |
%% \bxhp@pop{<stack>} | |
\def\bxhp@pop#1{% | |
\expandafter\bxhp@pop@a#1\bxhp@end#1 | |
} | |
\def\bxhp@pop@a#1/#2\bxhp@end#3{% | |
\def#3{#2}% | |
} | |
\def\bxhp@push#1#2{% | |
\edef#1{#2/#1}% | |
} | |
%%-------------------------------------- drawings | |
%% color definitions | |
\definecolor{bxhp@rod}{rgb}{1.0,0.8,0} | |
\definecolor{bxhp@count}{rgb}{0.0,0.4,0} | |
%%<*> \tohstepname | |
% The word for "step". | |
\newcommand\tohstepname{} | |
%%<*> \settohunitlength{<dimen>} | |
% Sets the value of \unitlength used in the puzzle graphics. | |
\newcommand*\settohunitlength[1]{% | |
\def\bxhp@unitlength{#1}% | |
} | |
%% \bxhp@draw@figure | |
\def\bxhp@draw@figure{% | |
\begingroup | |
\bxhp@xx\bxhp@n@disks \multiply\bxhp@xx6 | |
\bxhp@yy\bxhp@n@disks \advance\bxhp@yy2 | |
\setlength\unitlength{\bxhp@unitlength}% | |
\begin{picture}(\bxhp@xx,\bxhp@yy)% | |
\put(0,0){\color{bxhp@rod}% | |
\rule{\bxhp@xx\unitlength}{\unitlength}}% | |
\advance\bxhp@yy-1 | |
\bxhp@xx\bxhp@n@disks \multiply\bxhp@xx2 | |
\multiput(\bxhp@n@disks,1)(\bxhp@xx,0){3}{% | |
\color{bxhp@rod}\kern-.3\unitlength | |
\rule{.6\unitlength}{\bxhp@yy\unitlength}}% | |
\bxhp@put@tower(\bxhp@n@disks,1){A}% | |
\bxhp@xx\bxhp@n@disks \multiply\bxhp@xx3 | |
\bxhp@put@tower(\bxhp@xx,1){B}% | |
\bxhp@xx\bxhp@n@disks \multiply\bxhp@xx5 | |
\bxhp@put@tower(\bxhp@xx,1){C}% | |
\end{picture}% | |
\endgroup | |
} | |
%% \bxhp@show | |
\def\bxhp@show{% | |
\newpage | |
\begingroup | |
\noindent\normalsize | |
\rule[-1em]{0pt}{3em}\color{bxhp@count}% | |
\tohstepname | |
\makebox[7em][r]{\bfseries\itshape\LARGE \the\bxhp@step}% | |
\par\medskip | |
\noindent\normalsize | |
\bxhp@draw@figure | |
\par | |
\endgroup | |
} | |
%% \bxhp@elt@disk{<disk_no>} | |
% Graphics of a disk. | |
\def\bxhp@elt@disk#1{% | |
\@tempdima=.5\p@ | |
\multiply\@tempdima#1\divide\@tempdima\bxhp@n@disks | |
\@tempdimb=.5\p@ \advance\@tempdimb-\@tempdima | |
\edef\bxhp@set@color{\noexpand\color | |
[rgb]{0,\strip@pt\@tempdimb,\strip@pt\@tempdima}}% | |
\@tempdima=1.5\unitlength \@tempdima=#1\@tempdima | |
\edef\bxhp@tempa{\the\@tempdima}% | |
\makebox[\z@]{\bxhp@set@color\rule{\bxhp@tempa}{\unitlength}}% | |
} | |
%% \bxhp@put@tower(x,y){<rod>} | |
% Puts the whole graphics of a tower in a rod. | |
\def\bxhp@put@tower(#1,#2)#3{% | |
\bxhp@xx=#1\relax \bxhp@yy=#2\relax | |
\advance\bxhp@yy\csname bxhp@n@rod#3\endcsname | |
\advance\bxhp@yy-1 | |
\edef\bxhp@args{\csname bxhp@rod#3\endcsname*/}% | |
\expandafter\bxhp@put@tower@a\bxhp@args | |
} | |
\def\bxhp@put@tower@a#1/{% | |
\if*#1\else | |
\bxhp@put@tower@b{#1}% | |
\expandafter\bxhp@put@tower@a | |
\fi | |
} | |
\def\bxhp@put@tower@b#1{% | |
\put(\bxhp@xx,\bxhp@yy){\bxhp@elt@disk{#1}}% | |
\advance\bxhp@yy-1 | |
} | |
%%-------------------------------------- initial settings | |
\renewcommand\tohstepname{Step} | |
\settohunitlength{10pt} | |
%%-------------------------------------- all done | |
%% EOF |
\documentclass[a4paper]{article} | |
\usepackage{color} % required | |
\usepackage{bxhanoi} | |
\begin{document} | |
\settohunitlength{5pt} % unit-length in figures | |
\towerofhanoi{10} % number of disks | |
\end{document} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment