Commit Diff


commit - aa1d772fe2bde98f3b0f6d3e56417b194b771f59
commit + 2b2d4b999710dc9b7dd4dda4d89a5f6be7a9d463
blob - ce0ae0e1a6843b66bc22373ae1acc6a325420774
blob + a8717ac512e4f6394dc8f319bfc4ddfb77f75be5
--- src/day-15.lisp
+++ 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)))))
blob - 1621a1f685edc8851c5f42c927912b7508770164
blob + 0f5c55ebaf04c15852bc21b6973c53a007a34807
--- t/day-15.lisp
+++ 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)))