Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
432 PurelyFunctional.tv Newsletter

Atbash Cipher

The Atbash Cipher is simple: replace every letter with its "mirror" in the alphabet. A is replaced by Z. B is replaced by Y. Etc. Write a function to calculate it.

Examples

(atbash "") ;=> ""
(atbash "hello") ;=> "svool"
(atbash "Clojure") ;=> "Xolqfiv"
(atbash "Yo!") ;=> "Bl!"

Please maintain capitalization and non-alphabetic characters.

Thanks to this site for the problem idea, where it is rated Very Hard in Python. The problem has been modified.

Please submit your solutions as comments on this gist.

To subscribe: https://purelyfunctional.tv/newsletter/

@souenzzo

This comment has been minimized.

Copy link

@souenzzo souenzzo commented Jun 28, 2021

(let [mirror-clusters [[\a \z]
                       [\A \Z]
                       [\0 \9]]
      build-map (fn [[start end]]
                  (let [start (int start)
                        end (int end)]
                    (into {} (map (fn [k v]
                                    [(char k)
                                     (char v)])
                               (range start (inc end))
                               (range end (dec start) -1)))))
      mirror-map (reduce merge (map build-map mirror-clusters))
      atbash (fn [s]
               (apply str (replace mirror-map s)))]
  [(atbash "")                                              ;=> ""
   (atbash "hello")                                         ;=> "svool"
   (atbash "Clojure")                                       ;=> "Xolqfiv"
   (atbash "Yo!")])                                         ;=> "Bl!")
  
=> ["" "svool" "Xolqfiv" "Bl!"]
@tylerw

This comment has been minimized.

Copy link

@tylerw tylerw commented Jun 28, 2021

(let [lower (transduce (map char) str "" (range (int \a) (inc (int \z))))
      upper (clojure.string/upper-case lower)
      cmap (into {} (map vector lower (reverse lower)))
      cmap (into cmap (map vector upper (reverse upper)))]
  (defn atbash
    [s]
    (clojure.string/escape s cmap)))

Slight variation:

(let [lower (transduce (map char) str "" (range (int \a) (inc (int \z))))
      upper (clojure.string/upper-case lower)
      cmap (->> (map (juxt identity reverse) [lower upper])
                (into {} (mapcat (partial apply map vector))))]
  (defn atbash
    [s]
    (clojure.string/escape s cmap)))
@mcuervoe

This comment has been minimized.

Copy link

@mcuervoe mcuervoe commented Jun 28, 2021

(defn mirror [c] 
  (cond 
    (<= (int \a) (int c) (int \z)) (char (- (int \z) (- (int c) (int \a))))
    (<= (int \A) (int c) (int \Z)) (char (- (int \Z) (- (int c) (int \A))))
    :else c))
  
(defn atbash [s]
  (apply str (map mirror s)))
@miner

This comment has been minimized.

Copy link

@miner miner commented Jun 28, 2021

