1(defpackage #:advent.2024.02
2 (:use #:cl))
3(in-package #:advent.2024.02)
4
5(defvar *input* "02.input")
6
7;;; Part 1
8;; How many lines contain monotonically increasing or decreasing numbers that
9;; are all at least 1 and at most 3 apart?
10
11(defun parse (file)
12 (loop for line in (uiop:read-file-lines file)
13 collect (loop for num in (cl-ppcre:split "\\s+" line)
14 collect (read-from-string num))))
15
16(defun test-line (line)
17 (and (or (apply #'> line)
18 (apply #'< line))
19 (loop for (a b) on line
20 when (and a b (> (abs (- a b)) 3))
21 do (return nil)
22 finally (return t))))
23
24(defun solve-1 ()
25 (count-if #'test-line (parse *input*)))
26
27;;; Part 2
28;; How many lines meet 1's requirements when able to remove *one* element to
29;; meet them?
30
31(defvar *unsafe*
32 (remove-if #'test-line (parse *input*)))
33
34(defun generate-variations (list)
35 "Generate all variations of LIST with one element removed."
36 (loop for i from 0 to (1- (length list))
37 collect (remove-if (let ((j 0))
38 (lambda (x)
39 (declare (ignorable x))
40 (prog1 (= i j)
41 (incf j))))
42 list)))
43
44(defun solve-2 ()
45 (+ (solve-1)
46 (count-if (lambda (line)
47 (some #'test-line (generate-variations line)))
48 *unsafe*)))