-
Notifications
You must be signed in to change notification settings - Fork 0
/
day08.clj
107 lines (83 loc) · 2.37 KB
/
day08.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
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
(ns advent.day08
(:require [advent.core :as c]
[clojure.java.io :as io]
[clojure.pprint :as pp]
[clojure.set :as set]
[clojure.string :as str]))
(defn parse-instruction [[i v]]
[(keyword i)
(Integer/parseInt v)])
(defn read-input [file]
(->> file
(c/read-lines)
(map #(str/split % #" "))
(map parse-instruction)))
(defn visited? [lst val]
(some #{val} lst))
(defn move-next [program idx acc]
(let [[instruction val] (nth program idx)]
(case instruction
:nop [(inc idx) acc]
:jmp [(+ idx val) acc]
:acc [(inc idx) (+ acc val)])))
(defn run [program]
(loop [[idx acc] [0 0]
visited []]
(if (visited? visited idx)
acc
(recur (move-next program idx acc) (conj visited idx)))))
(defn part1 [file]
(run (read-input file)))
;; ----------------------------------------------------------------------------------------------------
;; change one jmp to nop, or one nop to jmp to fix the program
;; valid run is when the idx goes past the last instruction
;; try every combination of the program where nop/jmp is swapped
(comment
([:nop 0]
[:acc 1]
[:jmp 4]
[:acc 3]
[:jmp -3]
[:acc -99]
[:acc 1]
[:jmp -4]
[:acc 6])
)
(defn get [program idx]
(nth program idx))
(defn set [program idx val]
(assoc program idx val))
(defn swap [[a b]]
(if (= :nop a)
[:jmp b]
[:nop b]))
(defn build-version [program idx]
(set program idx (swap (get program idx))))
(defn nopjmp? [program idx]
(let [[a b] (get program idx)]
(or (= :nop a) (= :jmp a))))
(defn get-indexes [program]
(let [cnt (count program)]
(loop [idx 0
acc []]
(if (>= idx cnt)
acc
(recur (inc idx)
(if (nopjmp? program idx) (conj acc idx) acc))))))
(defn build-alternative-programs [program]
(map #(build-version program %) (get-indexes program)))
(defn run2
"Exit when the program runs past the last instruction."
[program]
(let [cnt (count program)]
(loop [[idx acc] [0 0]
visited []]
(if (visited? visited idx)
nil
(if (>= idx cnt)
acc
(recur (move-next program idx acc) (conj visited idx)))))))
(defn part2 [file]
(let [p (vec (read-input file))
programs (build-alternative-programs p)]
(first (filter #(not (nil? %)) (map run2 programs)))))