aoc/2021/09/09.lisp

68 lines
2.0 KiB
Common Lisp

(load (merge-pathnames "../common.lisp" *load-truename*))
(defconstant test-data
'("35"
"20"
"15"
"25"
"47"
"40"
"62"
"55"
"65"
"95"
"102"
"117"
"150"
"182"
"127"
"219"
"299"
"277"
"309"
"576"))
(defun parse-input (data)
(make-array (length data) :initial-contents (mapcar #'parse-integer data)))
(defun check-xmas (data &key (preamble 25))
(loop named top
for x from preamble to (length data)
do (loop named check for i from (- x preamble) to x
do (loop for j from (- x preamble) to x
do (when (and (not (= (aref data i) (aref data j)))
(= (+ (aref data i) (aref data j))
(aref data x)))
(return-from check)))
finally (return-from top (values (aref data x) x)))))
(defun part1 (input &key (preamble 25))
(check-xmas input :preamble preamble))
(defun biggest-consecutives (target data)
(loop named top
for i from 0 to (- (length data) 2)
do (loop named check
for j from 1 to (1- (length data))
with sum = (aref data i)
do (progn
(setf sum (+ sum (aref data (+ i j))))
(cond
((= target sum) (return-from top (subseq data i (+ i j))))
((< target sum) (return-from check NIL)))))))
(defun part2 (input &key (preamble 25))
(let* ((consecutives (multiple-value-bind (value i) (check-xmas input :preamble preamble)
(biggest-consecutives value input)))
(sub (map 'list #'identity consecutives)))
(+ (apply #'min sub)
(apply #'max sub))))
(let ((data (parse-input test-data)))
(assert (= 127 (part1 data :preamble 5)))
(assert (= 62 (part2 data :preamble 5))))
(let ((input (parse-input (read-data))))
(format t "Part 1: ~A~%" (part1 input))
(format t "Part 2: ~A~%" (part2 input)))