51 lines
1.5 KiB
Common Lisp
51 lines
1.5 KiB
Common Lisp
(load "util.lisp")
|
|
|
|
(defpackage "aoc:5"
|
|
(:use :cl "aoc-util"))
|
|
|
|
(in-package "aoc:5")
|
|
|
|
(fn parse-input (input) (=> list (values list list))
|
|
(let ((input (-<> (position "" input :test #'string=)
|
|
(split input)
|
|
multiple-value-list)))
|
|
(values
|
|
(loop for range in (car input)
|
|
for bounds = (uiop:split-string range :separator '(#\-))
|
|
collect (mapcar #'parse-integer* bounds))
|
|
(mapcar #'parse-integer* (cdadr input)))))
|
|
|
|
(fn in-range (n range) (=> (integer list) boolean)
|
|
(destructuring-bind (lower upper) range
|
|
(and (<= n upper) (>= n lower))))
|
|
|
|
(fn round-1 (ranges items) (=> (list list) fixnum)
|
|
(loop
|
|
for item in items
|
|
sum
|
|
(loop
|
|
for range in ranges
|
|
if (in-range item range)
|
|
return 1
|
|
finally (return 0))))
|
|
|
|
(fn round-2 (ranges) (=> list integer)
|
|
(loop
|
|
with ranges = (sort ranges #'(lambda (x y) (< (car x) (car y))))
|
|
with end = 0
|
|
for (lower upper) in ranges
|
|
if (> lower end)
|
|
sum (1+ (- upper lower)) ;add the size of the range to our running total
|
|
and do (setf end upper) ;make the end of our current range the upper bound
|
|
else
|
|
;; (lower, upper) contained in ranges => remove the intersect
|
|
sum (- (max upper end) end)
|
|
and do (setf end (max upper end))))
|
|
|
|
(let ((input (uiop:read-file-lines "5-input")))
|
|
(multiple-value-bind (ranges items) (parse-input input)
|
|
(->> (round-1 ranges items)
|
|
(format t "Round 1: ~a~%"))
|
|
(->> (round-2 ranges)
|
|
(format t "Round 2: ~a~%"))))
|