Login
7 branches 0 tags
Benjamin Vincent Schulenburg Faster/more efficient [array/fill!] ca9e57f 4 years ago 261 Commits
nujel / tests / day9.nuj
#!/usr/bin/env nujel

[defun 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 [- [data :height] 1]]
                       [array/2d/ref data x [+ y 1]]
                        10]]
       [def right [if [< x [- [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]]
]

[defun count-basin-size [data x y]
       [if [or [< x 0]
               [>= x [data :width]]
               [< y 0]
               [>= y [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]]]]]
]

[defun array/2d/find-low-points [data]
       [def low-point-sum 0]
       [def basins #nil]
       [for [y 0 [data :height]]
       [for [x 0 [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 [list/sort basins]]
       [def biggest-3-basins [list [car bb] [cadr bb] [caddr bb]]]
       @[:part1 [low-point-sum] :part2 [apply * biggest-3-basins]]
]

[defun map/set/row [data y line w]
       [def cols [map int [split line ""]]]
       [for [x 0 w]
            [array/2d/set! data x y [car cols]]
            [cdr! cols]
       ]
]

[defun map/load [filename w h]
       [def ret [array/2d/allocate w h]]
       [def lines [split [file/read filename] "\n"]]
       [for [y 0 h]
            [map/set/row ret y [car lines] w]
            [cdr! lines]
       ]
       ret
]

[def ex-map [map/load "day9.input" 100 100]]
[def res [array/2d/find-low-points ex-map]]
[def result [res :part1]]
[when [!= result 480]
      [throw [list :wrong-result "Wrong result" result]]]
[def result [res :part2]]
[when [!= result 1045660]
      [throw [list :wrong-result "Wrong result" result]]]