Hi everyone, it’s my first interaction with the community.
I’ve done something recently I wanna share and please get me some feedbacks
Thanks
;; encript
;W . . . E . . . C . . . R . . . U . . . O . . .
;. E . R . D . S . O . E . E . R . N . T . N . E
;. . A . . . I . . . V . . . D . . . A . . . C .
; WECRUO ERDSOEERNTNE AIVDAC
;; encript with spaces
;;WRIVDN EEAEDSOEE U TOC CRRAN
;; decript
;;W E C R U O
;;ERDSOEERNTNE
;;A I V D A C
(defn- sanitize
[text]
(-> text
(clojure.string/replace #"[\s]" "_")
(clojure.string/replace #"[^A-Za-z_]" "")))
(defn- unsanitize
[text]
(-> text
(clojure.string/replace #"[^A-Za-z_]" "")
(clojure.string/replace #"[_]" " ")))
(defn- zigzag
[text rails]
(let [initial-data {:rail 0
:direction :up
:fence (vec (repeat rails []))}
update-direction (fn [m r d] (merge m {:direction d
:rail (cond-> r
(= d :up) inc
(= d :down) dec)}))
fence-builder (fn [{:keys [rail direction] :as acc} curr]
(let [top? (= rail (dec rails))
bottom? (= rail 0)
middle? (not (or top? bottom?))]
(cond-> acc
top? (update-direction rail :down)
bottom? (update-direction rail :up)
middle? (update-direction rail direction)
:always (update-in [:fence rail] #(conj % curr)))))]
(reduce fence-builder initial-data text)))
(defn- gen-hash
[{:keys [fence]}]
(apply str (flatten fence)))
(defn encrypt
[text rails]
(-> text
sanitize
(zigzag rails)
gen-hash))
(is (= "WRIVDN_EEAEDSOEE_U_TOC__CRRAN"
(encrypt "WE ARE DISCOVERED. RUN AT ONCE" 3)))
(is (= "W_VR_EEDOE_UTO_RICRDNANEASE_C"
(encrypt "WE ARE DISCOVERED. RUN AT ONCE" 4)))
(defn- build-zigzag
[hash rails]
(loop [fence (:fence (zigzag hash rails))
hash (vec hash)
text []]
(if (empty? fence)
text
(let [size (count (first fence))]
(recur
(next fence)
(vec (drop size hash))
(conj text (subvec hash 0 size)))))))
(defn- fill-zigzag
[fence text rails]
(let [initial-data {:rail 0
:direction :up
:fence fence
:text []}
update-direction (fn [m r d] (merge m {:direction d
:rail (cond-> r
(= d :up) inc
(= d :down) dec)}))
fence-builder (fn [{:keys [rail direction] :as acc} _]
(let [top? (= rail (dec rails))
bottom? (= rail 0)
middle? (not (or top? bottom?))]
(cond-> acc
top? (update-direction rail :down)
bottom? (update-direction rail :up)
middle? (update-direction rail direction)
:always (as-> $
(update $ :text #(conj % (first (get-in $ [:fence rail]))))
(update-in $ [:fence rail] #(next %))))))]
(reduce fence-builder initial-data (range (count text)))))
(defn gen-text
[{:keys [text]}]
(apply str text))
(defn decrypt
[hash rails]
(-> hash
(build-zigzag rails)
(fill-zigzag hash rails)
gen-text
unsanitize))
(is (= "HELLO WORLD AGAIN"
(decrypt "HORANEL_OL_GILWDA" 3)))
(is (= "WE ARE DISCOVERED RUN AT ONCE"
(decrypt "WRIVDN_EEAEDSOEE_U_TOC__CRRAN" 3)))
(is (= "WE ARE DISCOVERED RUN AT ONCE"
(decrypt "W_VR_EEDOE_UTO_RICRDNANEASE_C" 4)))