-
Notifications
You must be signed in to change notification settings - Fork 0
/
day22.clj
104 lines (90 loc) · 2.79 KB
/
day22.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
(def src (->> (str/split (slurp "day22.txt") #"\n")
(mapv
(fn[s]
(map #(Integer. %) (drop-last 1 (drop 3 (re-seq #"\d+" s))))))))
(defn viable
[l [a b]]
(let [a (nth l a)
b (nth l b)]
(if (or (= 0 (nth a 0))
(> (nth a 0) (nth b 1))) false
true)))
(defn redraw
[l ylen mx]
(let [[a b] (get l (- mx ylen))
v (+ a b)]
(-> (mapv (fn [[a b]]
(cond
(= 0 a) \z
(> (+ a b) (* v 2)) \#
:else \.)) l)
(assoc (- mx ylen) \g)
)))
(def re-src (redraw src 25 (count src)))
(defn get-nxtpath
[p l ylen mx his]
(let [bs (cond-> []
(>= (- p ylen) 0) (conj (- p ylen))
(< (+ p ylen) mx) (conj (+ p ylen))
(> (mod p ylen) 0) (conj (dec p))
(> (mod (inc p) ylen) 0) (conj (inc p)))]
(->> bs
(filter (complement his))
(filter #(not (#{\g \#} (get l %)))))))
(defn get-path
[l ylen]
(let [mx (count l)
p (.indexOf l \g)]
(loop [his #{p} paths [[p]]]
(let [[his paths] (reduce (fn [[his paths] path]
(let [ps (get-nxtpath (last path) l ylen mx his)
his (into his ps)]
[his (into paths (mapv (partial conj path) ps))]))
[his []] paths)
goals (reduce #(case (last %2) 0 (conj %1 %2) %1) [] paths)]
(if (empty? goals) (recur his paths)
goals)))))
(defn get-minmove
[l ylen mx init target]
(loop [his #{init} ps [init] n 0]
(let [[his ps] (reduce (fn [[his ps] p]
(let [cps (get-nxtpath p l ylen mx his)
ps (into ps cps)
his (into his ps)]
[his ps]))
[his []] ps)]
(cond
(empty? ps) -1
(some #{target} ps) (inc n)
:else (recur his ps (inc n))))))
(defn proc-path
[l ylen mx path]
(loop [l l path path cnt 0]
(if (empty? path) cnt
(let [g (.indexOf l \g)
init (.indexOf l \z)
target (first path)
n (get-minmove l ylen mx init target)]
(recur (-> l
(assoc init \.)
(assoc target \g)
(assoc g \z))
(rest path)
(+ cnt n 1))))))
(defn proc-p1
[l]
(->> (for [a (range (count l))
b (range (count l))
:when (not= a b)]
[a b])
(filter #(viable l %))
count))
(defn proc-p2
[l ylen]
(let [mx (count l)
paths (get-path l ylen)]
(apply min (mapv #(proc-path l ylen mx (rest %)) paths))))
;part1
(proc-p1 src)
;part2
(proc-p2 re-src 25)