68 lines
2.0 KiB
Common 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)))
|