src/2017/days/day-17.lisp @ e41337e3b59b

Accessors
author Steve Losh <steve@stevelosh.com>
date Wed, 15 Dec 2021 23:10:57 -0500
parents 182bdd87fd9e
children (none)
(advent:defpackage* :advent/2017/17)
(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)))