]>
Commit | Line | Data |
---|---|---|
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))) |