(defpackage #:advent.2024.07 (:use #:cl #:advent.2024.00)) (in-package #:advent.2024.07) ;;; Part 1. ;; Using + and *, find which test values (before the colon) can be solved with ;; the remaining numbers. Add valid test values to get the answer. (defvar *example* "190: 10 19 3267: 81 40 27 83: 17 5 156: 15 6 7290: 6 8 6 15 161011: 16 10 13 192: 17 8 14 21037: 9 7 18 13 292: 11 6 16 20") (defun parse-string (str) (loop for line in (uiop:split-string str :separator '(#\newline)) for numbers = (ppcre:split ":?\\s+" line) collect (mapcar #'parse-integer numbers))) (defun compute1 (nums ops) (reduce (lambda (a b) (funcall (pop ops) a b)) nums)) (defun enumerate-oplists (length) (cond ((zerop length) ()) ((= length 1) '((+) (*))) (t (flet ((num->oplist (n) (loop for op across (map 'vector (alexandria:compose #'parse-integer #'string) (format nil "~v,'0b" length n)) collect (case op (0 '+) (1 '*))))) (loop for n from 0 to (1- (expt 2 length)) collect (num->oplist n)))))) (defun valid? (nums) (let ((oplen (- (length nums) 2))) (loop for ops in (enumerate-oplists oplen) if (= (car nums) (compute1 (cdr nums) ops)) return (car nums) finally (return 0)))) (defun solve1 (&optional (input (input))) (loop for line in (parse-string (uiop:read-file-string input)) sum (valid? line))) ;;; Part 2. A THIRD TYPE OF OPERATOR! ;; The third op, ||, combines the digits from the left and right inputs into a ;; single number --- e.g. 12 || 345 -> 12345. (defun enumerate-oplists2 (length) (flet ((num->oplist (n) (loop for op across (map 'vector (alexandria:compose #'parse-integer #'string) (format nil "~3,v,'0R" length n)) collect (case op (0 '+) (1 '*) (2 'glom))))) ; || (loop for n from 0 to (1- (expt 3 length)) collect (num->oplist n)))) (defun glom (a b) (parse-integer (format nil "~D~D" a b))) (defun valid2? (nums) (let ((oplen (- (length nums) 2))) (loop for ops in (enumerate-oplists2 oplen) if (= (car nums) (compute1 (cdr nums) ops)) return (car nums) finally (return 0)))) (defun solve2 (&optional (input (input))) (loop for line in (parse-string (uiop:read-file-string input)) sum (valid2? line))) ;;; This is taking a lot longer to run --- more operations to run through.. as ;;; it goes I should say that I *could've*, and probably *should've*, rewritten ;;; all the non-2 functions to be more general, then passed in the specifics ;;; with the solve(1,2) ... but whatever.