-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathday14.clj
58 lines (46 loc) · 1.67 KB
/
day14.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
(ns advent-2020-clojure.day14
(:require [clojure.string :as str]))
; State: {:mask "", :memory {"n" v}}
(def empty-mask "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX")
(def empty-state {:mask empty-mask :memory {}})
(defn zero-pad [s]
(let [space-padded (->> s Long/parseLong Long/toBinaryString (format "%36s"))]
(str/replace space-padded \space \0)))
(defn binary-to-long [b]
(Long/parseLong b 2))
(defn mask-value [v mask]
(->> (zero-pad v)
(map (fn [m v] (if (= \X m) v m)) mask)
(apply str)
binary-to-long))
(defn update-mask [state mask]
(assoc state :mask mask))
(defn set-bitmasked-value [state addr v]
(assoc-in state [:memory addr] (mask-value v (:mask state))))
(defn floating-addresses [s]
(if-not (str/index-of s \X)
(list s)
(mapcat #(floating-addresses (str/replace-first s \X %))
[\0 \1])))
(defn masked-addresses [address mask]
(->> (zero-pad address)
(map (fn [m v] (if (= m \0) v m)) mask)
(apply str)
floating-addresses))
(defn set-bitmasked-addresses [state addr v]
(->> (:mask state)
(masked-addresses addr)
(map #(vector % (Integer/parseInt v)))
(update state :memory (partial into))))
(defn process-line [line state mem-command]
(condp re-matches line
#"mask = (\w+)" :>> (fn [[_ mask]] (update-mask state mask))
#"mem\[(\d+)\] = (\d+)" :>> (fn [[_ addr v]] (mem-command state addr v))))
(defn solve [input mem-command]
(->> (str/split-lines input)
(reduce #(process-line %2 %1 mem-command) empty-state)
:memory
vals
(apply +)))
(defn part1 [input] (solve input set-bitmasked-value))
(defn part2 [input] (solve input set-bitmasked-addresses))