1(defpackage #:advent.2024.03
2 (:use #:cl))
3(in-package #:advent.2024.03)
4
5(defvar *input* "03.input")
6
7;;; Part 1
8;; parse a file for mul(\d\d?\d?,\d\d?\d?), multiply the numbers, then add the results
9
10(defun solve1 ()
11 (let ((in (uiop:read-file-string *input*)))
12 (solve1/string in)))
13
14(defvar *mul-regex* "mul\\((\\d\\d?\\d?),(\\d\\d?\\d?)\\)")
15
16(defun solve1/string (in)
17 (let ((sum 0))
18 (ppcre:do-scans (ms me rs re "mul\\((\\d\\d?\\d?),(\\d\\d?\\d?)\\)" in sum)
19 ;; (format t "~A/~A || ~A/~A~&" ms me rs re)
20 (let ((a (parse-integer in :start (elt rs 0) :end (elt re 0)))
21 (b (parse-integer in :start (elt rs 1) :end (elt re 1))))
22 (incf sum (* a b)))
23 sum)))
24
25;;; Part 2
26;; start with mul() enabled; on don't(), disable it; on do(), enable. add only
27;; enabled mul()s.
28
29(defvar *do-regex* "do\\(\\)")
30(defvar *dont-regex* "don't\\(\\)")
31
32;; I get to do this the long way round
33
34(defun solve2 ()
35 (let ((s (uiop:read-file-string *input*)))
36 (solve2/string s)))
37
38(defun solve2/string (in)
39 (let ((mulp t)
40 (sum 0))
41 (cl-ppcre:do-matches-as-strings (m (format nil "~A|~A|~A" *mul-regex*
42 *dont-regex* *do-regex*)
43 in sum)
44 (cond
45 ((and (ppcre:scan *mul-regex* m)
46 mulp)
47 (ppcre:do-register-groups (a b) ; this warning is .. fine???
48 (*mul-regex* m nil :sharedp t)
49 (incf sum (* (parse-integer a) (parse-integer b)))))
50 ((ppcre:scan *dont-regex* m)
51 (setf mulp nil))
52 ((ppcre:scan *do-regex* m)
53 (setf mulp t))))
54 sum))