advent-of-code-2023

My solutions to AoC 2023
git clone git://git.entf.net/advent-of-code-2023
Log | Files | Refs

commit 2b2d4b999710dc9b7dd4dda4d89a5f6be7a9d463
parent aa1d772fe2bde98f3b0f6d3e56417b194b771f59
Author: Lukas Henkel <lh@entf.net>
Date:   Fri, 15 Dec 2023 06:43:02 +0100

Day 15 task 2

Diffstat:
Msrc/day-15.lisp | 73+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++--------------
Mt/day-15.lisp | 5+++--
2 files changed, 62 insertions(+), 16 deletions(-)

diff --git a/src/day-15.lisp b/src/day-15.lisp @@ -3,18 +3,63 @@ (:export #:day-15)) (in-package #:aoc/day-15) -(defun day-15 (input) - (loop with sum = 0 - with current = 0 - for char = (read-char input nil) - while char +(defun next-element (input) + (let ((next (loop for char = (read-char input nil) + while (and char (char/= char #\,)) + when (char/= #\Newline) + collect char))) + (when next + (coerce next 'string)))) + +(defun calculate-hash (element) + (loop with current = 0 + for char across element + do (progn + (incf current (char-code char)) + (setf current (* current 17)) + (setf current (rem current 256))) + finally (return current))) + +(defun parse-element (element) + (loop for char across element + for i from 0 do (cond - ((char= char #\,) - (incf sum current) - (setf current 0)) - ((char= char #\Newline)) - (t - (incf current (char-code char)) - (setf current (* current 17)) - (setf current (rem current 256)))) - finally (return (+ sum current)))) + ((char= char #\-) + (return (list (subseq element 0 i) :remove))) + ((char= char #\=) + (return (list (subseq element 0 i) + (parse-integer element :start (1+ i)))))))) + +(defun total-focusing-power (boxes) + (loop for lenses across boxes + for box from 1 + sum (loop for lens in lenses + for slot from 1 + sum (* box slot (second lens))))) + +(defun day-15 (input) + (loop with boxes = (make-array 256 :initial-element nil) + for element = (next-element input) + while element + for parsed-element = (parse-element element) + for box = (calculate-hash (first parsed-element)) + do (setf (aref boxes box) + (if (eq (second parsed-element) :remove) + (remove (first parsed-element) + (aref boxes box) + :test #'equal + :key #'first) + (let* ((box-content (aref boxes box)) + (existing (find (first parsed-element) + box-content + :test #'equal + :key #'first))) + (if existing + (progn + (setf (second existing) (second parsed-element)) + box-content) + (nconc box-content + (list parsed-element)))))) + sum (claculate-hash element) into task-1 + finally (return (values task-1 + (total-focusing-power boxes))))) diff --git a/t/day-15.lisp b/t/day-15.lisp @@ -4,6 +4,7 @@ (define-test test-day-15 () - (multiple-value-bind (task-1) + (multiple-value-bind (task-1 task-2) (aoc:run-day 15 "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7") - (assert= 1320 task-1))) + (assert= 1320 task-1) + (assert= 145 task-2)))