commit 2b2d4b999710dc9b7dd4dda4d89a5f6be7a9d463
parent aa1d772fe2bde98f3b0f6d3e56417b194b771f59
Author: Lukas Henkel <lh@entf.net>
Date: Fri, 15 Dec 2023 06:43:02 +0100
Day 15 task 2
Diffstat:
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)))