(ns advent-of-code-2021.day8
(:require [clojure.java.io :as io]
[clojure.string :as str])
;; part 1 and part 2
(let [parse-values (fn [values]
(->> values
str/trim
(#(str/split % #"\s+"))
seq
(mapv (fn [v]
(->> v
seq
(map (comp keyword str))
((partial into #{})))))))
;; input is a mapping from signals (set of sets) to outputs (vector of sets).
;; For entries with the same set of signals the four outputs are appended.
input (->> "day-8/input.txt"
io/resource
slurp
str/split-lines
(map #(str/split % #"[|]"))
(reduce (fn [m [signals-str output-str]]
#_(assoc m signals-str output-str)
(let [signals (into #{} (parse-values signals-str))
output (parse-values output-str)]
(update m signals (fn [v]
(if v
(into v output)
output))))) {}))
;; Frequencies
;; 8 6 8 7 4 9 7 ;; Digit IDs
digits {0 #{:a :b :c :e :f :g} ;; 8+6+8+4+9+7 = 42
1 #{ :c :f } ;; 8+9 = 17
2 #{:a :c :d :e :g} ;; 8+8+7+4+7 = 34
3 #{:a :c :d :f :g} ;; 8+8+7+9+7 = 39
4 #{ :b :c :d :f } ;; ...
5 #{:a :b :d :f :g}
6 #{:a :b :d :e :f :g}
7 #{:a :c :f }
8 #{:a :b :c :d :e :f :g}
9 #{:a :b :c :d :f :g}}
calc-segment-frequencies (fn [signals]
(frequencies (mapcat identity signals)))
digit-id (fn [signal segment-frequencies]
(apply + (map segment-frequencies signal)))
digit-id-to-digit (let [segment-frequencies (calc-segment-frequencies (vals digits))]
(into {} (map (juxt #(digit-id (val %) segment-frequencies) key) digits)))
count-unique-outputs (count (mapcat (fn [entry]
(filter (fn [v]
(#{2 3 7 4} (count v))) (val entry))) input))
output-to-sums (fn [output]
(->> output
(partition 4)
(map (fn [nums]
(reduce (fn [s d]
(+ (* s 10) d)) 0 nums)))))
sum-of-decoded-entry-outputs (->> input
(reduce-kv (fn [r signals output]
(let [segment-frequencies (calc-segment-frequencies signals)]
(into r (->> output
(map (fn [signal] (-> signal
(digit-id segment-frequencies)
digit-id-to-digit)))
output-to-sums))))
[])
(apply +))]
{:part-1 count-unique-outputs
:part-2 sum-of-decoded-entry-outputs})