Login
7 branches 0 tags
Ben (X13/Arch) Reimplemented [input] in Nujel and cleaned up the codebase 1cbfc60 3 years ago 788 Commits
nujel / tests / fast / day4.nuj
#!/usr/bin/env nujel

[defn 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]]

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

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

[defn print/board/line [board marks]
       [print/board/line/number [array/ref board 0] marks]
       [print/board/line/number [array/ref board 1] marks]
       [print/board/line/number [array/ref board 2] marks]
       [print/board/line/number [array/ref board 3] marks]
       [print/board/line/number [array/ref board 4] marks]
       [newline]]

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

[defn 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]]]

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

[defn 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]]]

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

[def board/get-order]
[let [[cur-order 0]]
     [set! board/get-order [fn [] [inc! cur-order]]]]

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

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

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

[defn 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
                 [fn [board] [when [< [ref board :order] [ref first-board :order]]
                                  [set! first-board board]]
                            [when [> [ref board :order] [ref last-board :order]]
                                  [set! last-board board]]]]
       [when [not= [ref first-board :score] 10680]
             [throw [list :wrong-result "Wrong Part 1 result" first-board]]]
       [when [not= [ref last-board :score] 31892]
             [throw [list :wrong-result "Wrong Part 2 result" last-board]]]]

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

[take-turns boards turns]

[return :success]