#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"))