aoc2020/23.rkt

86 lines
2.7 KiB
Racket

#lang curly-fn racket
(require "scripts/aoc.rkt")
;; solution for day 23
;; this doesn't noticably change execution time :(
; (require racket/unsafe/ops)
; (define-simple-macro (mcar x) (unsafe-mcar x))
; (define-simple-macro (mcdr x) (unsafe-mcdr x))
; (define-simple-macro (set-mcar! l x) (unsafe-set-mcar! l x))
; (define-simple-macro (set-mcdr! l x) (unsafe-set-mcdr! l x))
; (define-simple-macro (vector-ref v i) (unsafe-vector-ref v i))
; (define-simple-macro (= a b) (unsafe-fx= a b))
; (define-simple-macro (sub1 x) (unsafe-fx- x 1))
; (define-simple-macro (zero? x) (unsafe-fx= x 0))
(define (move-opt* input times)
(define total (vector-length input))
(define-values [total+ total-] (values (add1 total) (sub1 total)))
(define items-map
(for/vector ([i (in-range total+)])
(if (zero? i) #f (mcons i #f))))
;; wrap it
(define fst (vector-ref items-map (vector-ref input 0)))
(define lst (vector-ref items-map (vector-ref input total-)))
(set-mcdr! lst fst)
;; fill in the rest
(for ([i (in-range 1 total)])
(set-mcdr! (vector-ref items-map (vector-ref input (sub1 i)))
(vector-ref items-map (vector-ref input i))))
(for/fold ([item-ref fst]) ([i (in-range times)])
(define current (mcar item-ref))
;; 🦈
(define top (mcdr item-ref))
(define mid (mcdr top))
(define bottom (mcdr mid))
;; the card values, for comparison against the card number to insert after
(define-values [tv mv bv] (values (mcar top) (mcar mid) (mcar bottom)))
;; unlink
(set-mcdr! item-ref (mcdr bottom))
(define wanted-value
(let loop ([wanted (sub1 current)])
(cond [(zero? wanted) (loop total)]
[(or (= wanted tv) (= wanted mv) (= wanted bv))
(loop (sub1 wanted))]
[else wanted])))
;; relink in new place
(define wanted-ref (vector-ref items-map wanted-value))
(set-mcdr! bottom (mcdr wanted-ref))
(set-mcdr! wanted-ref top)
;; return next head ref
(mcdr item-ref))
(vector-ref items-map 1))
(define (part1 input)
(define res (move-opt* input 100))
(let loop ([x (mcdr res)])
(if (eq? x res)
""
(string-append (number->string (mcar x)) (loop (mcdr x))))))
(define (part2 input)
(define rst (for/vector ([x (in-range (add1 (vector-length input)) 1000001)]) x))
(define all (vector-append input rst))
(define res (move-opt* all 10000000))
(* (mcar (mcdr (mcdr res))) (mcar (mcdr res))))
;; parse input file
(define (parse fname)
(~>> fname file->string (regexp-match* #px"\\d") (map string->number) list->vector))
(module+ main
(define input (parse "inputs/23"))
(answer 23 1 (time (part1 input)))
(answer 23 2 (time (part2 input)))
(displayln "meow"))