(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))))))