Exercism v3 launches on Sept 1st 2021. Learn more! ๐๐๐

# ClashTheBunny'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"
(crypto-square/normalize-ciphertext "Madness, and then illumination."))))
(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)))))``````
``````(use '[leiningen.exec :only (deps)])
(deps '[[org.clojure/math.numeric-tower "0.0.4"]])

(ns crypto-square
(require [clojure.math.numeric-tower :as Math])
(require [clojure.string :as str]))

(defn normalize-plaintext
[text]
(-> text (str/lower-case) (str/replace #"[^a-z0-9]" "")))

(defn square-size
[text]
(-> text
(normalize-plaintext)
(count)
(Math/sqrt)
(Math/ceil)
(int)))

(defn plaintext-segments
[text]
(let [text (normalize-plaintext text)]
(-> text
(#(str/replace %
(re-pattern (str "([a-z0-9]{" (square-size %) "})"))
"\$1 "))
(str/split #" "))))

(defn ciphertext
[text]
(let [segments (plaintext-segments text)
size     (-> text (square-size))]
(->> segments
(#(partition size size (repeat " ") (str/join "" %)))
(apply map vector)
(flatten)
(apply str)
(#(str/replace % #" " "")))))

(defn normalize-ciphertext
[text]
(-> text
(ciphertext)
(#(str/replace % #"([a-z0-9]{5})" "\$1 "))
(str/trim)))``````