src/2017/days/day-17.lisp @ ebb7ecd4844f
2016/02
author |
Steve Losh <steve@stevelosh.com> |
date |
Fri, 06 Dec 2019 23:50:53 -0500 |
parents |
2078ac8647c6 |
children |
182bdd87fd9e |
(defpackage :advent/2017/17 #.cl-user::*advent-use*)
(in-package :advent/2017/17)
(defun-inline spin (ring shift n)
(iterate (for i :from 1 :to n)
(ring-movef ring shift)
(ring-insertf-after ring i))
ring)
(defun simple-part-2 (shift)
(-<> (ring 0)
(spin <> shift 50000000)
(ring-find <> 0)
ring-next
ring-data))
(defun fast-part-2 (shift)
(declare (optimize speed (debug 1) (safety 1)))
(check-type shift fixnum)
;; Hack: the only actual value we care about is the one that's after 0, so we
;; don't actually have to store a list of the rest. We can just compute the
;; offset of where we *would* insert into the list, and keep track of the last
;; value we set index 1 to.
(iterate
(declare (iterate:declare-variables))
(with result)
(for (the fixnum size) :from 1)
(for (the fixnum val) :from 1 :to 50000000)
(for (the fixnum pos) :seed 0 :then (1+ (mod (+ pos shift) size)))
(when (= 1 pos)
(setf result val))
(returning result)))
(define-problem (2017 17) (data read) (1244 11162912)
(values
(-<> (ring 0)
(spin <> data 2017)
ring-next
ring-data)
(fast-part-2 data)))