-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathday23.clj
70 lines (59 loc) · 2.1 KB
/
day23.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
(ns advent-2020-clojure.day23)
(defn init-cups [input]
(let [cup-ids (map #(Integer/parseInt (str %)) input)
data-map (->> (partition 2 1 cup-ids cup-ids)
(map vec)
(into {}))]
{:current (first cup-ids) :cups data-map :size (count cup-ids)}))
(defn next-cup [state id]
(get-in state [:cups id]))
(defn cup-seq
([state] (cup-seq state (:current state)))
([state lookup]
(let [v (next-cup state lookup)]
(lazy-seq (cons v (cup-seq state v))))))
(defn destination-cup [{:keys [current size]} disallowed]
(loop [v (dec current)]
(cond
(zero? v) (recur size)
(disallowed v) (recur (dec v))
:else v)))
(defn next-turn [{:keys [current cups] :as state}]
(let [[pick1 pick2 pick3 next-current] (cup-seq state)
dest (destination-cup state #{pick1 pick2 pick3})
next-dest (next-cup state dest)]
(assoc state :current next-current
:cups (assoc cups current next-current
dest pick1
pick3 next-dest))))
(defn play-game [state turns]
(-> (iterate next-turn state)
(nth turns)))
(defn label [state]
(->> (cup-seq state 1)
(take-while #(not= % 1))
(apply str)))
(defn part1 [input num-turns]
(-> (init-cups input)
(play-game num-turns)
label))
(defn tail [{:keys [current cups]}]
(->> cups
(keep (fn [[k v]]
(when (= current v) k)))
first))
(defn extend-cups [state max-cup]
(let [{:keys [current cups]} state
extension-start (inc (apply max (keys cups)))
extension-end (inc max-cup)
extensions (->> (partition 2 1 [current] (range extension-start extension-end))
(map vec)
(into {(tail state) extension-start}))]
(assoc state :cups (merge cups extensions)
:size max-cup)))
(defn part2 [input max-cup num-turns]
(let [state (-> (init-cups input) (extend-cups max-cup))
answer (play-game state num-turns)]
(->> (cup-seq answer 1)
(take 2)
(apply *))))