(declaim (optimize (speed 3) (safety 0) (debug 0))) (defconstant +loop-count+ 1000000) (defconstant +expected-checksum+ 3500013) (defstruct (packet (:constructor %make-packet (digits))) digits) (defstruct (packet-state (:constructor %make-packet-state (tag payload))) tag payload) (declaim (ftype (function () fixnum) configured-loop-count)) (defun configured-loop-count () (handler-case (let ((line (read-line *standard-input* nil nil))) (if line (let ((value (parse-integer line :junk-allowed t))) (if (> value 0) value +loop-count+)) +loop-count+)) (error () +loop-count+))) (declaim (ftype (function () packet-state) live-state)) (defun live-state () (%make-packet-state :live (%make-packet #(2 7 1 8 2 8 1 8)))) (declaim (ftype (function () packet-state) cached-state)) (defun cached-state () (%make-packet-state :cached (%make-packet #(1 6 1 8 0 3 4 5)))) (declaim (ftype (function (fixnum packet-state packet-state) packet-state) select-state)) (defun select-state (i live cached) (declare (type fixnum i)) (if (zerop (rem i 2)) live cached)) (declaim (ftype (function (packet-state fixnum) fixnum) state-digit)) (defun state-digit (state index) (declare (type packet-state state) (type fixnum index)) (let* ((payload (packet-state-payload state)) (digits (packet-digits payload)) (value (svref digits index))) (declare (type simple-vector digits) (type fixnum value)) (case (packet-state-tag state) (:missing 0) (otherwise value)))) (declaim (ftype (function (fixnum) fixnum) enum-struct-payload-loop)) (defun enum-struct-payload-loop (limit) (declare (type fixnum limit)) (loop with i of-type fixnum = 0 with acc of-type fixnum = 13 with live of-type packet-state = (live-state) with cached of-type packet-state = (cached-state) while (< i limit) do (let* ((next (+ acc (state-digit (select-state i live cached) (rem i 8)))) (bounded (if (> next 1000000000) (- next 1000000000) next))) (declare (type fixnum next bounded)) (setf acc bounded i (+ i 1))) finally (return acc))) (let ((result (enum-struct-payload-loop (configured-loop-count)))) (format t "~D~%" result) (sb-ext:exit :code (if (= result +expected-checksum+) 0 1)))