Advent of Code 2018, day 2, part 2:
The [two IDs you are looking for] differ by exactly one character at the same position in both strings. For example, given the following IDs:
abcde
fghij
klmno
pqrst
fguij
axcye
wvxyz
The IDs
fghijandfguijdiffer by exactly one character, the third (handu). Those must be the correct IDs.
The code checks a list of strings to find two that match apart from a character at one position. So "abc" and "abz" would match.
I'm very green with Clojure, so feedback about any aspect of this code is appreciated.
(require 'clojure.set)
(def not-empty? (complement empty?))
(def input-lines (line-seq (clojure.java.io/reader "input.in")))
;; Given a string
;; Return a set of similar strings, with an asterisk replacing each character
;; eg "abc" gives #{[\* b c] [a \* c] [a b \*]}
(defn get-match-patterns [id]
(set (map #(assoc (vec id) % \*) (range (count id)))))
((fn [ids seen-patterns]
(when (empty? ids)
(throw (Exception. "Didn't find match")))
(let [[next-id & other-ids] ids
match-patterns (get-match-patterns next-id)
matches (clojure.set/intersection match-patterns seen-patterns)]
(if (not-empty? matches)
(prn (apply str (filter #(not= \* %) (first matches))))
(recur other-ids (apply conj seen-patterns match-patterns))))) input-lines #{})
Sample input:
abcde
fghij
klmno
pqrst
fguij
axcye
wvxyz
Sample output:
fgij