From cbb9262fbdfee490fa29de4171780fb4c7dd7614 Mon Sep 17 00:00:00 2001 From: Jonathan Chan Date: Sun, 22 Dec 2019 00:50:36 -0800 Subject: [PATCH] Day 22: Part 1 complete, part 2... still running? --- input/22.txt | 100 +++++++++++++++++++++++++++++++++++++++++++++++++++ src/22.rkt | 92 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 192 insertions(+) create mode 100644 input/22.txt create mode 100644 src/22.rkt diff --git a/input/22.txt b/input/22.txt new file mode 100644 index 0000000..154b55c --- /dev/null +++ b/input/22.txt @@ -0,0 +1,100 @@ +deal with increment 31 +deal into new stack +cut -7558 +deal with increment 49 +cut 194 +deal with increment 23 +cut -4891 +deal with increment 53 +cut 5938 +deal with increment 61 +cut 7454 +deal into new stack +deal with increment 31 +cut 3138 +deal with increment 53 +cut 3553 +deal with increment 61 +cut -5824 +deal with increment 42 +cut -889 +deal with increment 34 +cut 7128 +deal with increment 42 +cut -9003 +deal with increment 75 +cut 13 +deal with increment 75 +cut -3065 +deal with increment 74 +cut -8156 +deal with increment 39 +cut 4242 +deal with increment 24 +cut -405 +deal with increment 27 +cut 6273 +deal with increment 19 +cut -9826 +deal with increment 58 +deal into new stack +cut -6927 +deal with increment 65 +cut -9906 +deal with increment 31 +deal into new stack +deal with increment 42 +deal into new stack +deal with increment 39 +cut -4271 +deal into new stack +deal with increment 32 +cut -8799 +deal with increment 69 +cut 2277 +deal with increment 55 +cut 2871 +deal with increment 54 +cut -2118 +deal with increment 15 +cut 1529 +deal with increment 57 +cut -4745 +deal with increment 23 +cut -5959 +deal with increment 58 +deal into new stack +deal with increment 48 +deal into new stack +cut 2501 +deal into new stack +deal with increment 42 +deal into new stack +cut 831 +deal with increment 74 +cut -3119 +deal with increment 33 +cut 967 +deal with increment 69 +cut 9191 +deal with increment 9 +cut 5489 +deal with increment 62 +cut -9107 +deal with increment 14 +cut -7717 +deal with increment 56 +cut 7900 +deal with increment 49 +cut 631 +deal with increment 14 +deal into new stack +deal with increment 58 +cut -9978 +deal with increment 48 +deal into new stack +deal with increment 66 +cut -1554 +deal into new stack +cut 897 +deal with increment 36 diff --git a/src/22.rkt b/src/22.rkt new file mode 100644 index 0000000..a1b629a --- /dev/null +++ b/src/22.rkt @@ -0,0 +1,92 @@ +#lang racket + +(require match-string + "../lib.rkt") + +(define input + (problem-input 22)) + +(define (parse-technique technique) + (match technique + ["deal into new stack" deal-into-new-stack] + [(string-append "cut " s) (∂ cut-N-cards (string->number s))] + [(string-append "deal with increment " s) (∂ deal-with-increment-N (string->number s))])) + +(define (deal-into-new-stack cards) + (reverse cards)) + +(define (cut-N-cards n cards) + (if (negative? n) + (cut-N-cards (+ (length cards) n) cards) + (append (drop cards n) (take cards n)))) + +(define (deal-with-increment-N n cards) + (let* ([len (length cards)] + [vec (make-vector len)]) + (for ([index (range 0 len)] + [card cards]) + (vector-set! vec (modulo (* index n) len) card)) + (vector->list vec))) + +(define part1 + (let loop ([cards (range 0 10007)] + [shuffle input]) + (if (empty? shuffle) + (index-of cards 2019) + (loop ((parse-technique (first shuffle)) cards) (rest shuffle))))) + +;; egcd : number -> number -> (list number number number) +;; Extended Euclidean algorithm for computing GCD +;; Given integers a and b, return gcd(a, b), x, and y, where +;; ax + by = gcd(a, b). +(define (egcd a b) + (if (zero? a) + (list b 0 1) + (match-let ([(list g x y) (egcd (remainder b a) a)]) + (list g (- y (* x (quotient b a))) x)))) + +;; mmi : number -> number -> number +;; Modular multiplicative inverse +;; Given an integer n and a modulus m, return x such that +;; nx ≡ 1 (mod m), i.e. nx + my = 1 for some x, y. +;; We therefore require that n and m are coprime. +(define (mmi n m) + (match-let ([(list g x y) (egcd n m)]) + x)) + +;; The following functions are inverse to those from part 1 +;; with respect to the card indices. +;; That is, if some shuffling technique s takes a card at index i +;; and moves it to index s(i) = j, then s^-1(j) = i. +;; Therefore, if after applying a series of shuffling techniques, +;; we want to know what card is at position p, +;; we apply the inverse functions in reverse order to find its original index. + +(define (inverse-DINS len i) + (sub1 (- len i))) + +(define (inverse-CNC len n i) + (if (positive? n) + (modulo (+ n i) len) + (modulo (+ n i len) len))) + +(define (inverse-DWIN len n i) + (modulo (* (mmi n len) i) len)) + +(define (inverse-parse len technique) + (match technique + ["deal into new stack" (∂ inverse-DINS len)] + [(string-append "cut " s) (∂ inverse-CNC len (string->number s))] + [(string-append "deal with increment " s) (∂ inverse-DWIN len (string->number s))])) + +(define (inverse-shuffle len) + (apply compose (map (∂ inverse-parse len) input))) + +(define (part2) + (let loop ([count 101741582076661] + [index 2020]) + (if (zero? count) + index + (loop (sub1 count) ((inverse-shuffle 119315717514047) index))))) + +(show-solution part1 #f) \ No newline at end of file