# How to create a Caesar's encryption disk using LaTeX

How can I create a Caesar's encryption disk with LaTeX?

I guess, the ultimate solution would take a arbitrary list of letters and calculate the spaces and angles for each letter automatically. So if I pass 4 letters to it, each space should have 90 degrees.

-
This looks like fun. Can we add that to the tag? – hpesoj626 Mar 20 '13 at 5:51
Done, added 'fun' :-) – Uwe Ziegenhagen Mar 20 '13 at 6:04
What have you tried so far? MWE? Do you want to give a list of letters? The number of letters? What should happen when the number is greater than 26? – Qrrbrbirlbel Mar 20 '13 at 6:10
I have no idea how to tackle this problem, so there is no MWE yet. I could imagine it as the following: \ceasar[circleouterwidth=5cm]{a,b,c,d,e,f,g}{a,b,c,d,e,f,g} with character for the inner and the outer circle. Giving two separate lists could allow to use math symbols as well or Greek characters. There should not be a problem if there are more than 26 chars. – Uwe Ziegenhagen Mar 20 '13 at 6:27
Next challenge - build an Enigma machine in TeX? en.wikipedia.org/wiki/Enigma_machine – Ethan Bolker Mar 20 '13 at 12:52

## 4 Answers

### Commands

• \drawCaesarsDisk that works with a number of letters (only A to Z)
• \drawCaesarsList that works with one list for both rings or two different lists

### Keys

• inner radius/middle radius/outer radius
• Improvements: Specify inner radius and add inner height and outer height respectively to calculate the actual radii.
• Improvements: With these heights, scale the letters so that they fit right into one ring segment.
• number of letters (only \drawCaesarsDisk)
• inner letters and outer letters (only \drawCaesarsList): If only inner letters is specified the letters in the outer ring will be the same as in the inner ring.
• shift

### Parameters (both commands)

• First (optional): Key=Values for the disk.
• Second (mandatory): where the Disk is placed.

### Improvement:

• Radii/font-size calculation (see above)
• Starting with the first letter at the north position or right of it (possible style)
• Adding styles for circles, separators, letters, etc.
• Bug: The List command breaks with

! Dimension too large. <recently read> \pgfmath@x


when 46 or more letters are specified.

• I forgot something …

## Code

