@@ -0,0 +1,359 @@
10+A Caesar cipher is a very simple way to obfuscate a message. The technique
11+takes a string and swaps out each component letter with another letter that is
12+a specified number of positions up or down in the alphabet. For example, with a
13+"right-shift" of 1, `a` would become `b`, `j` would become `k`, and `z` would
14+wrap around back to `a`.
16+Consider the message below, and the cipher that results when we Caesar-shift the
17+message to the right by 1.
20+Plaintext message: "do not give way to anger"
21+Right-shifted cipher: "ep opu hjwf xbz up bohfs"
24+Note that the Caesar cipher is completely unsuitable for actually securing
25+information. Implementing it in a program is just a fun exercise.
27+### A Caesar Cipher In Hoon
29+Below is a generator that performs a Caesar cipher on a tape. This example
30+isn't the most compact implementation of such a cipher in Hoon, but it
31+demonstrates important principles that more laconic code would not. Save it as
32+`caesar.hoon` in your `/gen` directory.
39+ ++ alpha "abcdefghijklmnopqrstuvwxyz"
41+ |= [message=tape key=@ud]
42+ (operate message key (encoder key))
44+ |= [message=tape key=@ud]
45+ (operate message key (decoder key))
47+ |= [message=tape key=@ud encoder=(map @t @t)]
51+ (~(got by encoder) a)
54+ =/ keytape=tape (rott alpha key)
55+ (coder alpha keytape)
58+ =/ keytape=tape (rott alpha key)
59+ (coder keytape alpha)
62+ (~(put by (zipper a b)) ' ' ' ')
67+ ?. =((lent a) (lent b))
68+ ~| %uneven-lengths !!
70+ ?: |(?=(~ a) ?=(~ b))
72+ $(chart (~(put by chart) i.a i.b), a t.a, b t.b)
75+ =/ length=@ud (lent m)
76+ =+ s=(trim (mod n length) m)
79+|= [* [msg=tape key=@ud ~] ~]
82+:- (shift.caesar msg key)
83+(unshift.caesar msg key)
86+This generator takes two arguments: a `tape`, which is your plaintext message,
87+and an unsigned integer, which is the shift-value of the cipher. It produces
88+a cell of two `tapes`: one that has been shifted right by the value, and another
89+that has been shifted left. It also converts any uppercase input into lowercase.
91+Try it out in the Dojo:
114+##### Examining Our Code
116+Let's examine our `caesar.hoon` code piece by piece. We won't necessarily go
117+in written order; instead, we'll cover code in the intuitive order of the
118+program. For each chunk that we cover, try to read and understand the code
119+itself before reading the explanation.
128+The `!:` in the first line of the above code enables a full stack trace in the
131+`:- %say` begins to construct a cell with `%say` as the head, and the code that
132+follows as the tail. This causes the Arvo to interpret the file as a
133+[`%say` generator](/docs/tutorials/generators).
135+`=+` adds a noun the subject, `=^ caesar` names that noun, and `|%` is used
136+to create a core that contains the following arms. This results in having a core
137+with the face `caesar` that we can call.
139+Now let's look at the rest of the program that is outside of our core:
142+|= [* [msg=tape key=@ud ~] ~]
145+:- (shift.caesar msg key)
146+(unshift.caesar msg key)
149+The top line creates a gate with `|=`. The sample of that gate follows the
150+scheme used by `%say` generators: it's a 3-tuple whose parts allow for different
151+kinds of data. We only need non-optional arguments, though, so we only fill in
152+the second part. There we take a `msg` argument and a `key` argument. We use a
153+`*` and a `~` in the first part (Arvo data) and third part (optional arguments),
154+respectively, because we aren't using them here. See the
155+[generator documentation](/docs/tutorials/generators) for more information.
157+`:- %noun` simply labels the output of this program as the `%noun` mark.
159+`=. msg (cass msg)` changes the input string `msg` to lowercases. `=.` changes
160+the leg of the subject to something else. In our case, the leg to be changed is
161+`msg`, and the thing to replace it is `(cass msg)`. `cass` is a standard-library
162+gate that converts uppercase letters to lowercase.
164+`:- (shift.caesar msg key)` and `(unshift.caesar msg key)` simply composes a
165+cell of a right-shifted cipher and a left-shifted cell. This is the final output
171+ =/ length=@ud (lent m)
172+ =+ s=(trim (mod n length) m)
176+The `rott` arm takes takes a specified number of characters off of a tape and
177+puts them on the end of the tape.
179+`|= [m=tape n=@ud]` creates a gate that takes two arguments: `m`, a `tape`,
182+`=/ length=@ud (lent m)` stores the length of `m` to make the following
183+code a little clearer.
185+`trim` is a a gate from the standard library that splits a tape at into two
186+parts at a specified position. So `=+ s=(trim (mod n length) m)` splits the
187+tape `m` into two parts, `p` and `q`, and stores it in `s`. We call the modulus
188+operation `mod` to make sure that we split our `tape` at the correct place, even
189+if `n` is larger than `length`.
191+`(weld q.s p.s)` uses `weld`, which combines two strings into one. In this
192+instance, we are switching the two parts: the second part `q.s` is welded to the
193+front, and the first part `p.s` is welded to the back.
199+ =| chart=(map @t @t)
200+ ?. =((lent a) (lent b))
201+ ~| %uneven-lengths !!
203+ ?: |(?=(~ a) ?=(~ b))
205+ $(chart (~(put by chart) i.a i.b), a t.a, b t.b)
208+The `zipper` arm takes two tapes and creates a `map` out of them -- an
209+an association between their elements.
211+So then if `tapes` are easier to manipulate, why then are we producing `cords`?
212+In this case what we are going to to be doing is mapping a single element of a `
213+tape` to another element of a `tape`, which as we have established as being a
214+`cord`. This will simplify our use of this method and we don't need to
215+manipulate the keys or values, simply look them up.
217+`|= [a=tape b=tape]` builds a gate that takes two tapes, `a` and `b`, as its
220+`^- (map @t @t)` casts the gate to a `map` with a `cord` key and a `cord`
221+value. A `map` is a type equivalent to a dictionary in other languages: it's a
222+data structure that associates a key with a value. If, for example, we wanted
223+to have an association between `a` and 1 and `b` and 2, we could use a `map`.
225+`=| chart=(map @t @t)` adds a noun to the subject with the default value of
226+the `(map @t @t)` type, and gives that noun the face `chart`.
228+`?. =((lent a) (lent b))` checks if the two tapes are the same length. If not,
231+`|-` creates a trap, a gate that is called immediately.
233+`?: |(?=(~ a) ?=(~ b))` checks if either tape is empty. If this is true, we
234+the program is finished and can return `chart`, the the `map` that we have been
237+If the above test finds that its condition to be false, we trigger a recursion
238+that constructs our `map`: $(chart (~(put by chart) i.a i.b), a t.a, b t.b)`.
239+This code recursively adds an entry in our `map` where the head of the tape `a`
240+maps to the value of the head of tape `b` with `~(put by chart)`, our calling
241+of the `put` arm of the `by` map-engien core. The recursion also "consumes"
242+those heads with every iteration by changing `a` and `b` to their tails.
244+Perhaps now you can understand why this arm is named `zipper`. It's putting two
245+tapes together by matching pieces from each side, something akin to a jacket zipper.
247+We have three related arms to look at next, `coder`, `encoder`, and
248+`decoder`. `coder` is the foundation of the other two, so we'll look at it
254+ (~(put by (zipper a b)) ' ' ' ')
257+`|= [a=tape b=tape]` creates a gate that takes two `tapes`.
259+We use `put by` on the next line, giving it a `map` produced by the `zipper`
260+arm that we created before. This adds an entry to the map where the space
261+character (called `ace`) simply maps to itself. This is done to simplify
262+the handling of spaces in `tapes` we want to encode, since we don't want to
268+ =/ keytape=tape (rott alpha key)
269+ (coder alpha keytape)
272+ =/ keytape=tape (rott alpha key)
273+ (coder keytape alpha)
276+`encoder` and `decoder` are implemented in terms of the `coder` arm. These gates
277+are essentially identical, with the arguments reversed. They simplify the two
278+common transactions you want to do in this program: producing `maps` that we can
279+use to encode and decode messages.
281+In both cases, we create a gate that accepts a `@ud` named `key`.
283+`=/ keytape=tape (rott alpha key)` creates a `keytape` noun by calling `rott`
284+on `alpha` our `key` input. `alpha` is our arm which contains a `tape` of the
287+`(coder alpha keytape)`, for `encoder`, and `(coder keytape alpha)`, for
288+`decoder`, produce a `map` that has the first argument as the keys and the
289+second as the values.
291+If our two inputs to `coder` were `"abcdefghijklmnopqrstuvwxyz"` and
292+`"bcdefghijklmnopqrstuvwxyza"` We would get a `map` where `'a'` maps to `'b'`,
293+`'b'` to `'c'` and so on. By doing this we can produce a `map` that gives us a
294+translation between the alphabet and our shifted alphabet, or vice versa.
296+Still with us? Good. We are finally about to use all the stuff that we've
301+ |= [message=tape key=@ud]
302+ (operate message key (encoder key))
304+ |= [message=tape key=@ud]
305+ (operate message key (decoder key))
308+Both `shift` and `unshift` take two arguments: our `message`, the `tape` that we
309+want to manipulate; and our `key`, the value that we want to shift our message
312+`shift` is for encoding, and `unshift` is for decoding. Thus, `shift` calls the
313+`operate` arm with `(operate message key (encoder key))`, and `unshift` makes
314+that call with `(operate message key (decoder key))`. These both produce the
315+final output of the core, to be called in the form of `(shift.caesar msg key)`
316+and `(unshift.caesar msg key)` at the bottom of the program.
320+ |= [message=tape key=@ud encoder=(map @t @t)]
324+ (~(got by encoder) a)
327+`operate` produces a `tape`. The `%+` rune allows us to pull an arm
328+with a pair sample. The arm we are going to pull is `turn`. This arm
329+takes two arguments, a `list` and a `gate` to apply to each element of the
332+If we then give our arm Caesar's famous statement, and get our left- and
336+> +caesar "i came i saw i conquered" 4
337+["m geqi m wea m gsruyivih" "e ywia e ows e ykjmqanaz"]
340+Now, to decode, we can put either of our ciphers in with the appropriate key and
341+look for the legible result.
344+> +caesar "m geqi m wea m gsruyivih" 4
345+["q kium q aie q kwvycmzml" "i came i saw i conquered"]
347+> +caesar "e ywia e ows e ykjmqanaz" 4
348+["i came i saw i conquered" "a usew a kso a ugfimwjwv"]
354+1. Take the example generator and modify it to add a second layer of shifts.
356+2. Extend the example generator to allow for using characters other than a-z.
358+3. Build a gate that can take a Caesar shifted `tape` and produce
359+possible unshifted `tapes`.