Repository: exercism/clojure (clojure)

Issue:
Tests for crypto-square are incorrect
Two of the tests for the `normalize-ciphertext` function of the `crypto-square` exercise are wrong, as they don't account for the padding requirement that is in the README. For example, consider the following test:

```clojure
(deftest cipher-3
  (is (= "msemo aanin dnin ndla etlt shui"
         (crypto-square/normalize-ciphertext "Madness, and then illumination."))))
```

The cipher text that is returned contains chunks of different lengths: `msemo aanin dnin ndla etlt shui`, where the spec says:

> 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.

The [spec](https://github.com/exercism/problem-specifications/blob/main/exercises/crypto-square/description.md)'s example string is `"If man was meant to stay on the ground, god would have given us roots."`, and if I run that using the example implementation, it returns `"imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn sseoau"` instead of `"imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn  sseoau "`

Pull request:
The current implementation did not follow the spec. In this commit, the tests are updated as well as the example implementation.

Closes #372

Patch:
diff --git a/exercises/practice/crypto-square/.meta/src/example.clj b/exercises/practice/crypto-square/.meta/src/example.clj
index 46ca4985e..31379cc13 100644
--- a/exercises/practice/crypto-square/.meta/src/example.clj
+++ b/exercises/practice/crypto-square/.meta/src/example.clj
@@ -1,37 +1,24 @@
-(ns crypto-square)
+(ns crypto-square
+  (:require [clojure.string :as str]))
 
-(defn normalize-plaintext [input]
-  (.toLowerCase (clojure.string/replace input #"[^0-9a-zA-Z]" "")))
+(defn normalize-plaintext [plaintext]
+  (str/lower-case (str/replace plaintext #"[^\w]" "")))
 
-(defn square-size [input]
-  (let [s (Math/sqrt (count input))
-        si (Math/round (Math/floor s))]
-    (if (== 0 (rem s si))
-      si (inc si))))
+(defn square-size [plaintext]
+  (int (Math/ceil (Math/sqrt (count (normalize-plaintext plaintext))))))
 
-(defn plaintext-segments [input]
-  (let [text (normalize-plaintext input)
-        size (square-size text)]
-    (vec (map #(apply str %1)
-              (partition size size nil text)))))
+(defn plaintext-segments [plaintext]
+  (let [normalized-plaintext (normalize-plaintext plaintext)
+        size (square-size normalized-plaintext)]
+    (map #(apply str %) (partition size size nil normalized-plaintext))))
 
-(defn ciphertext [input]
-  (let [segments (plaintext-segments input)
-        size (count (first segments))]
-    (apply str (for [n (range size)
-                     s segments]
-                 (nth s n nil)))))
+(defn- padded-segments [plaintext pad]
+  (let [segments (plaintext-segments plaintext)
+        r (count (first segments))]
+        (map #(concat % (take (- r (count %)) (repeat pad))) segments)))
 
-(defn normalize-ciphertext [input]
-  (let [cipher                  (ciphertext input)
-        cipher-length           (count cipher)
-        square-max              (square-size cipher)
-        square-longest          (int (Math/ceil (/ (count cipher) square-max)))
-        square-shortest         (int (Math/floor (/ (count cipher) square-max)))
-        square-count-long-sides (- cipher-length (* square-max square-shortest))]
-    (apply str (interpose " "
-                          (map #(apply str %1)
-                               (concat (partition square-longest square-longest nil
-                                                  (take (* square-count-long-sides square-longest) cipher))
-                                       (partition square-shortest square-shortest nil
-                                                  (take-last (- cipher-length (* square-count-long-sides square-longest)) cipher))))))))
+(defn ciphertext [plaintext]
+  (apply str (apply mapcat vector (padded-segments plaintext nil))))
+
+(defn normalize-ciphertext [plaintext]
+  (str/join " " (map #(apply str %) (apply map vector (padded-segments plaintext \ )))))


Test patch:
diff --git a/exercises/practice/crypto-square/test/crypto_square_test.clj b/exercises/practice/crypto-square/test/crypto_square_test.clj
index 28cb9af3c..be4b0e0d2 100644
--- a/exercises/practice/crypto-square/test/crypto_square_test.clj
+++ b/exercises/practice/crypto-square/test/crypto_square_test.clj
@@ -28,18 +28,21 @@
   (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-4
+  (is (= "msemo aanin dnin  ndla  etlt  shui "
+         (crypto-square/normalize-ciphertext "Madness, and then illumination."))))
 (deftest cipher-5
   (is (= (str "ageihdsednsh lsagtoonaepe lannswnccair hrditeaetnrh "
-              "ueethdnatoio mbqyewdnotto aouayicdwhod nranatosaef "
-              "bnldrhnhrrb efirersodir irnieecusno nedgnailoat")
+              "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)))))
+(deftest cipher-6
+  (is (= "imtgdvs fearwer mayoogo anouuio ntnnlvt wttddes aohghn  sseoau "
+         (crypto-square/normalize-ciphertext "If man was meant to stay on the ground, god would have given us roots."))))
\ No newline at end of file