diff --git a/src/2024/day02.lisp b/src/2024/day02.lisp new file mode 100644 index 0000000..d622965 --- /dev/null +++ b/src/2024/day02.lisp @@ -0,0 +1,61 @@ + +(defpackage :aoc/2024/02 + (:use :cl :aoc :alexandria) + (:export + #:sample-data + #:part1 + #:part2 + #:deltas + #:safe-levels + #:safe-levels-with-dampener + )) + +(in-package :aoc/2024/02) + + +(defun parse-line (s) + (map 'list #'parse-integer (cl-ppcre:split " " s))) + +(defvar input-data '()) +(setf input-data (map 'list #'parse-line (test-input 2024 2))) + +(defvar sample-text "") +(setf sample-text (aoc:split-lines "7 6 4 2 1 +1 2 7 8 9 +9 7 6 2 1 +1 3 2 4 5 +8 6 4 4 1 +1 3 6 7 9 +")) + +(defvar sample-data '()) +(setf sample-data (map 'list #'parse-line sample-text)) + +(defun deltas (levels) + (map 'list #'- (subseq levels 1) levels)) + +(defun safe-levels (levels) + (let ((ds (deltas levels))) + (and + (or (every #'plusp ds) (every #'minusp ds)) + (every (lambda (d) (>= 3 (abs d))) ds)))) + +(defun remove-nth (n xs) + (append (subseq xs 0 (1- n)) (nthcdr n xs))) + +(defun safe-levels-with-dampener (levels) + (or (safe-levels levels) + (loop for n from 1 to (length levels) + thereis (safe-levels (remove-nth n levels))))) + +(defun part1 (data) + (loop for report in data + count (safe-levels report))) + +(defun part2 (data) + (loop for report in data + count (safe-levels-with-dampener report))) + +(defun solve-day () + (format t "part1: ~A~%" (part1 input-data)) + (format t "part2: ~A~%" (part2 input-data))) diff --git a/tests/2024/day02-test.lisp b/tests/2024/day02-test.lisp new file mode 100644 index 0000000..7e6137f --- /dev/null +++ b/tests/2024/day02-test.lisp @@ -0,0 +1,41 @@ +(defpackage :aoc/2024/02/tests + (:use :cl :aoc :aoc/tests :aoc/2024/tests :parachute :aoc/2024/02)) + +(in-package :aoc/2024/02/tests) + +(define-test suite-2024-02 + ;:parent suite-2024 + ) + +(define-test+run test-deltas + :parent suite-2024-02 + (true (equalp '(1 1 1) (deltas '(1 2 3 4))))) + +(define-test+run test-safe-levels + :parent suite-2024-02 + (true (safe-levels '(7 6 4 2 1))) ; Safe because the levels are all decreasing by 1 or 2. + (false (safe-levels '(1 2 7 8 9))) ; Unsafe because 2 7 is an increase of 5. + (false (safe-levels '(9 7 6 2 1))) ; Unsafe because 6 2 is a decrease of 4. + (false (safe-levels '(1 3 2 4 5))) ; Unsafe because 1 3 is increasing but 3 2 is decreasing. + (false (safe-levels '(8 6 4 4 1))) ; Unsafe because 4 4 is neither an increase or a decrease. + (true (safe-levels '(1 3 6 7 9))) ; Safe because the levels are all increasing by 1, 2, or 3. + ) + +(define-test+run test-safe-levels-with-dampener + :parent suite-2024-02 + (true (safe-levels-with-dampener '(7 6 4 2 1))) + (false (safe-levels-with-dampener '(1 2 7 8 9))) + (false (safe-levels-with-dampener '(9 7 6 2 1))) + (true (safe-levels-with-dampener '(1 3 2 4 5))) + (true (safe-levels-with-dampener '(8 6 4 4 1))) + (true (safe-levels-with-dampener '(1 3 6 7 9))) + ) +(define-test+run test-part1 + :parent suite-2024-02 + (true (equalp 2 (part1 sample-data)))) + +(define-test+run test-part2 + :parent suite-2024-02 + (true (equalp 31 (part2 sample-data)))) + +