application/octet-stream
•
4.38 KB
•
116 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 (pad-start num 3)))
(display (pad-start num 3))))
(defn print/board/line (board marks)
(print/board/line/number (ref board 0) marks)
(print/board/line/number (ref board 1) marks)
(print/board/line/number (ref board 2) marks)
(print/board/line/number (ref board 3) marks)
(print/board/line/number (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))
(set! board :score (* last-num (reduce (ref board :board) board/score/row 0)))
(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 (ref (ref board :board) 0) marks)
(print/board/line (ref (ref board :board) 1) marks)
(print/board/line (ref (ref board :board) 2) marks)
(print/board/line (ref (ref board :board) 3) marks)
(print/board/line (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! (:alloc Array 100) #f))
(while (int? (car turns))
(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)