aboutsummaryrefslogtreecommitdiff
path: root/aoc2023-racket/day-04/day-04.rkt
blob: 7a357c59e1c3e97150094d499c035f8e62d65c28 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#lang racket

(require advent-of-code
         data/applicative
         data/either
         data/monad
         megaparsack
         megaparsack/text
         threading)

(struct card (n wins))

(define card/p
  (do (string/p "Card")
    (many/p space/p)
    [n <- integer/p]
    (string/p ":")
    (many/p space/p)
    [winners <- (many-until/p integer/p #:sep (many/p space/p) #:end (try/p (string/p " | ")))]
    (many/p space/p)
    [has <- (many+/p integer/p #:sep (many/p space/p))]
    (pure (card n (set-count (set-intersect (first winners) has))))))

(define raw-cards (~> (open-aoc-input (find-session) 2023 4 #:cache #true) port->lines))

;; part 1
(for/sum ([raw-card (in-list raw-cards)]
          #:do [(match-define (success (card _ wins)) (parse-string card/p raw-card))]
          #:unless (= wins 0))
  (expt 2 (sub1 wins)))

;; part 2
(for/fold ([counts (for/hash ([n (in-inclusive-range 1 (length raw-cards))])
                     (values n 1))]
           #:result (apply + (hash-values counts)))
          ([raw-card (in-list raw-cards)]
           #:do [(match-define (success (card n wins)) (parse-string card/p raw-card))])
  (define bonus-range (inclusive-range (+ n 1) (+ n wins)))
  (define won-cards (hash-ref counts n))
  (foldl (λ (n acc) (hash-update acc n (curry + won-cards))) counts bonus-range))