Login
7 branches 0 tags
Ben (X13/Arch) Fixed empty source files breaking stdLib fa27119 3 years ago 399 Commits
nujel / tests / fast / day4.nuj
#!/usr/bin/env nujel

[defun split/boards [l]
       [def qq #nil]
       [def q #nil]
       [while l
              [if [== [car l] ""]
                  [do [set! qq [cons [reverse q] qq]]
                      [set! q #nil]]
                  [set! q [cons [car l] q]]]
              [cdr! l]]
       [reverse qq]]

[defun parse/board [board-raw]
       @[:score 0 :order 0 :board [apply array/new [map board-raw [\ [row] [apply array/new [read row]]]]]]]

[defun print/board/line/number [num marks]
       [if [marks num]
           [display [ansi-green [string/pad-start num 3]]]
           [display [string/pad-start num 3]]]]

[defun print/board/line [board marks]
       [print/board/line/number [board 0] marks]
       [print/board/line/number [board 1] marks]
       [print/board/line/number [board 2] marks]
       [print/board/line/number [board 3] marks]
       [print/board/line/number [board 4] marks]
       [newline]]

[defun bingo/row? [board marks row]
       [and [marks [[board row] 0]]
            [marks [[board row] 1]]
            [marks [[board row] 2]]
            [marks [[board row] 3]]
            [marks [[board row] 4]]]]

[defun bingo/rows? [board marks]
       [or [bingo/row? board marks 0]
           [bingo/row? board marks 1]
           [bingo/row? board marks 2]
           [bingo/row? board marks 3]
           [bingo/row? board marks 4]]]

[defun bingo/col? [board marks col]
       [and [marks [[board 0] col]]
            [marks [[board 1] col]]
            [marks [[board 2] col]]
            [marks [[board 3] col]]
            [marks [[board 4] col]]]]

[defun bingo/cols? [board marks]
       [or [bingo/col? board marks 0]
           [bingo/col? board marks 1]
           [bingo/col? board marks 2]
           [bingo/col? board marks 3]
           [bingo/col? board marks 4]]]

[defun bingo? [board marks]
       [or [bingo/rows? board marks]
           [bingo/cols? board marks]]]

[def board/get-order]
[let [[cur-order 0]]
     [set! board/get-order [\ [] [++ cur-order]]]]

[defun board/score! [board marks last-num]
       [defun board/score/num [a b] [+ a [if [marks b] 0 b]]]
       [defun board/score/row [a b] [reduce b board/score/num a]]
       [tree/set! board :score [* last-num [reduce [board :board] board/score/row 0]]]
       [tree/set! board :order [board/get-order]]]

[defun print/board [board marks last-num]
       [if [not [zero? [board :order]]]
           [do [println [ansi-rainbow "BINGO!!!!"]]
               [println ["Score: " [ansi-blue [board :score]]]]
               [println ["Order: " [ansi-gray [board :order]]]]]
           [println [ansi-yellow "Board:"]]]
       [print/board/line [[board :board] 0] marks]
       [print/board/line [[board :board] 1] marks]
       [print/board/line [[board :board] 2] marks]
       [print/board/line [[board :board] 3] marks]
       [print/board/line [[board :board] 4] marks]
       [newline]]

[defun check/boards [boards marks last-num]
       [for-each boards
                 [\ [board]
                    [when [and [zero? [board :order]]
                               [bingo? [board :board] marks]]
                          [board/score! board marks last-num]]]]]

[defun take-turns [boards turns]
       [def marks [array/fill! [array/allocate 100] #f]]
       [while [int? [car turns]]
              [array/set! marks [car turns] #t]
              [check/boards boards marks [car turns]]
              [cdr! turns]]
       [def first-board [car boards]]
       [def last-board [car boards]]
       [for-each boards
                 [\ [board] [when [< [board :order] [first-board :order]]
                                  [set! first-board board]]
                            [when [> [board :order] [last-board :order]]
                                  [set! last-board board]]]]
       [when [!= [first-board :score] 10680]
             [throw [list :wrong-result "Wrong Part 1 result" first-board]]]
       [when [!= [last-board :score] 31892]
             [throw [list :wrong-result "Wrong Part 2 result" last-board]]]]

[def raw [split [file/read "tests/fast/day4.input"] "\n"]]
[def turns [-> [car raw] [split ","] [map int]]]
[def boards [-> [cddr raw] [split/boards] [map parse/board]]]

[take-turns boards turns]