advent-of-code-2024

My solutions to AoC 2024
Log | Files | Refs

commit 5ebe82fbf80d12d57735a7ddd314db7ecc3e132f
parent be08f67cded6e0367aeb15c08edd637f31e98965
Author: Lukas Henkel <lh@entf.net>
Date:   Mon,  2 Dec 2024 12:56:40 +0100

Optimize

Diffstat:
Msrc/day-2.lisp | 45++++++++++++++++++++++-----------------------
Mt/day-2.lisp | 8++++++++
2 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/src/day-2.lisp b/src/day-2.lisp @@ -3,36 +3,35 @@ (:export #:day-2)) (in-package #:aoc/day-2) -(defun report-safe-p (report) - (loop with dir = (if (> (first report) (second report)) #'> #'<) - with last = (first report) - for current in (cdr report) - for diff = (abs (- last current)) - unless (funcall dir last current) - do (return nil) - unless (<= diff 3) - do (return nil) - do (setf last current) +(defun report-safe-p (report &key direction allow-skip) + (when (null direction) + (return-from report-safe-p + (or (report-safe-p report :direction #'< :allow-skip allow-skip) + (report-safe-p report :direction #'> :allow-skip allow-skip)))) + (when (null (cdr report)) + (return-from report-safe-p t)) + (loop with last = nil + for cdr on report + until (null (cdr cdr)) + for left = (car cdr) + for right = (cadr cdr) + for diff = (abs (- left right)) + for cdir = (funcall direction left right) + unless (and cdir (<= diff 3)) + do (return (when allow-skip + (or (report-safe-p (cons left (cddr cdr)) :direction direction) + (if (null last) + (report-safe-p (cdr cdr) :direction direction) + (report-safe-p (cons (car last) (cdr cdr)) :direction direction))))) + do (setf last cdr) finally (return t))) -(defun remove-nth (n list) - (concatenate 'list - (subseq list 0 n) - (subseq list (1+ n)))) - -(defun report-somewhat-safe-p (report) - (or (report-safe-p report) - (loop for i from 0 below (length report) - for nr = (remove-nth i report) - when (report-safe-p nr) - do (return t)))) - (defun day-2 (input) (loop for line = (read-line input nil) until (null line) for report = (read-number-list line) when (report-safe-p report) sum 1 into task-1 - when (report-somewhat-safe-p report) + when (report-safe-p report :allow-skip t) sum 1 into task-2 finally (return (values task-1 task-2)))) diff --git a/t/day-2.lisp b/t/day-2.lisp @@ -4,6 +4,14 @@ (define-test test-day-2 () + ;;; Test resets + ;; Report where the first item needs to be skipped + (assert (aoc/day-2::report-safe-p (list 30 24 25 28 31 33 35) :allow-skip t)) + ;; Report where the second item needs to be skipped + (assert (aoc/day-2::report-safe-p (list 24 21 25 28 31 33 35) :allow-skip t)) + ;; Report where reset target needs to be removed + (assert (aoc/day-2::report-safe-p (list 25 22 19 21 20 17 14 13) :allow-skip t)) + ;;; Test task 1 & 2 (multiple-value-bind (task-1 task-2) (aoc:run-day 2 "7 6 4 2 1 1 2 7 8 9