--- a/advent.asd Fri Dec 01 13:42:19 2017 -0500
+++ b/advent.asd Sat Dec 02 12:48:50 2017 -0500
@@ -5,7 +5,7 @@
:license "MIT"
- :depends-on (:iterate :losh)
+ :depends-on (:iterate :losh :split-sequence :str)
:serial t
:components ((:module "vendor" :serial t
--- a/src/main.lisp Fri Dec 01 13:42:19 2017 -0500
+++ b/src/main.lisp Sat Dec 02 12:48:50 2017 -0500
@@ -12,19 +12,42 @@
(map 'list #'digit-char-p <>)
(remove nil <>)))
+(defun read-file-of-lines-of-numbers (path)
+ (iterate (for line :in-file path :using #'read-line)
+ (collect (mapcar #'parse-integer (str:words line)))))
+
;;;; Problems -----------------------------------------------------------------
(defun day-1-part-1 ()
- (iterate (for (x . y) :pairs-of-list (read-file-of-digits "data/2017/01-1"))
+ (iterate (for (x . y) :pairs-of-list (read-file-of-digits "data/2017/01"))
(when (= x y)
(sum x))))
(defun day-1-part-2 ()
(iterate
- (with data = (coerce (read-file-of-digits "data/2017/01-1") 'vector))
+ (with data = (coerce (read-file-of-digits "data/2017/01") 'vector))
(with length = (length data))
(for x :in-vector data)
(for iy :modulo length :from (truncate length 2))
(for y = (aref data iy))
(when (= x y)
(sum x))))
+
+
+(defun day-2-part-1 ()
+ (flet ((checksum (line)
+ (- (apply #'max line)
+ (apply #'min line))))
+ (summation (remove nil (read-file-of-lines-of-numbers "data/2017/02"))
+ :key #'checksum)))
+
+(defun day-2-part-2 ()
+ (labels ((validp (a b)
+ (dividesp (max a b) (min a b)))
+ (head-valid-p (list)
+ (some (curry #'validp (car list))
+ (cdr list)))
+ (checksum (line)
+ (somelist #'head-valid-p line)))
+ (summation (remove nil (read-file-of-lines-of-numbers "data/2017/02"))
+ :key #'checksum)))
--- a/vendor/make-quickutils.lisp Fri Dec 01 13:42:19 2017 -0500
+++ b/vendor/make-quickutils.lisp Sat Dec 02 12:48:50 2017 -0500
@@ -5,6 +5,7 @@
:utilities '(
:curry
+ :extremum
:rcurry
:read-file-into-string
--- a/vendor/quickutils.lisp Fri Dec 01 13:42:19 2017 -0500
+++ b/vendor/quickutils.lisp Sat Dec 02 12:48:50 2017 -0500
@@ -2,7 +2,7 @@
;;;; See http://quickutil.org for details.
;;;; To regenerate:
-;;;; (qtlc:save-utils-as "quickutils.lisp" :utilities '(:CURRY :RCURRY :READ-FILE-INTO-STRING) :ensure-package T :package "ADVENT.QUICKUTILS")
+;;;; (qtlc:save-utils-as "quickutils.lisp" :utilities '(:CURRY :EXTREMUM :RCURRY :READ-FILE-INTO-STRING) :ensure-package T :package "ADVENT.QUICKUTILS")
(eval-when (:compile-toplevel :load-toplevel :execute)
(unless (find-package "ADVENT.QUICKUTILS")
@@ -14,7 +14,7 @@
(when (boundp '*utilities*)
(setf *utilities* (union *utilities* '(:MAKE-GENSYM-LIST :ENSURE-FUNCTION
- :CURRY :RCURRY :ONCE-ONLY
+ :CURRY :EXTREMUM :RCURRY :ONCE-ONLY
:WITH-OPEN-FILE* :WITH-INPUT-FROM-FILE
:READ-FILE-INTO-STRING))))
(eval-when (:compile-toplevel :load-toplevel :execute)
@@ -61,6 +61,50 @@
(apply ,fun ,@curries more)))))
+ (defun extremum (sequence predicate &key key (start 0) end)
+ "Returns the element of `sequence` that would appear first if the subsequence
+bounded by `start` and `end` was sorted using `predicate` and `key`.
+
+`extremum` determines the relationship between two elements of `sequence` by using
+the `predicate` function. `predicate` should return true if and only if the first
+argument is strictly less than the second one (in some appropriate sense). Two
+arguments `x` and `y` are considered to be equal if `(funcall predicate x y)`
+and `(funcall predicate y x)` are both false.
+
+The arguments to the `predicate` function are computed from elements of `sequence`
+using the `key` function, if supplied. If `key` is not supplied or is `nil`, the
+sequence element itself is used.
+
+If `sequence` is empty, `nil` is returned."
+ (let* ((pred-fun (ensure-function predicate))
+ (key-fun (unless (or (not key) (eq key 'identity) (eq key #'identity))
+ (ensure-function key)))
+ (real-end (or end (length sequence))))
+ (cond ((> real-end start)
+ (if key-fun
+ (flet ((reduce-keys (a b)
+ (if (funcall pred-fun
+ (funcall key-fun a)
+ (funcall key-fun b))
+ a
+ b)))
+ (declare (dynamic-extent #'reduce-keys))
+ (reduce #'reduce-keys sequence :start start :end real-end))
+ (flet ((reduce-elts (a b)
+ (if (funcall pred-fun a b)
+ a
+ b)))
+ (declare (dynamic-extent #'reduce-elts))
+ (reduce #'reduce-elts sequence :start start :end real-end))))
+ ((= real-end start)
+ nil)
+ (t
+ (error "Invalid bounding indexes for sequence of length ~S: ~S ~S, ~S ~S"
+ (length sequence)
+ :start start
+ :end end)))))
+
+
(defun rcurry (function &rest arguments)
"Returns a function that applies the arguments it is called
with and `arguments` to `function`."
@@ -162,6 +206,6 @@
:while (= bytes-read buffer-size)))))))
(eval-when (:compile-toplevel :load-toplevel :execute)
- (export '(curry rcurry read-file-into-string)))
+ (export '(curry extremum rcurry read-file-into-string)))
;;;; END OF quickutils.lisp ;;;;