-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday9.clj
61 lines (54 loc) · 1.8 KB
/
day9.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
(ns clojure-solutions.day9
(:require [clojure.string :as str]
[clojure.set :as set])
(:use [clojure-solutions.util] :reload))
(defn- parse []
(->> (slurp "./input/day9.txt")
str/split-lines
(map #(str-to-coll-base 10 %))))
(defn- neighbours
"Get all horizontal/vertical neighbours of an index."
[i j]
[[(dec i) j] [i (dec j)]
[(inc i) j] [i (inc j)]])
(defn- get-sinks [mat]
(map-matrix (fn [i j el]
(when (every? #(< el %) ; is a sink?
(keep #(mat-ix mat %) ; get values of neighbours
(neighbours i j)))
[el [i j]])) ; return sink value and indices
mat))
;; => 631
(defn- part1 [mat]
(reduce (fn [acc [el _]] (+ acc (inc el)))
0
(get-sinks mat)))
(defn- basin-for
"For a given matrix `mat', find the basin associated to `el', which
should be a sink."
[mat el]
(letfn
((go [seen [n [i j]]]
(let [bigger-nums ; numbers bigger than the current one
(keep (fn [ixs]
(let [k (mat-ix mat ixs)]
(when (and (some? k) (> k n) (not= k 9))
[k ixs])))
(neighbours i j))]
(if (empty? bigger-nums)
(conj seen [i j]) ; no new numbers -> abort
(apply set/union ; new numbers -> recurse
(map #(go (conj seen [i j]) %)
bigger-nums))))))
(go #{} el)))
;; => 821560
(defn- part2 [mat]
(->> (get-sinks mat)
(map #(count (basin-for mat %)))
(sort >)
(take 3)
(reduce *)))
(defn day9 []
(let [mat (parse)]
(println (part1 mat))
(println (part2 mat))))