Login
7 branches 0 tags
Benjamin Vincent Schulenburg Improved docs 0998b4f 3 years ago 907 Commits
nujel / tests / fast / 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/fast/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]