Refactoring day 22 and 23.
This commit is contained in:
parent
35437aeb6a
commit
50820b435a
76
src/22.rkt
76
src/22.rkt
|
@ -9,18 +9,27 @@
|
||||||
|
|
||||||
;; A shuffle operation (technique) is
|
;; A shuffle operation (technique) is
|
||||||
;; an affine transformation on a card's index.
|
;; an affine transformation on a card's index.
|
||||||
;; Applying the transformation (m, o) to i yields (m*i + o).
|
|
||||||
;; We can compose transformations and only keep track
|
|
||||||
;; of the multiple and offset factors (modulo some len).
|
|
||||||
;; The identity transformation is I = (1, 0).
|
;; The identity transformation is I = (1, 0).
|
||||||
|
;; Applying the transformation (m, o) to i yields (m*i + o).
|
||||||
|
|
||||||
(struct affine (multiple offset) #:transparent)
|
(struct affine (multiple offset) #:transparent)
|
||||||
|
|
||||||
|
(define I (affine 1 0))
|
||||||
|
|
||||||
(define (apply-affine len mo i)
|
(define (apply-affine len mo i)
|
||||||
(match-let ([(affine m o) mo])
|
(match-let ([(affine m o) mo])
|
||||||
(% (+ (* m i) o) len)))
|
(% (+ (* m i) o) len)))
|
||||||
|
|
||||||
(define I (affine 1 0))
|
;; We can compose transformations and only keep track
|
||||||
|
;; of the multiple and offset factors (modulo some len);
|
||||||
|
;; <> composes two transformations as if the second were
|
||||||
|
;; applied first and the first applied last, so
|
||||||
|
;; (m1 , o1) <> (m2, o2) = (m1 * m2, m1 * o2 + o1).
|
||||||
|
(define (<> len a1 a2)
|
||||||
|
(match-let ([(affine m1 o1) a1]
|
||||||
|
[(affine m2 o2) a2])
|
||||||
|
(affine (% (* m1 m2) len)
|
||||||
|
(% (+ (* m1 o2) o1) len))))
|
||||||
|
|
||||||
;; Applying the transformation (m, o) n times is the same as
|
;; Applying the transformation (m, o) n times is the same as
|
||||||
;; applying the transformation (m^n + o*(m^n - 1)/(m - 1)),
|
;; applying the transformation (m^n + o*(m^n - 1)/(m - 1)),
|
||||||
|
@ -31,6 +40,13 @@
|
||||||
[o* (% (* o (sub1 m^n) (modular-inverse (sub1 m) len)) len)])
|
[o* (% (* o (sub1 m^n) (modular-inverse (sub1 m) len)) len)])
|
||||||
(affine m^n o*)))
|
(affine m^n o*)))
|
||||||
|
|
||||||
|
;; Inverting the transformation (m, o) is the same as
|
||||||
|
;; the transformation (m^-1, -o*m^-1)
|
||||||
|
(define (affine-invert mo len)
|
||||||
|
(match-let* ([(affine m o) mo]
|
||||||
|
[m^-1 (modular-inverse m len)])
|
||||||
|
(affine m^-1 (* -1 o m^-1))))
|
||||||
|
|
||||||
;; All shuffling transformation techniques are modulo the number of cards.
|
;; All shuffling transformation techniques are modulo the number of cards.
|
||||||
;; deal into new stack: reversing the order of the cards,
|
;; deal into new stack: reversing the order of the cards,
|
||||||
;; corresponding to the transformation i → -1*i + (length - 1)
|
;; corresponding to the transformation i → -1*i + (length - 1)
|
||||||
|
@ -39,56 +55,30 @@
|
||||||
;; deal with increment N: placing a card every n steps,
|
;; deal with increment N: placing a card every n steps,
|
||||||
;; corresponding to the transformation i → n*i
|
;; corresponding to the transformation i → n*i
|
||||||
|
|
||||||
(define (DINS len mo)
|
(define (DINS len)
|
||||||
(match-let ([(affine m o) mo])
|
(affine -1 (sub1 len)))
|
||||||
(affine (% (* m -1) len)
|
|
||||||
(% (- (sub1 len) o) len))))
|
|
||||||
|
|
||||||
(define (CNC len n mo)
|
(define (CNC len n)
|
||||||
(match-let ([(affine m o) mo])
|
(affine 1 (* n -1)))
|
||||||
(affine m (% (- o n) len))))
|
|
||||||
|
|
||||||
(define (DWIN len n mo)
|
(define (DWIN len n)
|
||||||
(match-let ([(affine m o) mo])
|
(affine n 0))
|
||||||
(affine (% (* m n) len)
|
|
||||||
(% (* o n) len))))
|
|
||||||
|
|
||||||
;; The corresponding inverse transformations are:
|
|
||||||
;; DINS: -1*i + (length - 1) ← i
|
|
||||||
;; CNC: i + n ← i
|
|
||||||
;; DWIN: n^-1*i ← i
|
|
||||||
;; where ·^-1 is the modular multiplicative inverse
|
|
||||||
|
|
||||||
(define (inverse-DINS len mo)
|
|
||||||
(DINS len mo))
|
|
||||||
|
|
||||||
(define (inverse-CNC len n mo)
|
|
||||||
(CNC len (* n -1) mo))
|
|
||||||
|
|
||||||
(define (inverse-DWIN len n mo)
|
|
||||||
(DWIN len (modular-inverse n len) mo))
|
|
||||||
|
|
||||||
;; Shuffling combines all transformations in order.
|
;; Shuffling combines all transformations in order.
|
||||||
;; Inverse shuffling combines all inverse transformations in reverse order.
|
;; Inverse shuffling is simply the inverse transformation.
|
||||||
;; We begin with the identity transformation, I = (1, 0).
|
;; We begin with the identity transformation, I = (1, 0).
|
||||||
|
|
||||||
(define (parse len T mo)
|
(define (parse len T)
|
||||||
(match T
|
(match T
|
||||||
["deal into new stack" (DINS len mo)]
|
["deal into new stack" (DINS len)]
|
||||||
[(string-append "cut " s) (CNC len (string->number s) mo)]
|
[(string-append "cut " s) (CNC len (string->number s))]
|
||||||
[(string-append "deal with increment " s) (DWIN len (string->number s) mo)]))
|
[(string-append "deal with increment " s) (DWIN len (string->number s))]))
|
||||||
|
|
||||||
(define (inverse-parse len T mo)
|
|
||||||
(match T
|
|
||||||
["deal into new stack" (inverse-DINS len mo)]
|
|
||||||
[(string-append "cut " s) (inverse-CNC len (string->number s) mo)]
|
|
||||||
[(string-append "deal with increment " s) (inverse-DWIN len (string->number s) mo)]))
|
|
||||||
|
|
||||||
(define (shuffle len)
|
(define (shuffle len)
|
||||||
(foldl (∂ parse len) I input))
|
(foldl (λ (T mo) (<> len (parse len T) mo)) I input))
|
||||||
|
|
||||||
(define (inverse-shuffle len)
|
(define (inverse-shuffle len)
|
||||||
(foldr (∂ inverse-parse len) I input))
|
(affine-invert (shuffle len) len))
|
||||||
|
|
||||||
(define part1
|
(define part1
|
||||||
(let ([len 10007])
|
(let ([len 10007])
|
||||||
|
|
|
@ -9,7 +9,7 @@
|
||||||
(string->program (car (problem-input 23))))
|
(string->program (car (problem-input 23))))
|
||||||
|
|
||||||
(define network
|
(define network
|
||||||
(build-vector 50 (λ (n) (resume-with-input (exec input) n))))
|
(build-vector 50 (λ (n) (resume-with-input (resume-with-input (exec input) n) -1))))
|
||||||
|
|
||||||
(define packets
|
(define packets
|
||||||
(build-vector 50 (λ (_) (make-queue))))
|
(build-vector 50 (λ (_) (make-queue))))
|
||||||
|
@ -32,7 +32,7 @@
|
||||||
(type-case state st
|
(type-case state st
|
||||||
[in (resume)
|
[in (resume)
|
||||||
(if (queue-empty? input)
|
(if (queue-empty? input)
|
||||||
(vector-set! network i (resume -1))
|
(void)
|
||||||
(let* ([x (dequeue! input)]
|
(let* ([x (dequeue! input)]
|
||||||
[y (dequeue! input)]
|
[y (dequeue! input)]
|
||||||
[st (resume-with-input (resume x) y)])
|
[st (resume-with-input (resume x) y)])
|
||||||
|
|
Loading…
Reference in New Issue