(set! *warn-on-reflection* true)
(set! *unchecked-math* :warn-on-boxed)

(def loop-count 1000000)
(def expected-checksum 3500013)

(defrecord Packet [digits])

(defn configured-loop-count []
  (try
    (let [line (read-line)
          value (Integer/parseInt (.trim ^String line))]
      (if (pos? value) value loop-count))
    (catch Exception _
      loop-count)))

(defn live-state []
  {:tag :live :payload (->Packet [2 7 1 8 2 8 1 8])})

(defn cached-state []
  {:tag :cached :payload (->Packet [1 6 1 8 0 3 4 5])})

(defn select-state [i live cached]
  (if (zero? (rem i 2)) live cached))

(defn state-digit [state index]
  (case (:tag state)
    :missing 0
    (nth (:digits ^Packet (:payload state)) index)))

(defn enum-struct-payload-loop [limit]
  (loop [i 0
         acc 13
         live (live-state)
         cached (cached-state)]
    (if (< i limit)
      (let [next (+ acc (state-digit (select-state i live cached) (rem i 8)))
            bounded (if (> next 1000000000)
                      (- next 1000000000)
                      next)]
        (recur (inc i) bounded live cached))
      acc)))

(let [result (enum-struct-payload-loop (configured-loop-count))]
  (println result)
  (System/exit (if (= result expected-checksum) 0 1)))
