refactored and simplified

runs somewhat slower but no need for caching anymore.
much more minimalist
This commit is contained in:
Peter Tillemans 2024-12-11 11:18:40 +01:00
parent b8810a97a5
commit eb8c2226f7
2 changed files with 8 additions and 54 deletions

View file

@ -17,7 +17,6 @@
(defun parse-line (line) (defun parse-line (line)
(mapcar #'parse-integer (cl-ppcre:split " " line))) (mapcar #'parse-integer (cl-ppcre:split " " line)))
(defun parse-input (lines) (defun parse-input (lines)
(parse-line lines)) (parse-line lines))
@ -28,31 +27,20 @@
(defparameter sample-data (defparameter sample-data
(parse-input sample-text)) (parse-input sample-text))
(defun n-digits (x) (defun n-digits (x)
(ceiling (log (1+ x) 10))) (ceiling (log (1+ x) 10)))
(defun evolve-stone (stone) (defun evolve-stone (stone)
(let* ((n (n-digits stone)) (let* ((n (n-digits stone)))
(split-factor (expt 10 (/ n 2))))
(cond (cond
((= 0 stone) (list 1)) ((= 0 stone) (list 1))
((evenp n) (list ((evenp n) (let ((split-factor (expt 10 (/ n 2))))
(list
(floor (/ stone split-factor)) (floor (/ stone split-factor))
(mod stone split-factor))) (mod stone split-factor))))
(t (list (* 2024 stone))))) (t (list (* 2024 stone)))))
) )
(defun merge-stone-map (map1 map2 &optional (multiplier 1))
(let ((result (copy-hash-table map1)))
(loop
for k being the hash-keys of map2
for v being the hash-values of map2
do (incf (gethash k result 0) (* v multiplier)))
result))
(defun stones-to-stone-map (stones) (defun stones-to-stone-map (stones)
(let ((result (make-hash-table :size (length stones)))) (let ((result (make-hash-table :size (length stones))))
(loop (loop
@ -63,22 +51,14 @@
(defun total-stones (stone-map) (defun total-stones (stone-map)
(loop for v being the hash-values of stone-map sum v)) (loop for v being the hash-values of stone-map sum v))
(defparameter stone-map-cache (make-hash-table :size 1000))
(defun map-stone (stone)
(let ((rslt (gethash stone stone-map-cache)))
(or rslt
(let ((stones (evolve-stone stone))
(stone-map (make-hash-table)))
(loop for s in stones
do (incf (gethash s stone-map 0)))
(setf (gethash stone stone-map-cache) stone-map)))))
(defun evolve-stone-map (stone-map) (defun evolve-stone-map (stone-map)
(let ((result (make-hash-table :size 1000))) (let ((result (make-hash-table :size 1000)))
(loop (loop
for k being the hash-keys of stone-map for k being the hash-keys of stone-map
for v being the hash-values of stone-map for v being the hash-values of stone-map
do (setf result (merge-stone-map result (map-stone k) v))) do (loop
for s in (evolve-stone k)
do (incf (gethash s result 0) v)))
result)) result))
(defun evolve-stone-map-n (stone-map n) (defun evolve-stone-map-n (stone-map n)
@ -94,7 +74,6 @@
(defun part2 (data) (defun part2 (data)
(format nil "~A" (total-stones (evolve-stone-map-n (stones-to-stone-map data) 75)))) (format nil "~A" (total-stones (evolve-stone-map-n (stones-to-stone-map data) 75))))
(defun solve-day () (defun solve-day ()
(format t "part1: ~A~%" (part1 input-data)) (format t "part1: ~A~%" (part1 input-data))
(format t "part2: ~A~%" (part2 input-data))) (format t "part2: ~A~%" (part2 input-data)))

View file

@ -12,37 +12,12 @@
(is equal '(125 17) (parse-line "125 17")) (is equal '(125 17) (parse-line "125 17"))
) )
(defparameter example-evolution
'((125 17)
(253000 1 7)
(253 0 2024 14168)
(512072 1 20 24 28676032)
(512 72 2024 2 0 2 4 2867 6032)
(1036288 7 2 20 24 4048 1 4048 8096 28 67 60 32)
(2097446912 14168 4048 2 0 2 4 40 48 2024 40 48 80 96 2 8 6 7 6 0 3 2)))
(define-test test-evolve-stone (define-test test-evolve-stone
:parent suite-2024-11 :parent suite-2024-11
(is equal '(1) (evolve-stone 0)) (is equal '(1) (evolve-stone 0))
(is equal '(9 9) (evolve-stone 99)) (is equal '(9 9) (evolve-stone 99))
(is equal '(2024) (evolve-stone 1))) (is equal '(2024) (evolve-stone 1)))
(define-test test-evolve-stones
:parent suite-2024-11
(loop
for case in example-evolution
for expected in (subseq example-evolution 1)
do (is equal expected (evolve-stones case)) )
)
(define-test+run test-part1 (define-test+run test-part1
:parent suite-2024-11 :parent suite-2024-11
(is equal "55312" (part1 sample-data))) (is equal "55312" (part1 sample-data)))
(define-test+run test-part2
:parent suite-2024-11
(is equal nil (part2 sample-data)))