diff options
Diffstat (limited to '2021/day8')
-rw-r--r-- | 2021/day8/08a.clj | 12 | ||||
-rw-r--r-- | 2021/day8/08b.clj | 69 |
2 files changed, 81 insertions, 0 deletions
diff --git a/2021/day8/08a.clj b/2021/day8/08a.clj new file mode 100644 index 0000000..dc261e5 --- /dev/null +++ b/2021/day8/08a.clj @@ -0,0 +1,12 @@ +(ns day-8) + +(require '[clojure.string :as str]) + +(def input (as-> (slurp "./input") x + (str/split x #"\n") + (map (fn [l] + (map (fn [p] (str/split (str/trim p) #" ")) (str/split l #"\|"))) x))) + +(def onlyOutputs (flatten (map second input))) +(def knownDigits (filter (fn [xs] (contains? (set '(2 4 3 7)) (count xs))) onlyOutputs)) +(println (count knownDigits)) diff --git a/2021/day8/08b.clj b/2021/day8/08b.clj new file mode 100644 index 0000000..067f802 --- /dev/null +++ b/2021/day8/08b.clj @@ -0,0 +1,69 @@ +(ns day-8) + +(require '[clojure.string :as str]) +(require '[clojure.set :as set]) + +(def ALPHABET #{\a \b \c \d \e \f \g}) +(defn decodeWith [signal mapping] + (cond (every? (fn [x] (contains? mapping x)) signal) (set (map (fn [x] (get mapping x)) signal)) + :else false)) + +(def SIGNAL_TO_NUM {#{\a \b \c \e \f \g} 0 + #{\c \f} 1 + #{\a \c \d \e \g} 2 + #{\a \c \d \f \g} 3 + #{\b \c \d \f} 4 + #{\a \b \d \f \g} 5 + #{\a \b \d \e \f \g} 6 + #{\a \c \f} 7 + #{\a \b \c \d \e \f \g} 8 + #{\a \b \c \d \f \g} 9}) + +(defn decodedArrToNum [arr] + (reduce + (map-indexed (fn [idx sig] (* (Math/pow 10 (- (count arr) idx 1)) (SIGNAL_TO_NUM sig))) arr))) + +; characters that haven't been mapped (ie the mapping doesnt specify what they actually should be) +(defn unmappedChars [mapping] + (set/difference ALPHABET (keys mapping))) + +; characters that haven't been used (ie there is no character in the mapping that results in them) +(defn unusedChars [mapping] + (set/difference ALPHABET (vals mapping))) + +(defn validResult [x] + (contains? #{#{\a \b \c \e \f \g} #{\c \f} #{\a \c \d \e \g} #{\a \c \d \f \g} #{\b \c \d \f} #{\a \b \d \f \g} #{\a \b \d \e \f \g}#{\a \c \f} #{\a \b \c \d \e \f \g} #{\a \b \c \d \f \g}} x)) + +(defn tryWith [signals mapping knownValues] + (cond + (not (every? (fn [[in expected]] + (def attemptedDecode (decodeWith in mapping)) + (or (= false attemptedDecode) (= expected attemptedDecode))) + knownValues)) false ; stop considering path if it breaks any known values + (not (every? (fn [in] + (def attemptedDecode (decodeWith in mapping)) + (or (= false attemptedDecode) (validResult attemptedDecode))) + signals)) false ; stop when any of the fully resolved signals are invalid + (every? validResult (map (fn [x] (decodeWith x mapping)) signals)) mapping ; base case - all resolved to valid values + :else (let [tryingToMap (first (unmappedChars mapping))] + (first (filter (comp true? boolean) (for [candidate (unusedChars mapping)] + (do + (tryWith signals (assoc mapping tryingToMap candidate) knownValues)))))))) + +(def KNOWN_VALUES {2 #{\c \f} 4 #{\b \c \d \f} 3 #{\a \c \f} 7 #{\a \b \c \d \e \f \g}}) + +(defn extractKnownValues [signals] + (reduce (fn [m s] (cond (contains? KNOWN_VALUES (count s)) (assoc m s (get KNOWN_VALUES (count s))) + :else m)) {} signals)) + +(def input (as-> (slurp "./input") x + (str/split x #"\n") + (map (fn [l] + (map (fn [p] (map set (str/split (str/trim p) #" "))) (str/split l #"\|"))) x))) + +(def lineMappings (map (fn [l] (let [signals (set (flatten l))] + (tryWith signals {} (extractKnownValues signals)))) input)) +(def decodedOutputs (map (fn [l m] (let [signals (second l)] + (map (fn [x] (decodeWith x m)) signals))) input lineMappings)) +(def outputs (map decodedArrToNum decodedOutputs)) + +(println (reduce + outputs)) |