day-15.lisp (2486B)
1 (defpackage #:aoc/day-15 2 (:use #:cl #:aoc/utils) 3 (:export #:day-15)) 4 (in-package #:aoc/day-15) 5 6 (defun next-element (input) 7 (let ((next (loop for char = (read-char input nil) 8 while (and char (char/= char #\,)) 9 when (char/= #\Newline) 10 collect char))) 11 (when next 12 (coerce next 'string)))) 13 14 (defun calculate-hash (element) 15 (loop with current = 0 16 for char across element 17 do (progn 18 (incf current (char-code char)) 19 (setf current (* current 17)) 20 (setf current (rem current 256))) 21 finally (return current))) 22 23 (defun parse-element (element) 24 (loop for char across element 25 for i from 0 26 do (cond 27 ((char= char #\-) 28 (return (list (subseq element 0 i) :remove))) 29 ((char= char #\=) 30 (return (list (subseq element 0 i) 31 (parse-integer element :start (1+ i)))))))) 32 33 (defun total-focusing-power (boxes) 34 (loop for lenses across boxes 35 for box from 1 36 sum (loop for lens in lenses 37 for slot from 1 38 sum (* box slot (second lens))))) 39 40 (defun day-15 (input) 41 (loop with boxes = (make-array 256 :initial-element nil) 42 for element = (next-element input) 43 while element 44 for parsed-element = (parse-element element) 45 for box = (calculate-hash (first parsed-element)) 46 do (setf (aref boxes box) 47 (if (eq (second parsed-element) :remove) 48 (remove (first parsed-element) 49 (aref boxes box) 50 :test #'equal 51 :key #'first) 52 (let* ((box-content (aref boxes box)) 53 (existing (find (first parsed-element) 54 box-content 55 :test #'equal 56 :key #'first))) 57 (if existing 58 (progn 59 (setf (second existing) (second parsed-element)) 60 box-content) 61 (nconc box-content 62 (list parsed-element)))))) 63 sum (calculate-hash element) into task-1 64 finally (return (values task-1 65 (total-focusing-power boxes)))))