alexandria-ocasio-cortez axiom-of-choice area-of-concern american-orthodox-church almost-optimal-coset solutions in the year of our lord 2021, I guess
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

114 lines
3.3 KiB

#lang racket
(require "lib/common.rkt")
;; board : [Vectorof Integer]
;; seen : [Setof Integer]
(struct bingo (board [seen #:mutable]) #:transparent)
;; boards are 5x5
(define (board-ref vec i j)
(vector-ref vec (+ j (* 5 i))))
;; Input -> [Listof Integer] [Listof Bingo]
(define (parse lines)
(define draws (first lines))
(define boards (rest lines))
(values (map string->number (string-split draws ","))
(for/list ([board (in-list boards)])
(bingo (apply vector (map string->number (string-split board)))
(mutable-set)))))
(define (is-winner? bingo)
(or
;; verticals
(for/or ([i (in-range 5)])
(for/and ([j (in-range 5)])
(set-member?
(bingo-seen bingo)
(board-ref (bingo-board bingo) i j))))
;; horizontals
(for/or ([i (in-range 5)])
(for/and ([j (in-range 5)])
(set-member?
(bingo-seen bingo)
(board-ref (bingo-board bingo) j i))))))
(define (calculate-score bingo last-called)
(define board-set (apply set (vector->list (bingo-board bingo))))
(define remaining (set-subtract board-set (bingo-seen bingo)))
(* (for/sum ([i (in-set remaining)]) i)
last-called))
(define (day4a lines)
(define-values (draws boards) (parse lines))
(define last-called
(for/fold ([last-called -1])
([draw (in-list draws)]
#:break (for/or ([board (in-list boards)])
(is-winner? board)))
(for ([board (in-list boards)])
(when (vector-member draw (bingo-board board))
(set-add! (bingo-seen board) draw)))
draw))
(define winner
(for/first ([board (in-list boards)]
#:when (is-winner? board))
board))
(calculate-score winner last-called))
(define (day4b lines)
(define-values (draws boards) (parse lines))
(define last-winner
(for/fold ([winners '()]
[remaining boards]
#:result (first winners))
([draw (in-list draws)])
(for ([board (in-list remaining)])
(when (vector-member draw (bingo-board board))
(set-add! (bingo-seen board) draw)))
(values
(append
(for/list ([board (in-list remaining)]
#:when (is-winner? board))
(cons board draw))
winners)
(filter (λ (x) (not (is-winner? x))) remaining))))
(print-board (car last-winner))
(displayln (cdr last-winner))
(calculate-score (car last-winner) (cdr last-winner)))
(define (print-board in)
(for ([e (in-slice 5 (in-vector (bingo-board in)))])
(displayln e)))
(module+ main
(call-with-input-file "data/day4.txt"
(lambda (prt)
(define lines (string-split (port->string prt) "\n\n"))
(answer 4 1 (day4a lines))
(answer 4 2 (day4b lines)))))
(module+ test
(require rackunit)
(define test-board
(vector 14 21 17 24 4
10 16 15 9 19
18 8 23 26 20
22 11 13 6 5
2 0 12 3 7))
(define test-seen
(set 14 21 17 4 9 23 11 2 0 7 24))
(check-true (is-winner? (bingo test-board test-seen)))
(call-with-input-file "data/day4.test.txt"
(lambda (prt)
(define lines (string-split (port->string prt) "\n\n"))
(check-equal? (day4a lines) 4512)
(check-equal? (day4b lines) 1924))))