Skip to content

Instantly share code, notes, and snippets.

@zr-tex8r
Created February 6, 2012 17:47
Show Gist options
  • Save zr-tex8r/1753619 to your computer and use it in GitHub Desktop.
Save zr-tex8r/1753619 to your computer and use it in GitHub Desktop.
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