diff --git a/src/2024/day05.lisp b/src/2024/day05.lisp new file mode 100644 index 0000000..2217f7c --- /dev/null +++ b/src/2024/day05.lisp @@ -0,0 +1,125 @@ +(defpackage :aoc/2024/05 + (:use :cl :aoc :alexandria :trivia) + (:export + #:sample-data + #:sample-data2 + #:part1 + #:part2 + #:rule-okp + #:rules-okp + #:middle-page + #:apply-rule + #:sort-with-rules + )) + +(in-package :aoc/2024/05) + +(defun parse-rule (s) + (mapcar #'parse-integer (cl-ppcre:split "[|]" s))) + +(defun parse-book (s) + (mapcar #'parse-integer (cl-ppcre:split "," s))) + +(defun parse-input (lines) + (let ((sep (position "" lines :test #'equal))) + (list + (mapcar #'parse-rule (subseq lines 0 sep )) + (mapcar #'parse-book (subseq lines (1+ sep)))))) + + + (defvar input-data '()) +(setf input-data (parse-input (test-input 2024 5))) + +(defvar sample-text "") +(setf sample-text (aoc:split-lines "47|53 +97|13 +97|61 +97|47 +75|29 +61|13 +75|53 +29|13 +97|29 +53|29 +61|53 +97|53 +61|29 +47|13 +75|47 +97|75 +47|61 +75|61 +47|29 +75|13 +53|13 + +75,47,61,53,29 +97,61,53,29,13 +75,29,13 +75,97,47,61,53 +61,13,29 +97,13,75,29,47")) + + +(defvar sample-data '()) +(setf sample-data (parse-input sample-text)) + +(defun rule-okp (rule book) + (let ((a (or (position (first rule) book) -1)) + (b (or (position (second rule) book) 999))) + (< a b))) + + +(defun rules-okp (rules book) + (every (lambda (rule) (rule-okp rule book)) rules)) + +(defun middle-page (book) + (let ((mid (floor (/ (length book) 2)))) + (nth mid book))) + +(defun sum-middle-pages (data) + (let* ((rules (first data)) + (books (second data))) + (loop for book in books + if (rules-okp rules book) + sum (middle-page book)))) + +(defun part1 (data) + (format nil "~A" (sum-middle-pages data))) + +(defun apply-rule (book rule) + (let ((a (position (first rule) book)) + (b (position (second rule) book))) + (cond + ((not a) book) + ((not b) book) + ((< a b) + book) + (t (append (subseq book 0 b) + (subseq book a (1+ a)) + (subseq book b a) + (subseq book (1+ a)))) + ))) + +(defun sort-with-rules (rules book) + (let ((sorted-book (reduce #'apply-rule rules :initial-value book))) + (if (equal sorted-book book) + book + (sort-with-rules rules sorted-book)))) + +(defun fixed-books (data) + (let ((rules (first data)) + (books (second data))) + (loop for book in books + if (not (rules-okp rules book)) + collect (sort-with-rules rules book)))) + +(defun part2 (data) + (let ((s (loop for book in (fixed-books data) + sum (middle-page book)))) + (format nil "~A" s))) + +(defun solve-day () + (format t "part1: ~A~%" (part1 input-data)) + (format t "part2: ~A~%" (part2 input-data))) + diff --git a/tests/2024/day05-test.lisp b/tests/2024/day05-test.lisp new file mode 100644 index 0000000..ec68415 --- /dev/null +++ b/tests/2024/day05-test.lisp @@ -0,0 +1,31 @@ +(defpackage :aoc/2024/05/tests + (:use :cl :aoc :aoc/tests :aoc/2024/tests :parachute :aoc/2024/05)) + +(in-package :aoc/2024/05/tests) + +(define-test suite-2024-05 + ;:parent suite-2024 + ) + +(define-test test-middle-page + :parent suite-2024-05 + (is = 61 (middle-page (75 47 61 53 29))) + ) + + +(define-test test-order-pages + :parent suite-2025-05 + (is equalp (sort-with-rules rules '(75 97 47 61 53)) '(97 75 47 61 53)) + (is equalp (sort-with-rules rules '(61 13 29)) '(61 29 13)) + (is equalp (sort-with-rules rule '(97 13 75 29 47)) '(97 75 47 29 13))) + + +(define-test+run test-part1 + :parent suite-2024-05 + (true (equalp "143" (part1 sample-data)))) + +(define-test+run test-part2 + :parent suite-2024-05 + (true (equalp nil (part2 sample-data2)))) + +