-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathday_04.clj
executable file
·85 lines (66 loc) · 2.24 KB
/
day_04.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
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
#!/usr/bin/env bb
(require '[clojure.string :as str])
(def input (str/split-lines (slurp "./input/day_04.txt")))
(defn str->int
[s]
(Integer/parseInt s))
(def draw-numbers (map str->int (str/split (first input) #",")))
(def board-input (drop 1 input))
(defn tokenize
[s]
(str/split (str/trim s) #"\s+"))
(def size (count (tokenize (second board-input))))
(def not-empty? (complement empty?))
(defn counter
[size]
(zipmap (take size (range)) (repeat size 0)))
(defn next-board
[board-input]
(let [board (take-while not-empty? board-input)
remains (drop (inc size) board-input)
split-row #(reduce-kv (fn [acc k v] (assoc acc (str->int v) {:col k :row %1})) {} (tokenize %2))]
(list (into {:score {:row (counter size) :col (counter size)}} (map-indexed split-row board)) remains)))
(defn split-boards
[[_ & lines]]
(loop [result []
lines lines]
(if (not-empty? lines)
(let [[board remains] (next-board lines)]
(recur (conj result board) remains))
result)))
(defn update-board
[board n]
(if (contains? board n)
(let [{r :row c :col} (get board n)
update-mark (fn [m] (update m n #(assoc % :mark true)))
update-inc #(update-in %1 [:score %2 %3] inc)
update-score (fn [m] (update-inc (update-inc (update-mark m) :row r) :col c))]
(update-score board))
board))
(defn is-end?
[board]
(let [{r :row c :col} (:score board)
filled? (fn [r] (some #(when (= size %) board) (vals r)))]
(or (filled? r) (filled? c))))
(def is-game?
(complement is-end?))
(defn score
[board x]
(* (reduce-kv (fn [acc k v]
(if (or (contains? v :mark) (= k :score))
acc
(+ acc k))) 0 board)
x))
(defn run-numbers
[numbers board-input]
(loop [numbers numbers
state (split-boards board-input)
scores []]
(if (empty? numbers)
scores
(let [[x & numbers] numbers
state (map #(update-board % x) state)]
(recur numbers (filter is-game? state) (into scores (map #(score % x) (filter is-end? state))))))))
(def board-scores (run-numbers draw-numbers board-input))
(println "sol 1:" (first board-scores))
(println "sol 2:" (last board-scores))