aboutsummaryrefslogtreecommitdiff
path: root/2024/11/puzzles.lisp
blob: 7d44a0b79d03233c35bd7a62cfe0373299c836fa (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#!/usr/bin/sbcl --script

(defparameter *memo* (make-hash-table :test 'equal))

(defun main (filename blink-count)
  (loop for stone in (read-stones filename)
        sum (count-stones stone blink-count)))

(defun read-stones (filename)
  (with-open-file (stream filename)
    (let ((contents (make-string (file-length stream))))
      (read-sequence contents stream)
      (read-from-string (concatenate 'string "(" contents ")")))))

(defun count-stones (stone blink-count)
  (let ((stone+blink-count (cons stone blink-count)))
    (or (gethash stone+blink-count *memo*)
        (setf (gethash stone+blink-count *memo*)
              (cond ((minusp (decf blink-count))
                     1)
                    ((zerop stone)
                     (count-stones 1 blink-count))
                    ((evenp (integer-digit-count stone))
                     (multiple-value-bind (hi lo) (integer-split stone)
                       (+ (count-stones hi blink-count)
                          (count-stones lo blink-count))))
                    (:else
                      (count-stones (* 2024 stone) blink-count)))))))

(defun integer-digit-count (x)
  (1+ (truncate (log x 10))))

(defun integer-split (x)
  (floor x (expt 10 (floor (integer-digit-count x) 2))))

;; START PART 1
(format t "~d~%" (main "input" 25))
;; END PART 1 START PART 2
(format t "~d~%" (main "input" 75))
;; END PART 2