aboutsummaryrefslogtreecommitdiff
path: root/2024/puzzle-3.lisp
blob: cca2f432e9a7832198389b4fabc9bb1a4d53f4c2 (plain)
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
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
(load "util.lisp")

(defparameter input (uiop:read-file-string "3-input"))

(defun is-good-mul (str)
  (let* ((delimiter (search "," str))
         (end (search ")" str)))
    (if (or (null delimiter) (null end)
            (> delimiter end)
            (not (eq #\( (char str 3))))
        nil
        (let* ((first-arg (subseq str 4 delimiter))
               (second-arg (subseq str (1+ delimiter) end)))
          (and (every #'digit-char-p first-arg)
               (every #'digit-char-p second-arg))))))

(defun trim-mul (str)
  (subseq str 0 (1+ (search ")" str))))

(defun parse-mul (str)
  (let ((start (search "(" str))
        (middle (search "," str))
        (end (search ")" str)))
    (list (parse-integer (subseq str (1+ start) middle))
          (parse-integer (subseq str (1+ middle) end)))))

(defun parse-input-muls (line)
  (let ((possible (search-all "mul" line)))
    (--> (cdr possible)
         (append _ (list (length line)))
         (mapcar (lambda (z1 z2) (cons z1 (subseq line z1 z2))) possible _)
         (remove-if-not (lambda (x) (is-good-mul (cdr x))) _)
         (mapcar (lambda (x) (cons (car x) (trim-mul (cdr x)))) _)
         (mapcar (lambda (x) (cons (car x) (parse-mul (cdr x)))) _))))

(format t "Round 1: ~a~%"
        (loop for (pos x y) in (parse-input-muls input)
              sum (* x y)))

(defun parse-input-conds (input)
  (let ((dos (search-all "do()" input))
        (donts (search-all "don't()" input)))
    (cons
     '(do . 0)
     (sort (append (mapcar (lambda (x) (cons 'do x)) dos)
                   (mapcar (lambda (x) (cons 'dont x)) donts))
           (lambda (x y) (< (cdr x) (cdr y)))))))

(defun current-cond (pos conds)
  (caar (last (remove-if (lambda (x) (> (cdr x) pos)) conds))))

(format t "Round 2: ~a~%"
        (let ((conds (parse-input-conds input))
              (muls (parse-input-muls input)))
          (loop for (pos x y) in muls
                for current = (current-cond pos conds)
                if (eq current 'do)
                  sum (* x y))))