Tuesday, February 18, 2025

Advent of Code 2024: Day 7

You don’t have to use named-lets for tail recursive loops. You can use them for any recursive function. Here is an example of a named let that computes the factorial of 5:

(let fact ((n 5))
  (if (= n 0)
      1
      (* n (fact (- n 1)))))

Day 7 is an unremarkable puzzle. On each line of input we are given a target number and some terms. We work on the terms from left to right and we can add the next term or multiply by it. We are to sum the target numbers which can be identified as a result of some combination of adding and multiplying.

;;; -*- Lisp -*-

(in-package "ADVENT2024/DAY7")

(defun can-satisfy? (target ops terms)
  (let recur ((accum (first terms))
              (terms (rest terms)))
       (cond ((and (> accum target)
                   (not (find-if #’zerop terms)))
              nil)
             ((consp terms)
              (find-if
               (lambda (op)
                 (recur (funcall op accum (first terms)) (rest terms)))
               ops))
             ((null terms) (= target accum))
             (t (error "Dotted list.")))))

(defun parse-integer-list (str)
  (map ’list #’parse-integer (str:split #\Space str :omit-nulls t)))

(defun parse-line (str)
  (let ((key+value (str:split #\: str)))
    (cons (parse-integer (first key+value))
          (parse-integer-list (second key+value)))))

(defun puzzle (ops)
  (collect-sum
    (let* ((equations
             (#Mparse-line
              (scan-file (input-pathname) #’read-line)))
           (satisfied (#M(lambda (equation)
                           (can-satisfy? (car equation) ops (cdr equation)))
                         equations)))
      (#Mcar (choose satisfied equations)))))

(defun part-1 ()
  (puzzle (list #’+ #’*)))

Part two allows us to concatenate the digits in addition to muliplying or adding.

(defun concatenate-digits (left right)
  (+ (* left (expt 10 (1+ (integer-log right 10))))
     right))

(defun part-2 ()
  (puzzle (list #’+ #’* #’concatenate-digits)))

2 comments:

Leah Neukirchen said...

Day 7 is more fun (and faster) to solve backwards, trying to get from the result to the first digit.

Joe Marshall said...

My solutions aren't the only way (or the best way) to solve the problems, they are just a way.