blob: dc1f2c74fc6cc5779c41285443e2d3ad7813197c (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
|
(ql:quickload '(fiveam uiop))
(defparameter *msg* #(1 2 -3 3 -2 0 4))
(defun directional-pointers (size)
(let ((forward (make-array size))
(reverse (make-array size)))
(dotimes (i size)
(setf (svref forward i) (mod (1+ i) size)
(svref reverse i) (mod (1- i) size)))
(values forward reverse)))
(defun follow-pointer (pointer index count)
(if (zerop count)
index
(follow-pointer pointer (svref pointer index) (1- count))))
(defun move! (forward reverse element-idx shift)
"FORWARD is the leading array, not necessarily forward movement"
(let ((next-element (svref forward element-idx))
(prev-element (svref reverse element-idx)))
;; remove element from sequence
(setf (svref reverse next-element) prev-element)
(setf (svref forward prev-element) next-element))
(let* ((amount (1+ (mod (1- shift) (1- (length forward)))))
(target-index (follow-pointer forward element-idx amount)))
(psetf (svref reverse element-idx) target-index
(svref reverse (svref forward target-index)) element-idx
(svref forward element-idx) (svref forward target-index)
(svref forward target-index) element-idx))
(values forward reverse))
(defun shuffle! (forward reverse element-idx shift)
(cond
((zerop shift))
((plusp shift)
(move! forward reverse element-idx shift))
((move! reverse forward element-idx (abs shift))))
(values forward reverse))
(defun shuffle-pointers (msg repeat)
(multiple-value-bind (forward reverse) (directional-pointers (length msg))
(dotimes (_ repeat)
(dotimes (element-idx (length msg))
;; (format t "st: ~a f: ~a r: ~a~%" (ordered-series msg forward) forward reverse)
(shuffle! forward reverse element-idx (svref msg element-idx))))
(values forward reverse)))
(defun ordered-series (msg forward)
(let* ((len (length msg))
(series (make-array len)))
(do ((i (position 0 msg) (svref forward i))
(count 0 (1+ count)))
((<= len count) series)
(setf (svref series count)
(svref msg i)))))
(defun solver (repeat message)
(let ((new-array
(ordered-series message (shuffle-pointers message repeat))))
(+
(svref new-array (mod 1000 (length new-array)))
(svref new-array (mod 2000 (length new-array)))
(svref new-array (mod 3000 (length new-array))))))
(defun times-decrypt-key (msg)
(map 'vector (lambda (x) (* 811589153 x)) msg))
(fiveam:test solutions
(fiveam:is (= 3 (solver 1 *msg*)))
(fiveam:is (= 1623178306 (solver 10 (times-decrypt-key *msg*))))
(let ((input-msg (map 'vector #'parse-integer (uiop:read-file-lines "input"))))
(fiveam:is (= 7225 (solver 1 input-msg)))
(fiveam:is (= 548634267428 (solver 10 (times-decrypt-key input-msg))))))
|