aoc2020/17.rkt

64 lines
1.9 KiB
Racket
Raw Normal View History

2020-12-17 05:17:44 +00:00
#lang curly-fn racket
(require "scripts/aoc.rkt")
;; solution for day 17
(struct pt [x y z w] #:transparent)
(define pt-getters (list pt-x pt-y pt-z pt-w))
2020-12-17 05:59:45 +00:00
(define origin (pt 0 0 0 0))
2020-12-17 05:17:44 +00:00
(define (pt+ . args)
2020-12-17 06:10:57 +00:00
(for/fold ([ans origin]) ([x (in-list args)])
(apply pt (map #{+ (% ans) (% x)} pt-getters))))
(define (in-pts lower upper use-w?)
(define (in-range+ getter)
(in-range (sub1 (getter lower)) (+ 2 (getter upper))))
(for*/stream ([x (in-range+ pt-x)]
[y (in-range+ pt-y)]
[z (in-range+ pt-z)]
[w (if use-w? (in-range+ pt-w) (in-range 1))])
(pt x y z w)))
(define nearby/4d
2020-12-17 05:59:45 +00:00
(for/list ([pt (in-pts origin origin #t)] #:unless (equal? pt origin)) pt))
(define nearby/3d (filter #{zero? (pt-w %)} nearby/4d))
(define (calc-bounds world)
2020-12-17 06:07:02 +00:00
(define (helper reducer)
(apply pt (map #{apply reducer (set-map world %)} pt-getters)))
(values (helper min) (helper max)))
(define (simulate world use-w?)
(define-values [lower upper] (calc-bounds world))
(define nearby (if use-w? nearby/4d nearby/3d))
2020-12-17 06:07:02 +00:00
(for*/set ([pt (in-pts lower upper use-w?)]
[ct (in-value (stream-count #{set-member? world (pt+ pt %)} (in-list nearby)))]
#:when (if (set-member? world pt) (<= 2 ct 3) (= 3 ct)))
pt))
(define (simulate/times world times use-w?)
2020-12-17 06:07:02 +00:00
(set-count (for/fold ([world world]) ([_ (in-range times)])
(simulate world use-w?))))
(define part1 #{simulate/times % 6 #f})
(define part2 #{simulate/times % 6 #t})
2020-12-17 05:17:44 +00:00
;; parse input file
(define (parse fname)
(define input (file->lines fname))
(define world (mutable-set))
2020-12-17 05:17:44 +00:00
(for ([line (in-list input)] [y (in-naturals)])
(for ([char (in-string line)] [x (in-naturals)])
(when (char=? #\# char)
(set-add! world (pt x y 0 0)))))
2020-12-17 05:17:44 +00:00
world)
(module+ main
(define input (parse "inputs/17"))
(answer 17 1 (time (part1 input)))
(answer 17 2 (time (part2 input)))
(displayln "meow"))