(let [uppercase (vec "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
      lowercase (vec "abcdefghijklmnopqrstuvwxyz")
      atb-cipher-map (merge (zipmap uppercase (rseq uppercase))
                            (zipmap lowercase (rseq lowercase)))
      atb-cipher #(atb-cipher-map % %)]

  (defn atbash [s]
    (transduce (map atb-cipher)
               (fn ([] (StringBuilder.))
                   ([sb] (str sb))
                   ([sb ch] (.append ^StringBuilder sb ^Character ch)))
               s)))
@diavoletto76

This comment has been minimized.

Copy link

@diavoletto76 diavoletto76 commented Jun 28, 2021

(defn mirror-x [first last x]
     (char (- (int last) (- (int x) (int first)))))

(defn mirror-char [x]
  (cond (re-matches #"[a-z]" (str x)) (mirror-x \a \z x)
        (re-matches #"[A-Z]" (str x)) (mirror-x \A \Z x)
        :else x))

(defn atbash [xs]
  (->> (map mirror-char xs)
       (clojure.string/join "")))
@stuartstein777

This comment has been minimized.

Copy link

@stuartstein777 stuartstein777 commented Jun 28, 2021

(defn atbash [s]
 (let [alphabet "abcdefghijklmnopqrstuvwxyz"
       alphabet-uc (str/upper-case alphabet)
       cipher (merge (zipmap alphabet (reverse alphabet))
                     (zipmap alphabet-uc (reverse alphabet-uc)))]
   (->> (map (fn [c] (cipher c c)) s)
        (apply str))))
@steffan-westcott

This comment has been minimized.

Copy link

@steffan-westcott steffan-westcott commented Jun 28, 2021

(require '[clojure.string :as str])

(let [alpha "abcdefghijklmnopqrstuvwxyz"
      cipher (apply merge (map #(zipmap % (str/reverse %)) [alpha (str/upper-case alpha)]))]
  (defn atbash [s]
    (str/escape s cipher)))
@mchampine

This comment has been minimized.

Copy link

@mchampine mchampine commented Jun 29, 2021

(defn atbash [s]
  (let [f (fn [b v] [(char (+ b v)) (char (- (+ b 25) v))])
        mf (fn [ff b] (map #(f b %) (range 26)))
        mm (into {} (concat (mf f (int \a)) (mf f (int \A))))]
    (clojure.string/escape s mm)))
@ZaymonFC

This comment has been minimized.

Copy link

@ZaymonFC ZaymonFC commented Jun 29, 2021

(defn atbash [s]
  (let [a-z (map char (range (int \a) (inc (int \z))))
        A-Z (map char (range (int \A) (inc (int \Z))))
        alphabet-keys (concat a-z A-Z)
        alphabet-values (reverse (concat A-Z a-z))
        atbash-mapping (zipmap alphabet-keys alphabet-values)]
    (->> s (map (fn [x] (get atbash-mapping x x))) (apply str)))
@grierson

This comment has been minimized.

Copy link

@grierson grierson commented Jun 29, 2021

(def alphabet "ABCDEFGHIJKLMNOPQRSTUVWXYZ")
(def uppercaseAlphabet (seq alphabet))
(def lowercaseAlphabet (map #(Character/toLowerCase %) alphabet))
(def dictionary
  (merge
    (zipmap uppercaseAlphabet (reverse uppercaseAlphabet))
    (zipmap lowercaseAlphabet (reverse lowercaseAlphabet))))


(defn atbash [s]
  (if (empty? s)
    ""
    (apply str (map #(get dictionary % %) s))))
@jaihindhreddy

This comment has been minimized.

Copy link

@jaihindhreddy jaihindhreddy commented Jun 29, 2021

(require '[clojure.string :as str])

(let [a (int \a), z (int \z), A (int \A), Z (int \Z)
      flip #(let [i (int %)]
             (cond (<= a i z) (char (- z (- i a)))
                   (<= A i Z) (char (- Z (- i A)))
                   :else %))]
  (defn atbash [s]
    (str/escape s flip)))
@sztamas

This comment has been minimized.

Copy link

@sztamas sztamas commented Jun 30, 2021

(defn char-range [from to]
  (map char (range (int from) (inc (int to)))))

(defn mirror-char [char-range]
  (zipmap char-range (reverse char-range)))

(def lowercase-letters (char-range \a \z))

(def uppercase-letters (char-range \A \Z))

(def mirror-letters (merge (mirror-char lowercase-letters) (mirror-char uppercase-letters)))

(defn atbash [s]
  (->> s (map #(get mirror-letters % %)) (apply str)))
@vpetruchok

This comment has been minimized.

Copy link

@vpetruchok vpetruchok commented Jun 30, 2021

(def en-alphabet "abcdefghijklmnopqrstuvwxyz")

(defn atbash-mk-translation-table [alphabet]
  (->> alphabet
       (map-indexed (fn [i el]
                      [el (nth alphabet (- (dec (count alphabet)) i))]))
       (into {})))

(def translation-table
  (merge (atbash-mk-translation-table en-alphabet)
         (atbash-mk-translation-table (clojure.string/upper-case en-alphabet))))

(defn encode [ch]
  (get translation-table ch ch))

(defn atbash [s]
  (if (empty? s)
    ""
    (->> s
         (map encode)
         (clojure.string/join))))
@KubqoA

This comment has been minimized.

Copy link

@KubqoA KubqoA commented Jul 1, 2021

(defn char-range [from to] (map char (range (int from) (+ (int to) 1))))
(defn mirror-part [xs] (zipmap xs (reverse xs)))
(def mirror (merge (mirror-part (char-range \A \Z)) (mirror-part (char-range \a \z))))

(defn atbash [s] (apply str (replace mirror s)))
@alex-gerdom

This comment has been minimized.

Copy link

@alex-gerdom alex-gerdom commented Jul 1, 2021

(defn atbash [s]
   (let [A-Z (map char (range 65  91))
         a-z (map char (range 97 123))
         conversions (merge (zipmap A-Z (reverse A-Z))
                            (zipmap a-z (reverse a-z)))]
     (->> s
          (map #(get conversions % %))
          (clojure.string/join ""))))
  • Edited for off by one error for ascii code point of Z.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment