If you have a lisp installation, emacs, org-mode, and org-babel support for lisp installed you can run this by:
- Starting slime (
M-x slime
) - Typing
C-c C-c
in the block initialize. - In the repl type
(in-package :aoc-2022-20)
- Typing
C-c C-c
in the block answers
(unless (find-package :priority-queue)
(ql:quickload "priority-queue"))
(unless (find-package :cl-ppcre)
(ql:quickload "cl-ppcre"))
(unless (find-package :parseq)
(ql:quickload "parseq"))
(unless (find-package :lparallel)
(ql:quickload "lparallel"))
(unless (find-package :fiveam)
(ql:quickload "fiveam"))
(unless (find-package :series)
(ql:quickload "series"))
(unless (find-package :cl-permutation)
(ql:quickload "cl-permutation"))
(unless (find-package :bordeaux-threads)
(ql:quickload "bordeaux-threads"))
<<packages>>
(defpackage :aoc-2022-20
(:use :common-lisp
:parseq
:fiveam)
(:export :problem-a
:problem-b))
(in-package :aoc-2022-20)
(defun process-stream (in)
(loop for line = (read-line in nil)
while line
collect (parse-integer line)))
(defun read-input (file)
(with-open-file (in file)
(process-stream in)))
(defparameter *input*
(read-input "input/20.txt"))
(defun mix (numbers)
(let ((table (make-array (length numbers) :initial-contents numbers))
(sequence (loop for i from 0 below (length numbers) collect i)))
(setf (cdr (last sequence)) sequence)
(loop for i from 0 below (length table)
for previous = (loop for pos on sequence
until (= (cadr pos) i)
finally (return pos))
for element = (cdr previous)
for value = (aref table (car element))
for shift-by = (mod value (1- (length table)))
for new-previous = (nthcdr shift-by element)
unless (zerop (mod value (1- (length table))))
do (setf (cdr previous) (cdr element)) ;; remove the number
(psetf (cdr new-previous) element
(cdr element) (cdr new-previous)))
(let* ((zero (position 0 table))
(start (loop for pos on sequence
until (= (car pos) zero)
finally (return pos))))
(+ (aref table (elt start 1000))
(aref table (elt start 2000))
(aref table (elt start 3000))))))
(defun problem-a () (format t "Problem 20 A: ~a~%" (mix *input*)))
(defun mix-decrypt (numbers &key (decryption-key 811589153) (cycles 10))
(let ((table (make-array (length numbers) :initial-contents numbers))
(sequence (loop for i from 0 below (length numbers) collect i)))
(loop for i from 0 below (length table)
for n across table
do (setf (aref table i) (* decryption-key n)))
(setf (cdr (last sequence)) sequence)
(loop repeat cycles
do (loop for i from 0 below (length table)
for previous = (loop for pos on sequence
until (= (cadr pos) i)
finally (return pos))
for element = (cdr previous)
for value = (aref table (car element))
for shift-by = (mod value (1- (length table)))
for new-previous = (nthcdr shift-by element)
unless (zerop shift-by)
do (shiftf (cdr previous) (cdr element)
(cdr new-previous) element)))
(let* ((zero (position 0 table))
(start (loop for pos on sequence
until (= (car pos) zero)
finally (return pos))))
(+ (aref table (elt start 1000))
(aref table (elt start 2000))
(aref table (elt start 3000))))))
(defun problem-b () (format t "Problem 20 B: ~a~%" (mix-decrypt *input*)))
<<read-input>>
<<input>>
<<initialize>>
<<structs>>
<<functions>>
<<input>>
<<problem-a>>
<<problem-b>>
(problem-a)
(problem-b)
Problem 20 A: 19559 Problem 20 B: 912226207972
(def-suite aoc.2022.20)
(in-suite aoc.2022.20)
(run! 'aoc.2022.20)