Skip to content

Instantly share code, notes, and snippets.

@heyarne
Last active July 6, 2019 07:50
Show Gist options
  • Save heyarne/9371c82e7bd0437dab6b72d15f2c0b5a to your computer and use it in GitHub Desktop.
Save heyarne/9371c82e7bd0437dab6b72d15f2c0b5a to your computer and use it in GitHub Desktop.
Unfinished Clojure puzzle for the purely functional newsletter
user=> (require '[clojure.string :as str])
nil
user=> (def dictionary (->> (slurp "/home/arne/Downloads/purely functional - wordlist.txt")
#_=> (str/split-lines)))
#'user/dictionary
user=> (defn frequency-histogram [phrase]
#_=> (->> (str/split (str/lower-case phrase) #"\s+")
#_=> (map frequencies)
#_=> (apply merge-with +)))
#'user/frequency-histogram
user=> (defn fits-perfectly? [p1 p2]
#_=> (->> (merge-with - (frequency-histogram p1) (frequency-histogram p2))
#_=> (vals)
#_=> (every? zero?)))
#'user/fits-perfectly?
user=> (defn fits-in-phrase? [phrase1 phrase2]
#_=> (let [freq1 (frequency-histogram phrase1)
#_=> freq2 (frequency-histogram phrase2)]
#_=> (every? (fn [[k v]]
#_=> (>= (get freq1 k 0) v)) freq2)))
#'user/fits-in-phrase?
user=> (defn find-anagram
#_=> [phrase]
#_=> (let [dictionary (filter (partial fits-in-phrase? phrase) dictionary)]
#_=> (loop [word (nth dictionary 0)
#_=> candidates dictionary
#_=> anagram []
#_=> found []
#_=> next-start 1]
#_=> (cond
#_=> ;; as long as our list of candidates isn't completely used up...
#_=> (some? word)
#_=> (let [guess (str/join " " (conj anagram word))]
#_=> (cond
#_=> ;; found an anagram :)
#_=> (fits-perfectly? phrase guess)
#_=> (recur (first candidates) dictionary anagram (conj found (conj anagram word))
#_=>
#_=> ;; might still find one
#_=> (fits-in-phrase? phrase guess)
#_=> (recur (first candidates) dictionary (conj anagram word) found next-start)
#_=>
#_=> ;; the current word doesn't fit
#_=> :else
#_=> (recur (first candidates) (rest candidates) anagram found next-start)))
#_=>
#_=> ;; try again from a blank anagram if we weren't sucessful
#_=> (< next-start (count dictionary))
#_=> (recur (nth dictionary next-start) dictionary [] found (inc next-start)))
#_=>
#_=> ;; we did everything we could :)
#_=> :else found))))
#'user/find-anagram
;; TODO: Find all anagrams, not just the first one alphabetically
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment