aoc2021-day15b Clojure/JVM program
source code
; SPDX-License-Identifier: MIT
; Copyright (C) 2021 Tito Sacchi <tito@tilde.team>
; WARNING: These solutions were written while I was still learning Clojure and
; should by no means be taken as examples of good programming practice or fast
; implementations.
(ns aoc.2021.15b
(:require
[clojure.string :as str]
[clojure.java.io :as io]
[clojure.data.priority-map :refer [priority-map-keyfn]]))
(def input *in*)
(def grid (->> input
(io/reader)
(line-seq)
(mapcat (partial map #(Integer/parseInt (str %))))
(vec)))
(def block-size (Math/round (Math/sqrt (count grid))))
(def n (* block-size 5))
(defn at [[x y]] (+ (* y block-size) x))
(defn get-cost [grid [x y]]
(let [block-x (quot x block-size)
block-y (quot y block-size)
offset-x (rem x block-size)
offset-y (rem y block-size)
cost (+ block-x block-y (grid (at [offset-x offset-y])))]
(if (> cost 9) (- cost 9) cost)))
(defn all-coords [maxx maxy]
(for [x (range maxx)
y (range maxy)]
[x y]))
(defn xor [a b] (and (not (and a b)) (or a b)))
(defn neighbours [[x y]]
(for [dx [-1 0 1]
dy [-1 0 1]
:when (xor (not= dx 0) (not= dy 0))
:let [newx (+ x dx)
newy (+ y dy)]
:when (and (>= newx 0) (< newx n))
:when (and (>= newy 0) (< newy n))]
[newx newy]))
(defn dijkstra [cost-of start end]
(loop [pq (assoc
(reduce
#(assoc %1 %2 [##Inf nil]) ; [dist, prev]
(priority-map-keyfn first)
(all-coords n n))
start [0 nil])
prevs {}]
(let [[node [this-dist prev]] (first pq)
popd (dissoc pq node)
saved-prev (assoc prevs node prev)]
(if (= node end) saved-prev
(recur
(into popd (for [neigh (neighbours node)
:let [cost (cost-of neigh)
new-neigh-dist (+ this-dist cost)
old-neigh-dist (first (pq neigh))]
:when (some? old-neigh-dist) ; If neighbour is still in the priority queue
:when (< new-neigh-dist old-neigh-dist)]
[neigh [new-neigh-dist node]]))
saved-prev)))))
(defn acc-path [dst edges]
(loop [path [dst]]
(let [prev (edges (peek path))]
(if (some? prev)
(recur (conj path prev))
path))))
(def corner0 [0 0])
(def corner1 [(dec n) (dec n)])
(println (->> (dijkstra (partial get-cost grid) corner0 corner1)
(acc-path corner1)
(drop-last)
(map (partial get-cost grid))
(apply +)))
notes, command-line, and program output
NOTES:
Linux
Sun, 23 Jan 2022 19:49:40 GMT
COMMAND LINE:
clojure -cp /usr/share/java/data.priority-map.jar aoc2021_day15b.clj-1.clj 0 < aoc2021_day15b-input1000.txt
PROGRAM FAILED
PROGRAM OUTPUT:
Syntax error (OutOfMemoryError) compiling at (aoc2021_day15b.clj-1.clj:74:1).
Java heap space
Full report at:
/tmp/clojure-6016254585756780120.edn