(defun split-by-char (char string) (loop for i = 0 then (1+ j) as j = (position char string :start i) collect (subseq string i j) while j)) (defun read-seq (filespec) (with-open-file (stream filespec) (split-by-char #\, (read-line stream)))) (defun hash-algorithm (str) (let ((res 0)) (loop for c across str do (setf res (mod (* 17 (+ res (char-code c))) 256))) res)) (defun solve1 (filespec) (reduce #'+ (mapcar #'hash-algorithm (read-seq filespec)))) (defun solve2 (filespec) (let ((seq (read-seq filespec)) (boxes (make-array 256 :initial-element ()))) (loop for str in seq as symbp = (loop for c across str for i from 0 if (or (equal c #\-) (equal c #\=)) return i) as symb = (aref str symbp) as label = (subseq str 0 symbp) as hash = (hash-algorithm label) if (equal symb #\=) do (let* ((value (parse-integer (subseq str (1+ symbp)))) (box (aref boxes hash)) (lmember (assoc label box :test 'equal))) (if lmember (setf (cdr lmember) value) (setf (aref boxes hash) (acons label value box)))) else do (setf (aref boxes hash) (remove-if (lambda (a) (equal label (car a))) (aref boxes hash) :count 1))) (loop for box across boxes for i from 1 sum (loop for lens in (reverse box) for j from 1 sum (* i j (cdr lens)))))) (print (solve1 "data/15/example.txt")) ;; 1320 (print (solve1 "data/15/input.txt")) ;; 516804 (print (solve2 "data/15/example.txt")) ;; 145 (print (solve2 "data/15/input.txt")) ;; 231844