AoC'21, day 4, first problem rvc


Return the first winning card’s score.

 $ cat 04a.rkt  
 #lang racket 
  
  
 (provide 
   example-data 
   read-input) 
  
  
 (require 
   (prefix-in aoc: "aoc.rkt") 
   (prefix-in a: "array.rkt") 
   (prefix-in srfi42: srfi/42) 
   (prefix-in utl: "../scheme/utl.rkt")) 
  
  
 (define (aoc04a . args) 
  
   ; Return the score of the winning board in the given bingo 
   ; game.  If no game is given, use the contest problem input; 
   ; otherwise assume the argument is the string representation of 
   ; a problem input. 
  
   (run-the-game (apply read-input args))) 
  
  
  
 (define (bingo-board board-data) 
  
   ; Return an empty bingo board representing the given bingo card. 
  
  
   (define card (a:new board-data)) 
  
   ; Map a bingo number n to the count of unmarked numbers in the 
   ; row or column containing n on the board.  N is assumed to be 
   ; somewhere on the board. 
  
   (define rows (make-hash)) 
   (define cols (make-hash)) 
  
  
   (define (fill-board board card) 
  
     (let ((n (a:rows card))) 
       (do ((r (- n 1) (- r 1))) ((= r -1) #t) 
         (let ((v (vector n))) 
           (do ((c (- n 1) (- c 1))) ((= c -1) #t) 
             (hash-set! board (a:ref card r c) v)))))) 
  
  
   (define (mark board n) 
  
     ; Mark the given bingo board with the given number; return #t 
     ; iff the number completes a row or column in the board. 
      
     (let* ((v (hash-ref board n)) 
            (c (- (vector-ref v 0) 1))) 
       (vector-set! v 0 c) 
       (hash-remove! board n) 
       (zero? c))) 
  
  
   (fill-board rows card) 
   (fill-board cols (a:transpose card)) 
  
    
   (lambda (n) 
     (if (hash-has-key? rows n) 
         (begin 
           (if (or (mark rows n) (mark cols n)) 
               (apply + (hash-keys rows)) 
               0)) 
         0))) 
  
  
 (define  (read-input . arg) 
  
   ; Return the given bingo set-up.  If no set-up is given, use the 
   ; contest problem input; otherwise assume the argument is the 
   ; string representation of a problem input. 
  
  
   (define (make-board board-data) 
     (bingo-board 
       (map (lambda (b) (map string->number b)) board-data))) 
  
  
   (let ((i (aoc:aoc-read-input (if (null? arg) 4 (car arg))))) 
     (cons  
      (aoc:read-comma-separated-numbers (caaar i)) 
      (map make-board (cdr i))))) 
  
  
 (define (run-the-game bingo-game) 
  
   ; Return the score of the winning board in the given bingo 
   ; game. 
    
   (call-with-current-continuation 
  
     (lambda (k) 
  
       (srfi42:do-ec 
  
         (srfi42::list call (car bingo-game)) 
         (srfi42::list board (cdr bingo-game)) 
  
         (let ((board-value (board call))) 
           (unless (zero? board-value) 
             (k (* board-value call)))))))) 
  
  
 (module+ main 
  
   (aoc04a)) 
  
  
 (aoc:define-string example-data 
   "7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1" 
   "" 
   "22 13 17 11  0" 
   " 8  2 23  4 24" 
   "21  9 14 16  7" 
   " 6 10  3 18  5" 
   " 1 12 20 15 19" 
   "" 
   " 3 15  0  2 22" 
   " 9 18 13 17  5" 
   "19  8  7 25 23" 
   "20 11 10 24  4" 
   "14 21 16 12  6" 
   "" 
   "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 example-result 4512) 
  
  
 (module+ test 
  
   (require rackunit) 
  
   (check-equal? (aoc04a example-data) example-result) 
   (check-equal? (aoc04a) 54275) 
   ) 
  
  
 $ raco test 04a.rkt  
 raco test: (submod "04a.rkt" test) 
 2 tests passed 
  
 $