aboutsummaryrefslogtreecommitdiff
path: root/2021/day-11/day-11.rkt
blob: 0a3d48550105bbf781aa7bd9b0828e598f3517b5 (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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
#lang racket
(require "../../jj-aoc.rkt"
         threading)

(define coords
  (~>> (for/list ([r (in-range 10)])
         (for/list ([c (in-range 10)])
           (cons r c)))
       (apply append)))

(define octopus-data
  (~>> (for/list ([l (in-lines (open-day 11 2021))]
                  #:unless (equal? l ""))
         (~>> l
              string->list
              (map (λ~>> ~a string->number))))
       (apply append)
       (map cons coords)
       make-hash))

(define total-length (hash-count octopus-data))
(define row-length (sqrt total-length))

(define (adjacent-to coord)
  (match-define (cons r c) coord)
  (for*/list ([row (in-list '(-1 0 1))]
              [col (in-list '(-1 0 1))]
              #:unless (= 0 row col))
    (cons (+ r row) (+ c col))))

(define (simulate-octopi-step data)
  (define flashed-this-step (mutable-set))
  
  (let look-for-more-flashes
    ([octopi (for/hash ([(k v) data])
               (values k (add1 v)))]
     [flashes-so-far 0])
    (define-values (next-octopus-update
                    flashes-this-update)
      (for*/fold ([octopi octopi] [flashes 0])
                 ([(p x) (in-hash octopi)]
                  #:when (> x 9)
                  #:unless (set-member? flashed-this-step p))
        (set-add! flashed-this-step p)
        (define flashed-octopi
          (for*/fold ([o (hash-set octopi p 0)])
                     ([adj (in-list (adjacent-to p))]
                      #:when (hash-has-key? o adj)
                      #:unless (set-member? flashed-this-step adj))
            (hash-update o adj add1)))
        (values flashed-octopi
                (add1 flashes))))
    (if (> flashes-this-update 0)
        (look-for-more-flashes next-octopus-update
                               (+ flashes-so-far
                                  flashes-this-update))
        (values next-octopus-update
                flashes-so-far))))

;; part 1
(for/fold ([octopi octopus-data]
           [total-flashes 0] #:result total-flashes)
          ([step (in-range 100)])
  (define-values [next-state
                  flashes-from-this-state]
    (simulate-octopi-step octopi))
  (values next-state
          (+ total-flashes flashes-from-this-state)))

;; part 2
(for/fold ([octopi octopus-data]
           [synchro-step #f] #:result synchro-step)
          ([step (in-naturals 1)])
  (define-values [next-state
                  flashes-from-this-state]
    (simulate-octopi-step octopi))
  #:final (= flashes-from-this-state 100)
  (values next-state
          step))