Login
7 branches 0 tags
Ben (X13/Arch) Simplified things a little 0643405 9 days ago 1260 Commits
nujel / tests / slow / day9.nuj
#!/usr/bin/env nujel

(require :array/2d)

(defn is-low-point? (data x y)
      (def v (array/2d/ref data x y))
      (def top (if (> y 0)
                   (array/2d/ref data x (- y 1))
                   10))
      (def bottom (if (< y (- (ref data :height) 1))
                      (array/2d/ref data x (+ y 1))
                      10))
      (def right (if (< x (- (ref data :width) 1))
                     (array/2d/ref data (+ x 1) y)
                     10))
      (def left (if (> x 0)
                    (array/2d/ref data (- x 1) y)
                    10))
      (and (< v top) (< v bottom) (< v right) (< v left)))

(defn count-basin-size (data x y)
      (if (or (< x 0)
              (>= x (ref data :width))
              (< y 0)
              (>= y (ref data :height))
              (= 9 (array/2d/ref data x y)))
          0
          (do (array/2d/set! data x y 9)
              (+ 1 (count-basin-size data (- x 1) y)
                 (count-basin-size data (+ x 1) y)
                 (count-basin-size data x (- y 1))
                 (count-basin-size data x (+ y 1))))))

(defn array/2d/find-low-points (data)
      (def low-point-sum 0)
      (def basins #nil)
      (dotimes (y (ref data :height))
               (dotimes (x (ref data :width))
                        (when (is-low-point? data x y)
                              (+= low-point-sum (+ 1 (array/2d/ref data x y)))
                              (set! basins (cons (count-basin-size data x y) basins)))
                        ))
      (def bb (reverse (sort basins)))
      (def biggest-3-basins (list (car bb) (cadr bb) (caddr bb)))
      {:part1 low-point-sum :part2 (* (car bb) (cadr bb) (caddr bb))})

(defn map/set/row (data y line w)
      (def cols (map (split line "") read/int))
      (dotimes (x w)
               (array/2d/set! data x y (car cols))
               (cdr! cols)))

(defn map/load (filename w h)
      (def ret (array/2d/allocate w h))
      (def lines (split (file/read filename) "\n"))
      (dotimes (y h)
               (map/set/row ret y (car lines) w)
               (cdr! lines))
      ret)

(def ex-map (map/load "tests/slow/day9.dat" 100 100))
(def res (array/2d/find-low-points ex-map))
(def result (ref res :part1))
(when (not= result 480)
      (throw (list :wrong-result "Wrong result" result)))
(def result (ref res :part2))
(when (not= result 1045660)
      (throw (list :wrong-result "Wrong result" result)))

(return :success)