Advent of Code 2020 solutions in Racket, 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.

67 lines
2.1 KiB

#lang racket/base
(require "lib/common.rkt"
racket/set racket/string racket/vector
(define (run-game input steps)
(define len (vector-length input))
(define mapping
(for/vector ([i (in-range (add1 (vector-length input)))])
(if (zero? i) #f (mcons i #f))))
(define fst (vector-ref mapping (vector-ref input 0)))
(define lst (vector-ref mapping (vector-ref input (sub1 (vector-length input)))))
(set-mcdr! lst fst)
(for ([i (in-range 1 (vector-length input))])
(define item (vector-ref mapping (vector-ref input i)))
(define prev (vector-ref mapping (vector-ref input (sub1 i))))
(set-mcdr! prev item))
(define (tick-game item-ref)
(define cur (mcar item-ref))
(define top (mcdr item-ref))
(define bottom (mcdr (mcdr top)))
(define cups
(let loop ([d top] [cards (set)])
(if (eq? d bottom)
(set-add cards (mcar d))
(loop (mcdr d) (set-add cards (mcar d))))))
(set-mcdr! item-ref (mcdr bottom))
(set-mcdr! bottom #f)
(define wanted
(let loop ([wanted (sub1 cur)])
(cond [(zero? wanted) (loop len)]
[(set-member? cups wanted) (loop (sub1 wanted))]
[else wanted])))
(define wanted-ref (vector-ref mapping wanted))
(set-mcdr! bottom (mcdr wanted-ref))
(set-mcdr! wanted-ref top)
(mcdr item-ref))
(for/fold ([ref fst])
([_ (in-range steps)])
(tick-game ref))
(vector-ref mapping 1))
(define (day23a input)
(define result (run-game input 100))
(define one (mcar result))
(for/list ([v (in-mlist (mcdr result))]
#:break (= v one))
(number->string v))))
(define (day23b input)
(define real-input
(vector-append input (build-vector (- 1000000 (vector-length input))
(λ (x) (+ (add1 (vector-length input)) x)))))
(define result (run-game real-input 10000000))
(* (mlist-ref result 1) (mlist-ref result 2)))
(module+ main
(define input #(3 9 4 6 1 8 5 2 7))
(answer 23 1 (day23a input))
(answer 23 2 (day23b input)))