Login
7 branches 0 tags
Ben (X13/Void) Added array2d functions a4fe39f 4 years ago 258 Commits
nujel / tests / 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 [\ [row] [apply array/new [read row]]] board-raw]]]
]

[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 board/score/num b a]]
       [tree/set! board :score [* last-num [reduce board/score/row [board :board] 0]]]
       [tree/set! board :order [board/get-order]]
       ;[println [ansi-blue "Last Num: " last-num]]
       ;[print/board board marks]
]

[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 [\ [board]
		    [when [and [zero? [board :order]]
		               [bingo? [board :board] marks]]
			  [board/score! board marks last-num]]]
	         boards]
       ;[reduce [\ [a b] [if a a [if [bingo? b marks] b #nil]]] boards]
]

[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]
       ]
       ;[for-each [\ [board] [print/board board marks]] boards]
       [def first-board [car boards]]
       [def last-board [car boards]]
       [for-each [\ [board] [when [< [board :order] [first-board :order]]
			          [set! first-board board]]
		            [when [> [board :order] [last-board :order]]
			          [set! last-board board]]
		            ] boards]
       ;[print/board first-board marks]
       ;[print/board last-board marks]
       [when [!= [first-board :score] 10680]
     	     [throw [list :wrong-result "Wrong result" first-board]]]
       [when [!= [last-board :score] 31892]
	     [throw [list :wrong-result "Wrong result" last-board]]]
]

[def raw [split [file/read "day4.input"] "\n"]]
[def turns [map [\ [a] [car [read a]]] [split [car raw] ","]]]
[def boards [map parse/board [split/boards [cddr raw]]]]

[take-turns boards turns]