Rotating Letters
Svaqvat gur ybatrfg jbeq jura ebg13'q vf nyfb n jbeq.
Table of Contents
Idea
When viewing Greg Egan's twitter he mentioned words that were the Rot-13 of each other and.
Now I have a much more comprehensive list of words (obtained when looking for long wordlists for XKCD style password generation) so I think I could solve this problem, create new problems, and look at various fun patterns in English words using programming. To do this I will use Clojure.
What Do I Mean By "Rotating Letters"?
When I say "rotating words" I simply mean.
If you are used to modular arithmetic you could imagine it as simply adding 13 to each letter.
A Digression on XOR Ciphers
Another interesting way to do this with actual encryption is the XOR
cipher with a key. The rot-13 system is also in essence XOR
though without any key.
The rot-n
Function
This shifts a word n letter to the right (or left) through modular addition and subtraction.
(defn rot-n "Rotate or shift a word `n` letters." [word shift] (->> word (map (fn [character] (let [lowercase-offset (int \a) char-num (- (int character) lowercase-offset) english-chars (inc (- (int \z) (int \a)))] (char (+ lowercase-offset (mod (+ char-num shift) english-chars)))))) str/join))
English Words
Rot 13
Rot-13 is a classic example of english.
(ns rot-13 (:require [clojure.string :as str])) <<rot-n>> ;; Load the words into a set (let [words (-> "words_alpha.txt" slurp str/lower-case str/split-lines) word-set (set words)] (->> words (filter (fn [word] (let [rot-word (rot-n word 13)] (contains? word-set rot-word)))) (sort #(> (count %1) (count %2)))))
So we get two pairs, for a total four answers, which I will call pair g and pair c. The first was found by Greg Egan, here, while the second was found by me, while running my program.
pair g | pair c |
---|---|
abjurer | chechen |
nowhere | purpura |
This is fun, though not terribly interesting, to try to make it fun I will genralize it.
Generalized Rotation
Rot 13 is a rather elegant because it, as mentioned before, allows you to return to the original value rather quickly. But now we may begin to wonder what we were evaluating there.
What if we allowed for other values like rot-2 or rot-5? What would that look like?
Rot Cycles
26 | 13 | 26/3 | 13/2 | 26/5 | 13/3 | 26/7 | 13/4 | 26/9 | 13/5 | 26/11 | 13/6 |
So we are left rather sadly with this series of patterns.
So what do we get? Well sadly not much. I ran the code below and only two-letter words were found, mostly acronyms and other similar things.
(ns rot-4 (:require [clojure.string :as str])) <<rot-n>> (defn rot-cycle? "Check if there is a rotation cycle. Orig is the original word (used to evaluate the cycle), word is the last word, shift is the rotation applied, and words is a set of all words being evaluated." [shift words orig word] (let [rot-word (rot-n word shift)] (cond (= rot-word orig) true (not (contains? words rot-word)) false :else (rot-cycle? shift words orig rot-word)))) (def word-set (-> "words_alpha.txt" slurp str/lower-case str/split-lines set)) ;; Load the words into a set (let [words (-> "words_alpha.txt" slurp str/lower-case str/split-lines) word-set (set words)] (->> words (filter (fn [word] (rot-cycle? 13 word-set word word))) (sort #(> (count %1) (count %2)))))