Skip to content

Instantly share code, notes, and snippets.

@ericnormand
Created March 8, 2021 20:54
Show Gist options
  • Save ericnormand/d744381a3a625af105245fe5f9ecc942 to your computer and use it in GitHub Desktop.
Save ericnormand/d744381a3a625af105245fe5f9ecc942 to your computer and use it in GitHub Desktop.
417 PurelyFunctional.tv Newsletter

Character swap

Write a function that swaps every occurrence of one string with another, and vice versa. It is like clojure.string.replace but works both ways.

Examples

(swap "abc" "a" "b") ;=> "bac"
(swap "book" "k" "t") ;=> "boot"
(swap "Closure" "j" "s") ;=> "Clojure"
(swap "bee" "b" "e") ;=> "ebb"
(swap "abc" "1" "2") ;=> "abc"

Thanks to this site for the challenge idea where it is considered Hard in JavaScript. The problem has been modified from the original.

Please submit your solutions as comments on this gist.

@tvirolai
Copy link

tvirolai commented Mar 9, 2021

(defn swap [input char1 char2]
  (let [replacements {(first char1) (first char2)
                      (first char2) (first char1)}]
    (->> input
         (map (fn [c]
                (or (replacements c) c)))
         (apply str))))

@damesek
Copy link

damesek commented Mar 9, 2021

Without (Stringbuilder.)

  (defn -swap [input char1 char2]
    (->> (reduce
           (fn [acc vv]
             (let [v (str vv)
                   item (or (and (= char1 v) char2)
                            (and (= char2 v) char1))]
               (conj! acc (or item v))))
           (transient [])
           input)
         persistent!
         (apply str))))

with xform (works, but could be better)

(defn -swap-xform [char1 char2]
  (fn [xf]
    (fn
      ([] (xf))
      ([acc] (xf acc))
      ([acc v]
       (xf acc (or (or (and (= char1 (str v)) char2)
                       (and (= char2 (str v)) char1)) v))))))

(defn rf
  ([] (transient []))
  ([acc] (apply str (persistent! acc)))
  ([acc val] (conj! acc val)))

(transduce (-swap-xform "a" "b") rf "abc")

@just-sultanov
Copy link

(defn swap [s match replacement]
  (let [rules   {match       replacement
                 replacement match}
        replace (fn [x] (get rules x x))]
    (transduce
      (map (comp replace str)) str s)))

@nwjsmith
Copy link

nwjsmith commented Mar 9, 2021

(defn swap
  [s ch1 ch2]
  (->> s
       (map (fn [ch] (condp = (str ch) ch1 ch2 ch2 ch1 ch)))
       (apply str)))

@vmpj
Copy link

vmpj commented Mar 11, 2021

(defn swap [s r1 r2]
  (apply str (map #(get {r1 r2 r2 r1} (str %) %) s)))

@filippocostalli
Copy link

filippocostalli commented Mar 12, 2021

;; much better than my previous one and even faster
(defn swap [s ch1 ch2]
   (->> s
      (map #(cond
              (= (str %) ch1) ch2
              (= (str %) ch2) ch1
              :else %))
      (apply str)))

@tylerw
Copy link

tylerw commented Mar 13, 2021

; provided `a` and `b` are strings of length 1
(defn swap [s a b]
  (clojure.string/escape s {(first a) b (first b) a}))

@burnall
Copy link

burnall commented Mar 14, 2021

(defn swap [s a b]
  (clojure.string/replace s 
                          (re-pattern (str a "|" b))
                          {a b, b a}))

Seems like most (if not all= previous solutions suggest length 1 for a and b, which is not in the original problem statement.

@prairie-guy
Copy link

prairie-guy commented Apr 5, 2021

(require '[clojure.string :as string])
                                                                                                                                                      
(defn swap [s c1 c2]                                                                                                                                  
  (string/replace s (re-pattern (str c1 "|" c2)) {c1 c2, c2 c1}))

@sim-f
Copy link

sim-f commented Apr 11, 2021

Only works on replacements strings with length 1:

(defn swap [string rstr1 rstr2]
  (->> string
       (reduce
        (fn [acc c]
          (cond (= rstr1 (str c)) (conj acc rstr2)
                (= rstr2 (str c)) (conj acc rstr1)
                :else (conj acc c)))
        [])
       (apply str)))

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment