op (vec (drop 3 str-code))
apply-flag (fn [flag arg]
(case flag
- \0 (fn ([S] (get-in S [:memory arg]))
+ ;; ORs avoid returning nil
+ \0 (fn ([S] (or (get-in S [:memory arg]) 0))
([_ _] arg))
\1 (constantly arg)
- \2 (fn ([S] (get-in S [:memory (+ arg (:relctr S))]))
+ \2 (fn ([S] (or (get-in S [:memory (+ arg (:relctr S))]) 0))
([S _] (+ arg (:relctr S))))))
with-flags (fn [f]
(fn [S & args]
(case op
[\0 \1] (fn [S a b c] ; ADD
(-> S
- (assoc-in [:memory (c S 0)] (+' (a S) (b S)))
+ (assoc-in [:memory (c S true)] (+' (a S) (b S)))
(update :ctr + 4)))
[\0 \2] (fn [S a b c] ; MULT
(-> S
- (assoc-in [:memory (c S 0)] (*' (a S) (b S)))
+ (assoc-in [:memory (c S true)] (*' (a S) (b S)))
(update :ctr + 4)))
[\0 \3] (fn [S a _ _] ; IN
(-> S
- (assoc-in [:memory (a S 0)] (first (:input S)))
+ (assoc-in [:memory (a S true)] (first (:input S)))
(update :input subvec 1)
(update :ctr + 2)))
[\0 \4] (fn [S a _ _] ; OUT
(-> S
- (update :output conj (get-in S [:memory (a S 0)]))
+ (update :output conj (or (get-in S [:memory (a S true)]) 0))
(update :ctr + 2)))
[\0 \5] (fn [S a b _] ; BNEQ
(update S :ctr (if (not= (a S) 0) (constantly (b S)) #(+ % 3))))
(update S :ctr (if (= (a S) 0) (constantly (b S)) #(+ % 3))))
[\0 \7] (fn [S a b c] ; SLT
(-> S
- (assoc-in [:memory (c S 0)] (if (< (a S) (b S)) 1 0))
+ (assoc-in [:memory (c S true)] (if (< (a S) (b S)) 1 0))
(update :ctr + 4)))
[\0 \8] (fn [S a b c] ; SEQ
(-> S
- (assoc-in [:memory (c S 0)] (if (= (a S) (b S)) 1 0))
+ (assoc-in [:memory (c S true)] (if (= (a S) (b S)) 1 0))
(update :ctr + 4)))
[\0 \9] (fn [S a _ _] ; SREL
(-> S
([program settings]
(merge (build-state program) settings)))
+(defn intcode-until [pred state]
+ (as-> (assoc state :step true) it
+ (iterate intcode it)
+ (drop-while #(or (not (:exit %)) (pred %)) it)
+ (first it)
+ (dissoc it :step)))
+
(defn intcode [{:as state :keys [memory output]}]
(cond ; quit if :exit, step and return state if :step, else loop
- (get state :exit) {:memory memory :output output}
+ (get state :exit) {:memory memory :output output :exit true}
(get state :step) (perform-operation state)
:else (recur (perform-operation state))))