Skip to content

Instantly share code, notes, and snippets.

@gfreivasc
Created July 6, 2018 17:05
Show Gist options
  • Save gfreivasc/7040b06c2585b86b238ceb855a248c2e to your computer and use it in GitHub Desktop.
Save gfreivasc/7040b06c2585b86b238ceb855a248c2e to your computer and use it in GitHub Desktop.
(ns katas.diamond)
(require '[clojure.string :as string]
'[clojure.test :refer [is]])
(defn alphabet-pos [c]
(- (int c) (int \A)))
(defn anagram? [s]
(if (>= 1 (count s))
true
(if (not (= (first s) (last s)))
false
(anagram? (subs s 1 (- (count s) 1))))))
(defn d-line [top cur]
(str
(apply str (repeat (- top (alphabet-pos cur)) " "))
cur
(if (not (= cur \A))
(str
(apply str (repeat (+ -1 (* 2 (alphabet-pos cur))) " "))
cur))
))
(defn diamond [c]
(apply str
(interpose "\n"
(for [l (range (+ 1 (* 2 (alphabet-pos c))))]
(d-line
(alphabet-pos c)
(char (+ (int \A)
(if (> l (alphabet-pos c))
(- (* 2 (alphabet-pos c)) l)
l))
)))
)))
(is
(= "A" (diamond \A))
"A character must contain itself")
(is
(string/includes? (diamond \B) "A")
"A higher character must come with all lower ones")
(is
(string/includes? (diamond \B) "\n")
"Diamonds with more than one letters must be split in lines")
(is
(let [c \C]
(= (* 2 (alphabet-pos c)) (count (re-seq #"\n" (diamond \C)))))
"Number of line breaks must be similar to twice the position of the character")
(is
(not (string/includes? (diamond \B) "C"))
"Multiline diamond must not contain higher character than parameter")
(is
(= 3 (alphabet-pos \D))
"Alphabet position must return correct zero-based value")
(is
(anagram? "ABBCCBBA")
"Anagram must be identified")
(is
(not (anagram? "ABCCC"))
"No false-positives are acceptable")
(is
(anagram? (apply str (map string/trim (map string/trim-newline (string/split-lines (diamond \C))))))
"Diamond char sequence must be an anagram")
(is
(let [d (map string/trim (string/split-lines (diamond \C)))]
(= "A" (first d) (last d)))
"First and last lines of diamond must always be A")
(is
(= "A" (string/trim (d-line 2 \A)))
"Diamond line with A contains only one A")
(is
(= (+ -1 (* 2 (alphabet-pos \C))) (count (re-seq #" " (string/trim (d-line 2 \C)))))
"Inner spacing must be twice the alphabet position minus one")
(is
(= (alphabet-pos \C) (count (re-seq #" " (d-line 2 \A))))
"Outer spacing must match the distance from current character to top one")
(println (diamond \C))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment