# HG changeset patch # User Steve Losh # Date 1545018657 18000 # Node ID 5668f7ed5c2dc09ba172adcc898a9cdcc82e080a # Parent a2fa45383a67af4c8e513ff105540eeac560792f Day 14 diff -r a2fa45383a67 -r 5668f7ed5c2d package.lisp --- 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 diff -r a2fa45383a67 -r 5668f7ed5c2d src/2018/day-14.lisp --- /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)))) diff -r a2fa45383a67 -r 5668f7ed5c2d src/utils.lisp --- 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))