Login
7 branches 0 tags
Ben (X13/Arch) More compact images 8ddaf13 2 years ago 1151 Commits
nujel / tests / ridiculous / day15.nuj
#!/usr/bin/env nujel

(require :array/2d)

(defn map/set/row (data y line w)
       (def cols (map (split line "") 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)

(defn map/supersize (in)
       (def out (array/2d/allocate (* 5 (in :width)) (* 5 (in :height))))
       (dotimes (x (in :width))
       (dotimes (y (in :height))
            (dotimes (cx 5)
            (dotimes (cy 5)
                 (array/2d/set! out
                                (+ x (* cx (in :width)))
                                (+ y (* cy (in :height)))
                                (+ 1 (rem (+ -1 cx cy (array/2d/ref in x y)) 9)))
                 (array/2d/set! out
                                (+ x (* cx (in :width)))
                                (+ y (* cy (in :height)))
                                (+ 1 (rem (+ -1 cx cy (array/2d/ref in x y)) 9)))
            ))
       ))
       out
)

(defn queue/insert-sorted (q items)
       (if (and q (< (caar q) (caar items)))
	   (cons (car q) (queue/insert-sorted (cdr q) items))
	   (if items
	       (cons (car items) (queue/insert-sorted q (cdr items)))
	       q)))

(defn map/walk (cmap)
       (def total-risk (array/2d/allocate (cmap :width) (cmap :height)))
       (array/fill! (total-risk :data) 9999999999)
       (def x-max (- (cmap :width) 1))
       (def y-max (- (cmap :height) 1))
       (def q (list (list 0 x-max y-max)))
       (while q
              (def cur (car q))
	      (cdr! q)
              (def risk (car cur))
              (def x (cadr cur))
              (def y (caddr cur))
              (def crisk (array/2d/ref total-risk x y))
              (when (< risk crisk)
                    (array/2d/set! total-risk x y risk)
                    (+= risk (array/2d/ref cmap x y))
		    (def tmp #nil)
                    (when (< x x-max) (set! tmp (cons (list risk (+ x 1) y) tmp)))
                    (when (< y y-max) (set! tmp (cons (list risk x (+ y 1)) tmp)))
                    (when (> y 0) (set! tmp (cons (list risk x (- y 1)) tmp)))
                    (when (> x 0) (set! tmp (cons (list risk (- x 1) y) tmp)))
		    (when tmp (set! q (queue/insert-sorted q tmp)))
              ))
       (array/2d/ref total-risk 0 0))


(def res-p1 (map/walk (map/load "day15.input" 100 100)))
(when (not= res-p1 315)
      (throw (list :wrong-result "Wrong result" res-p1)))
(def res-p2 (map/walk (map/supersize (map/load "day15.input" 100 100))))
(when (not= res-p2 3040)
      (throw (list :wrong-result "Wrong result" res-p2)))

(return :success)