src/2017/days/day-17.lisp @ 81b47667837b

2019/10
author Steve Losh <steve@stevelosh.com>
date Sat, 14 Dec 2019 20:00:14 -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)))