Factor out A* implementation
[adventofcode2019.git] / src / adventofcode2019 / day18.clj
CommitLineData
7a710645
JK
1(ns adventofcode2019.day18
2 [:require [adventofcode2019.lib :refer :all]
3 [adventofcode2019.intcode :as i]
4 [clojure.string :as str]
5 [clojure.set :as set]
6 [clojure.core.match :refer [match]]
fa02619e 7 [clojure.math.combinatorics :as combo]])
7a710645
JK
8
9(defn build-world [input]
10 (let [point-encode (->> input
11 (map-indexed
12 (fn [y xs]
13 (map-indexed
14 (fn [x c]
15 [c [x y]]) xs)))
16 (apply concat))
17 passages (->> point-encode
18 (filter #(= \. (first %)))
19 (map second)
20 (set))
21 interesting (->> point-encode
22 (filter #(and (not= \. (first %))
23 (not= \# (first %))))
24 (into {}))
25 dkeys (select-keys interesting (filter #(Character/isLowerCase %)
26 (keys interesting)))
27 doors (select-keys interesting (filter #(Character/isUpperCase %)
28 (keys interesting)))
29 player (interesting \@)]
30 {:p player
31 :t (apply conj passages player (vals dkeys))
32 :k dkeys
33 :d doors}))
34
35(defn path-between [trav point-a point-b]
fa02619e
JK
36 (let [succ (fn [[x y]]
37 (filter trav
7a710645
JK
38 [[(inc x) y] [(dec x) y]
39 [x (inc y)] [x (dec y)]]))
fa02619e
JK
40 cost (fn [cs pt] (inc cs))
41 heur (partial manhattan-distance point-b)
42 des? (fn [pt] (= pt point-b))]
43 (second (a-star succ cost heur point-a des?))))
7a710645
JK
44
45(defn accessible [{player :p dkeys :k trav :t}]
46 (->> dkeys
47 (mmap (partial path-between trav player))
48 (remove #(= ##Inf (second %)))
49 (into {})))
50
fa02619e
JK
51#_(let [goto-nearest (fn [[p d k]]
52 (let [l (apply (partial min-key (partial manhattan-distance p)) k)]
53 [l (+ d (manhattan-distance p l)) (remove #{l} k)]))]
54 (as-> [p 0 (vals k)] it
55 (iterate goto-nearest it)
56 (nth it (dec (count k)))
57 (second it)))
7a710645 58(defn acquire-all-keys [world]
fa02619e
JK
59 (let [successor-world (fn [wo [kc ds]]
60 (let [kp (get-in wo [:k kc])
61 dc (Character/toUpperCase kc)
62 dp (get-in wo [:d dc])]
63 (-> wo
64 (assoc :p kp)
65 (assoc :$ ds)
66 (update :t conj dp)
67 (update-in [:k] dissoc kc)
68 (update-in [:l] conj kc))))
69 succ (fn [wo] (map (partial successor-world wo) (accessible wo)))
70 heur (fn [{:keys [p k]}]
71 (if (empty? k) 0
72 (reduce max (map (partial manhattan-distance p) (vals k)))))
73 cost (fn [cs pt] (+ cs (pt :$)))
74 des? (fn [pt] (empty? (pt :k)))]
75 (second (a-star succ cost heur (assoc world :l []) des?))))
7a710645
JK
76
77(defn day18 []
78 (let [input (get-list-from-file (input-file))
79 world (build-world input)]
80 (part1 (acquire-all-keys world))
81 #_(part2)))