application/octet-stream
•
4.44 KB
•
114 lines
#!/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 ["Score: " [ansi-blue [ref board :score]]]]
[println ["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 [!= [ref first-board :score] 10680]
[throw [list :wrong-result "Wrong Part 1 result" first-board]]]
[when [!= [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]