(ql:quickload "split-sequence")
(defun read-data (path)
(with-open-file (stream path)
(loop for line = (read-line stream nil)
while line collect line)))
(defparameter *input-source*
(cadr *posix-argv*))
;; Useful in testing
;; (defparameter *input-source* "example_input")
;; (defparameter *input-source* "input")
(defun parse-input (lines)
(map 'list #'parse-integer
(split-sequence:split-sequence #\, (car lines))))
(defparameter *data* (parse-input (read-data *input-source*)))
(defun median (data)
(nth (floor (length data) 2) data))
(defun fuel-cost (arr ref-value value-f)
(loop for e in arr
sum (funcall value-f ref-value e)))
(defun part1-cost (ref-value e)
(abs (- ref-value e)))
(defun part1 (data)
(let* ((sorted (sort (copy-seq data) #'<))
(median (median sorted)))
(fuel-cost sorted median #'part1-cost)))
(defun compounding-cost (ref-value e)
(let ((cost-base (part1-cost ref-value e)))
(/ (* cost-base (+ cost-base 1)) 2)))
(defun part2 (data)
(let* ((sorted (sort (copy-seq data) #'<))
(lowest (car sorted))
(highest (car (last sorted))))
(loop for x from lowest to highest
minimizing (fuel-cost sorted x #'compounding-cost))))
(format t "===== Part 1 =====")
(format t "Result: ~A~%~%" (time (part1 *data*)))
(format t "===== Part 2 =====")
(format t "Result: ~A~%" (time (part2 *data*)))