\documentclass[tikz]{standalone}
\usetikzlibrary{backgrounds}
\makeatletter
\tikzset{
/caesar/.cd,
inner radius/.store in=\qrr@caesar@innerR,
middle radius/.store in=\qrr@caesar@middleR,
outer radius/.store in=\qrr@caesar@outerR,
inner letters/.store in=\qrr@caesar@innerL,
outer letters/.store in=\qrr@caesar@outerL,
number of letters/.code=\pgfmathtruncatemacro\qrr@caesar@number{#1},
shift/.store in=\qrr@caesar@shift,
% defaults:
outer letters=,
shift=0
}
\newcommand*{\drawCaesarsDisk}[2][]{%
\begingroup
\pgfqkeys{/caesar}{#1}%
\foreach \radius in {\qrr@caesar@innerR,\qrr@caesar@middleR,\qrr@caesar@outerR}
\draw (#2) circle [radius=\radius];
\foreach \step in {0,...,\numexpr\qrr@caesar@number-1}{
\draw[shift={(#2)}] (\step*360/\qrr@caesar@number:\qrr@caesar@innerR) -- (\step*360/\qrr@caesar@number:\qrr@caesar@outerR);
\node[shift={(#2)},rotate=(\step+.5)*360/\qrr@caesar@number-90] at ({(\step+.5)*360/\qrr@caesar@number}:{.5*(\qrr@caesar@innerR)+.5*(\qrr@caesar@middleR)} ) {\@Alph{\numexpr26-\step}};
\pgfmathtruncatemacro\pgf@temp{mod(\step+\qrr@caesar@shift,\qrr@caesar@number)}%
\node[shift={(#2)},rotate=(\step+.5)*360/\qrr@caesar@number-90] at ({(\step+.5)*360/\qrr@caesar@number}:{.5*(\qrr@caesar@outerR)+.5*(\qrr@caesar@middleR)} ) {\@Alph{\numexpr26-\pgf@temp}};
}
\endgroup
}
\newcount\qrr@caesar@c
\newcommand*{\drawCaesarsList}[2][]{%
\begingroup
\pgfqkeys{/caesar}{#1}%
\foreach \radius in {\qrr@caesar@innerR,\qrr@caesar@middleR,\qrr@caesar@outerR}
\draw (#2) circle [radius=\radius];
\qrr@caesar@c=0\relax
\foreach \element in \qrr@caesar@innerL {\global\advance\qrr@caesar@c1}
\ifx\pgfutil@empty\qrr@caesar@outerL
\let\qrr@caesar@outerL\qrr@caesar@innerL
\fi
\edef\qrr@caesar@number{\number\qrr@caesar@c}%
\foreach \innerLetter[count=\step from 0] in \qrr@caesar@innerL {
\draw[shift={(#2)}] (\step*360/\qrr@caesar@number:\qrr@caesar@innerR) -- (\step*360/\qrr@caesar@number:\qrr@caesar@outerR);
\node[shift={(#2)},rotate=-(\step+.5)*360/\qrr@caesar@number-90] at ({-(\step+.5)*360/\qrr@caesar@number}:{.5*(\qrr@caesar@innerR)+.5*(\qrr@caesar@middleR)} ) {\innerLetter};
}
\foreach \outerLetter[count=\step@ from 0] in \qrr@caesar@outerL {
\ifnum\step@=\qrr@caesar@number\breakforeach\fi
\pgfmathtruncatemacro\step{mod(\step@+\qrr@caesar@shift,\qrr@caesar@number)}%
\node[shift={(#2)},rotate=-(\step+.5)*360/\qrr@caesar@number-90] at ({-(\step+.5)*360/\qrr@caesar@number}:{.5*(\qrr@caesar@outerR)+.5*(\qrr@caesar@middleR)} ) {\outerLetter};
}
\endgroup
}
\makeatother
\begin{document}
\begin{tikzpicture}
\drawCaesarsDisk[
inner radius=2cm,
middle radius=2cm+1.3em,
outer radius=2cm+3em,
number of letters=26,
shift=13,
]{0,0}
\end{tikzpicture}

\begin{tikzpicture}
\drawCaesarsList[
inner radius=.5cm,
middle radius=.5cm+1.3em,
outer radius=.5cm+3em,
inner letters={a,b,c,d,e,f,g},
outer letters={A,B,C,D,E,F,G}
]{2,0}
\end{tikzpicture}

\begin{tikzpicture}
\drawCaesarsList[
inner radius=2cm,
middle radius=2cm+1.3em,
outer radius=2cm+3em,
inner letters={a,...,z,A,B,...,T},%,U,V,W,X,Y,Z},
shift=26,
]{0,0}
\end{tikzpicture}
\end{document}


## Output

-
Wow! However I get an error: "! Package tikz Error: A node must have a (possibly empty) label text. ... l.58 ]{0,0} – Uwe Ziegenhagen Mar 20 '13 at 7:17
@UweZiegenhagen I have added some explanation since you made your comment. I also updated the solution to work with the 2.10 version of TikZ. The problem was a parsing error that was already discussed in other questions. And to clarify: Yes, you can give two (possibly different) lists and you can specify a shift. – Qrrbrbirlbel Mar 20 '13 at 7:35
You are awesome! :-) – Uwe Ziegenhagen Mar 20 '13 at 7:47
An alternative way of getting the length of a \foreach list is: \foreach \x [count=\c from 1, remember=\c] in {A,...,Z}{}. Then \c holds the length of the list. – Mark Wibrow Mar 20 '13 at 11:50

Here is what I've done so far:

\documentclass{standalone}
\usepackage{tikz}
\begin{document}
\begin{tikzpicture}
\pgfmathsetmacro{\alphsize}{26}

\pgfmathsetmacro{\ang}{360/\alphsize}
\pgfmathsetmacro{\d}{10}
\pgfmathsetmacro{\op}{98 + \ang/2 - 1.2}
\pgfmathsetmacro{\e}{\ang + \ang*\d}
\pgfmathsetmacro{\ep}{\op + \ang*\d}

\foreach \x in {0,\ang,...,360} {
\draw[gray] (\x:8em) -- (\x:12em);
}

\foreach \x [count=\xi] in {A,...,Z} {
\node[rotate=\ang - \ang*\xi] at (\op - \ang*\xi:11em) {\Large\x};
\node[rotate=\e - \ang*\xi] at (\ep - \ang*\xi:9em) {\Large\x};
}

\draw[thick] (0cm,0cm) circle(12em);
\draw[gray] (0cm,0cm) circle(10em);
\draw[thick] (0cm,0cm) circle(8em);
\end{tikzpicture}
\end{document}


-

Here:

\documentclass{article}
\usepackage{tikz}
\usepackage{ifthen}

\newcounter{encrypted}
\newcounter{original}

\newcommand{\increase}[1]{%command to increase a counter by 1 modulo 26
\ifthenelse{\arabic{#1}<26}{\addtocounter{#1}{1}}{\setcounter{#1}{1}}
}

\begin{document}

\setcounter{encrypted}{7}
\setcounter{original}{1}
\begin{tikzpicture}[scale=0.5]
\draw(0,0)circle(5)circle(7)circle(9);
\foreach \x in {1,2,...,26}
{
\draw(\x*360/26:5)--(\x*360/26:9);
\node at (\x*360/26+360/26+180/26:6){\Alph{encrypted}};
\node at (\x*360/26+360/26+180/26:8){\Alph{original}};
\increase{encrypted}
\increase{original}
}
\end{tikzpicture}

\end{document}


-
This looks really promising. Is there an easy way to take just a list of characters instead of hard-coding the 26 letters? – Uwe Ziegenhagen Mar 20 '13 at 6:33
@Toscho I have added the picture for you. I hope you don't mind. :-) – hpesoj626 Mar 20 '13 at 9:10

Just 4 fun with PSTricks.

\documentclass[pstricks,border=12pt]{standalone}
\SpecialCoor
\makeatletter
\def\N{26}

\begin{document}
% speficy the angular distance between the 2 sets of alphabets
\def\offset{13}
\begin{pspicture}(-5,-5)(5,5)
\psforeach{\r} {2,3,4}{\pscircle{\r}}
\degrees[\N]
\psforeach{\t}{65,66,..,90}{%
\psline(2;\the\psLoopIndex)(4;\the\psLoopIndex)
\pstVerb{/angle {\the\psLoopIndex\space 0.5 add} bind def}%
\rput{!angle 6.5 sub}(!3.5 angle \pst@angleunit PtoC){\char\t\relax}
\rput{!angle \offset\space add 6.5 sub}(!2.5 angle \offset\space add \pst@angleunit PtoC){\char\t\relax}
}
\end{pspicture}
\end{document}


## Animated version

To be funner!

\documentclass[pstricks,border=12pt]{standalone}
\usepackage{multido}
\SpecialCoor
\makeatletter
\def\N{26}

\begin{document}
\multido{\i=0+1}{\N}{%
% speficy the angular distance between the 2 sets of alphabets
\def\offset{\i}
\begin{pspicture}(-5,-5)(5,5)
\psforeach{\r} {2,3,4}{\pscircle{\r}}
\degrees[\N]
\psforeach{\t}{65,66,..,90}{%
\psline(2;\the\psLoopIndex)(4;\the\psLoopIndex)
\pstVerb{/angle {\the\psLoopIndex\space 0.5 add} bind def}%
\rput{!angle 6.5 sub}(!3.5 angle \pst@angleunit PtoC){\char\t\relax}
\rput{!angle \offset\space add 6.5 sub}(!2.5 angle \offset\space add \pst@angleunit PtoC){\char\t\relax}
}
\end{pspicture}}
\end{document}


## Warning

If we invoke \degrees[<value other than 360>] previously, conversion with \pst@angleunit is needed for representing points in RPN notation but it is NOT need for representing rotation angle. See the following code snippet.

\rput{!angle 6.5 sub}(!3.5 angle \pst@angleunit PtoC){\t}


It is funny? Don't ask me! I just knew this feature several minutes ago!

One more feature, unlike \foreach \t in {A,...,Z}{} that produces a correct result, \psforeach{\t}{A,..,Z}{} produces a weird output!

-