5668f7ed5c2d

Day 14
[view raw] [browse files]
author Steve Losh <steve@stevelosh.com>
date Sun, 16 Dec 2018 22:50:57 -0500
parents a2fa45383a67
children d5468dc3769d
branches/tags (none)
files package.lisp src/2018/day-14.lisp src/utils.lisp

Changes

--- a/package.lisp	Sun Dec 16 21:30:28 2018 -0500
+++ b/package.lisp	Sun Dec 16 22:50:57 2018 -0500
@@ -22,6 +22,7 @@
     :nth-digit
     :unique
     :positions-if
+    :digits
 
     :ring
     :ring-prev
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/2018/day-14.lisp	Sun Dec 16 22:50:57 2018 -0500
@@ -0,0 +1,50 @@
+(defpackage :advent/2018/14 #.cl-user::*advent-use*)
+(in-package :advent/2018/14)
+
+(defun combine (recipes elves)
+  (digits (summation elves :key (curry #'aref recipes)) :from-end t))
+
+(defun move-elves (recipes elves)
+  (do-array (elf elves)
+    (setf elf (mod (+ elf (aref recipes elf) 1)
+                   (length recipes)))))
+
+(defun format-output (scores)
+  (str:join "" (coerce scores 'list)))
+
+(define-problem (2018 14) (data read)
+  #+sbcl (sb-ext:gc :full t)
+  (iterate
+    (with recipes = (make-array 2
+                      :adjustable t
+                      :fill-pointer t
+                      :initial-contents '(3 7)))
+    (with elves = (make-array 2 :initial-contents '(0 1)))
+    (with part-1 = nil)
+    (with part-2 = nil)
+    (with target = (digits data :from-end t :result-type 'vector))
+    (with target-length = (length target))
+
+    (until (and part-1 part-2))
+
+    (unless part-1
+      (when (>= (length recipes) (+ 10 data))
+        (setf part-1 (format-output (subseq recipes data (+ data 10))))))
+
+    (iterate (for new-recipe :in (combine recipes elves))
+             (vector-push-extend new-recipe recipes)
+             (for len = (length recipes))
+             (for left = (- len target-length))
+             (unless part-2
+               (when (and (not (minusp left))
+                          (search target recipes :start2 left))
+                 (setf part-2 left))))
+
+    (move-elves recipes elves)
+
+    (finally (return (values part-1 part-2)))))
+
+(1am:test test-2018/14
+  (multiple-value-bind (part1 part2) (run)
+    (1am:is (string= "3610281143" part1))
+    (1am:is (= 20211326 part2))))
--- a/src/utils.lisp	Sun Dec 16 21:30:28 2018 -0500
+++ b/src/utils.lisp	Sun Dec 16 22:50:57 2018 -0500
@@ -362,3 +362,24 @@
                       :end end
                       :key key
                       :initial-value nil))))
+
+
+(defun digits (n &key (radix 10) from-end (result-type 'list))
+  "Return a fresh list of the digits of `n` in base `radix`.
+
+  By default, the digits are returned high-order first, as you would read them.
+  Use `from-end` to get them low-order first:
+
+    (digits 123)             ; => (1 2 3)
+    (digits 123 :from-end t) ; => (3 2 1)
+
+  "
+  (coerce
+    (funcall
+      (if from-end #'nreverse #'identity)
+      (iterate
+        (for (values remaining digit) = (truncate n radix))
+        (collect digit)
+        (setf n remaining)
+        (until (zerop n))))
+    result-type))