-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
1 parent
af77672
commit 55b18dc
Showing
1 changed file
with
69 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
(ns clojure-aoc.core (:gen-class) | ||
(:require [clojure-aoc.grids :as grids] | ||
[clojure.data.priority-map :refer [priority-map]] | ||
clojure.string)) | ||
|
||
(def input (-> (slurp "input.txt") (clojure.string/split #"\n"))) | ||
|
||
;; We can make a small optimizaton in our dijkstra by not re-visiting locations with a smaller streak and heat value, | ||
;; since that path is guaranteed to be better. | ||
|
||
(defn traverse1 [grid] | ||
(let [end (map (comp dec count) [(nth grid 0) grid])] | ||
(loop [to-visit (priority-map [[0 0] :down 0 []] 0) best {[0 0] {:down {0 0}}} visited #{}] | ||
(when-let [[[loc dir streak path] heat] (peek to-visit)] | ||
(if (= loc end) | ||
(do (println path) heat) | ||
(let [neighbours (->> grids/grid-dirs | ||
(filter (fn [[d _]] (every? #(not= d %) [(grids/opposite-dir dir) (if (= streak 3) dir nil)]))) | ||
(map (fn [[d c]] (vector (map + loc c) d))) | ||
(filter (fn [[l _]] (grids/in-bounds grid l))) | ||
(map (fn [[l d]] (vector [l d (if (= dir d) (inc streak) 1) (conj path l)] (+ heat (grids/at grid l))))) | ||
(filter (fn [[[l d s _] h]] | ||
(and (not (contains? visited [l d s])) | ||
(if-let [loc-best (get-in best [l d])] | ||
(not (some (fn [[best-s best-h]] (and (<= best-s s) (<= best-h h))) loc-best)) | ||
true))))) | ||
new-visit (into (pop to-visit) neighbours) | ||
new-best (reduce (fn [acc [[l d s _] h]] (assoc-in acc [l d s] h)) best neighbours) | ||
new-visited (conj visited [loc dir streak])] | ||
(recur new-visit new-best new-visited))))))) | ||
|
||
(defn traverse2 [grid] | ||
(let [end (map (comp dec count) [(nth grid 0) grid])] | ||
(loop [to-visit (priority-map [[0 0] :down 0 []] 0) best {[0 0] {:down {0 0}}} visited #{}] | ||
(when-let [[[loc dir streak path] heat] (peek to-visit)] | ||
(if (and (= loc end) (> streak 3)) | ||
(do (println path) heat) | ||
(let [neighbours (->> grids/grid-dirs | ||
(filter (fn [[d _]] | ||
(cond | ||
(< 0 streak 4) (= d dir) | ||
(= streak 10) (every? #(not= % d) [(grids/opposite-dir dir) dir]) | ||
:else (not= d (grids/opposite-dir dir))))) | ||
(map (fn [[d c]] (vector (map + loc c) d))) | ||
(filter (fn [[l _]] (grids/in-bounds grid l))) | ||
(map (fn [[l d]] (vector [l d (if (= dir d) (inc streak) 1) (conj path l)] (+ heat (grids/at grid l))))) | ||
(filter (fn [[[l d s _] h]] | ||
(and (not (contains? visited [l d s])) | ||
(or (< s 4) | ||
(if-let [loc-best (get-in best [l d])] | ||
(not (some (fn [[best-s best-h]] (and (<= best-s s) (<= best-h h))) loc-best)) | ||
true)))))) | ||
new-visit (into (pop to-visit) neighbours) | ||
new-best (reduce (fn [acc [[l d s _] h]] (assoc-in acc [l d s] h)) best (filter (fn [[[_ _ s _] _]] (> s 3)) neighbours)) | ||
new-visited (conj visited [loc dir streak])] | ||
(recur new-visit new-best new-visited))))))) | ||
|
||
(def part1 | ||
(let [grid (->> (map seq input) | ||
(map (fn [line] (map #(- (int %) (int \0)) line))))] | ||
(traverse1 grid))) | ||
|
||
(def part2 | ||
(let [grid (->> (map seq input) | ||
(map (fn [line] (map #(- (int %) (int \0)) line))))] | ||
(traverse2 grid))) | ||
|
||
(defn -main [& args] | ||
(println (str part1 " " part2))) |