# thebearmayor's solution

## to Crypto Square in the Clojure Track

Published at Jul 13 2018 · 0 comments
Instructions
Test suite
Solution

Implement the classic method for composing secret messages called a square code.

Given an English text, output the encoded version of that text.

First, the input is normalized: the spaces and punctuation are removed from the English text and the message is downcased.

Then, the normalized characters are broken into rows. These rows can be regarded as forming a rectangle when printed with intervening newlines.

For example, the sentence

"If man was meant to stay on the ground, god would have given us roots."

is normalized to:

"ifmanwasmeanttostayonthegroundgodwouldhavegivenusroots"

The plaintext should be organized in to a rectangle. The size of the rectangle (r x c) should be decided by the length of the message, such that c >= r and c - r <= 1, where c is the number of columns and r is the number of rows.

Our normalized text is 54 characters long, dictating a rectangle with c = 8 and r = 7:

"ifmanwas"
"meanttos"
"tayonthe"
"groundgo"
"dwouldha"
"vegivenu"
"sroots  "

The coded message is obtained by reading down the columns going left to right.

The message above is coded as:

"imtgdvsfearwermayoogoanouuiontnnlvtwttddesaohghnsseoau"

Output the encoded text in chunks that fill perfect rectangles (r X c), with c chunks of r length, separated by spaces. For phrases that are n characters short of the perfect rectangle, pad each of the last n chunks with a single trailing space.

"imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn  sseoau "

Notice that were we to stack these, we could visually decode the cyphertext back in to the original message:

"imtgdvs"
"fearwer"
"mayoogo"
"anouuio"
"ntnnlvt"
"wttddes"
"aohghn "
"sseoau "

## Source

J Dalbey's Programming Practice problems http://users.csc.calpoly.edu/~jdalbey/103/Projects/ProgrammingPractice.html

## Submitting Incomplete Solutions

It's possible to submit an incomplete solution so you can see how others have completed the exercise.

### crypto_square_test.clj

(ns crypto-square-test
(:require [clojure.test :refer [deftest is]]
crypto-square))

(deftest normalize-splunk
(is (= "splunk" (crypto-square/normalize-plaintext "s#!@\$%plunk"))))
(deftest normalize-with-punctuation
(is (= "123go" (crypto-square/normalize-plaintext "1, 2, 3 GO!"))))

(deftest square-2
(is (= 2 (crypto-square/square-size "1234"))))
(deftest square-3
(is (= 3 (crypto-square/square-size "123456789"))))
(deftest square-4
(is (= 4 (crypto-square/square-size "123456789abc"))))

(deftest segments
(is (= ["neverv", "exthin", "eheart", "withid", "lewoes"]
(crypto-square/plaintext-segments "Never vex thine heart with idle woes."))))
(deftest segments-2
(is (= ["zomg", "zomb", "ies"]
(crypto-square/plaintext-segments "ZOMG! ZOMBIES!!!"))))

(deftest cipher-1
(is (= "tasneyinicdsmiohooelntuillibsuuml"
(crypto-square/ciphertext "Time is an illusion. Lunchtime doubly so."))))
(deftest cipher-2
(is (= "wneiaweoreneawssciliprerlneoidktcms"
(crypto-square/ciphertext "We all know interspecies romance is weird."))))
(deftest cipher-3
(is (= "msemo aanin dnin ndla etlt shui"
(deftest cipher-4
(is (= "vrel aepe mset paoo irpo"
(crypto-square/normalize-ciphertext "Vampires are people too!"))))
(deftest cipher-5
(is (= (str "ageihdsednsh lsagtoonaepe lannswnccair hrditeaetnrh "
"ueethdnatoio mbqyewdnotto aouayicdwhod nranatosaef "
"bnldrhnhrrb efirersodir irnieecusno nedgnailoat")
(let [plaintext (str "All human beings are born free "
"and equal in dignity and rights. "
"They are endowed with reason and conscience "
"and should act towards one another "
"in a spirit of brotherhood.")]
(crypto-square/normalize-ciphertext plaintext)))))
(ns crypto-square
(:require [clojure.math.numeric-tower :as math]))

(defn normalize-plaintext [pt]
(let [normal-chars (set "abcdefghijklmnopqrstuvwxyz0123456789")]
(->> pt
(clojure.string/lower-case)
(filter normal-chars)
(apply str))))

(defn square-size [pt]
(let [normal-pt (normalize-plaintext pt)
length (count normal-pt)
[sqrt rem] (math/exact-integer-sqrt length)
size (if (zero? rem) sqrt (inc sqrt))]
size))

(defn plaintext-segments [pt]
(let [normal-pt (normalize-plaintext pt)
size (square-size pt)
partitions (partition-all size normal-pt)
segments (map (partial apply str) partitions)]
segments))

(defn normalize-ciphertext [pt]
(let [segments (plaintext-segments pt)
size (square-size pt)
pad-segment (fn [seg] (take size (concat seg (repeat nil))))
ct (clojure.string/join " " (map (partial apply str) column-segments))]
ct))

(defn ciphertext [pt]
(let [normalized-ct (normalize-ciphertext pt)
ct (apply str (remove #{\ } normalized-ct))]
ct))