(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)))