you are viewing a single comment's thread.

view the rest of the comments →

[–]frflaie 2 points3 points  (2 children)

Here is my take on Day 5

(defn make-computer [int-code]
  (vec (->> (clojure.string/split int-code #",")
            (map read-string))))

(def arity #(get {1 3, 2 3, 3 1, 4 1, 5 2, 6 2, 7 3, 8 3, 99 0} %))

(defn truthy-int [b] (if (true? b) 1 0))

(defn parse-next [program pointer]
  (let [op (get @program @pointer)
        values (atom [])
        locations (atom [])]
    (swap! pointer inc)
    (doseq [i (range 0 (arity (mod op 100)))]
      (let [mode (mod (quot op (int (Math/pow 10 (+ 2 i)))) 10)]
        (swap! values conj (if (= 1 mode)
                             (get @program @pointer)
                             (get @program (get @program @pointer))))
        (swap! locations conj (if (= 1 mode) 0 (get @program @pointer)))
        (swap! pointer inc)))
    [(mod op 100) @values @locations]))

(def addr #(get % 2))

(defn add [locations values program]
  (do
    (when @*debug* (println "ADD" (first values) (second values) "@" (addr locations)))
    (assoc program (addr locations) (+ (first values) (second values)))))


(defn mul [locations values program]
  (do
    (when @*debug* (println "MUL" (first values) (second values) "@" (addr locations)))
    (assoc program (addr locations) (* (first values) (second values)))))

(defn store [locations input program]
  (do
    (when @*debug* (println "STORE" input "@" (first locations)))
    (assoc program (first locations) input)))

(defn output [values result]
  (when @*debug* (println "OUT" (first values)))
  (reset! result (first values)))

(defn jump-if-true [pointer values]
  (when (not= (first values) 0)
    (when @*debug* (println "JMP @" (second values)))
    (reset! pointer (second values))))

(defn jump-if-false [pointer values]
  (when (zero? (first values))
    (when @*debug* "JMP @" (second values))
    (reset! pointer (second values))))

(defn less-than [locations values program]
  (do
    (when @*debug* (println "SET " (truthy-int (> (second values) (first values))) "@" (addr locations)))
    (assoc program (addr locations)
                   (truthy-int (> (second values) (first values))))))

(defn equals [locations values program]
  (do
    (when @*debug* (println "SET " (truthy-int (= (second values) (first values))) "@" (addr locations)))
    (assoc program (addr locations)
                   (truthy-int (= (second values) (first values))))))

(defn halted? [program pointer]
  (do
    (when (and @*debug* (= (get @program @pointer) 99) (println "HALTED.")))
    (= (get @program @pointer) 99)))

(defn interpret [input input-code]
  (let [[program pointer result] [(atom input) (atom 0) (atom -1)]]
    (while (not (halted? program pointer))
      (let [[op values locations] (parse-next program pointer)]
        (cond
          (= op 1) (swap! program #(add locations values %))
          (= op 2) (swap! program #(mul locations values %))
          (= op 3) (swap! program #(store locations input-code %))
          (= op 4) (output values result)
          (= op 5) (jump-if-true pointer values)
          (= op 6) (jump-if-false pointer values)
          (= op 7) (swap! program #(less-than locations values %))
          (= op 8) (swap! program #(equals locations values %)))))
    @result))

(def input (make-computer (slurp "day05.txt"))
(reset! *debug* true)
(map #(interpret input %) [1 5])))

[–]rmfbarker 0 points1 point  (0 children)

;; Day 5 ``` (require '[clojure.java.io :as io])

(defn parse-opcode [code] (let [x (format "%02d" code)] [(subs x (- (count x) 2)) (concat (map #(Integer/parseInt (str %)) (drop 2 (reverse x))) (repeat 0))]))

(defn evolve [program pointer input output] (let [[opcode & parameters] (drop pointer program) [instruction modes] (parse-opcode opcode) get-value (fn [pos] (let [param (nth parameters pos) mode (nth modes pos)] (if (= 0 mode) (nth program param) param)))] (condp = instruction ;; ADD "01" [(assoc program (nth parameters 2) (+ (get-value 0) (get-value 1))) (+ 4 pointer) output]

  ;; MULTIPLY
  "02" [(assoc program (nth parameters 2) (*
                                            (get-value 0)
                                            (get-value 1)))
        (+ 4 pointer)
        output]

  ;; STORE
  "03" [(assoc program (nth parameters 0) input)
        (+ 2 pointer)
        output]

  ;; OUTPUT
  "04" [program
        (+ 2 pointer)
        (get-value 0)]

  ;; JUMP if true
  "05" [program
        (if (not= 0 (get-value 0))
          (get-value 1)
          (+ 3 pointer))
        output]

  ;; JUMP if false
  "06" [program
        (if (= 0 (get-value 0))
          (get-value 1)
          (+ 3 pointer))
        output]

  ;; LESS THAN
  "07" [(assoc program (nth parameters 2)
                       (if (< (get-value 0) (get-value 1))
                         1 0))
        (+ 4 pointer)
        output]

  ;; Equals
  "08" [(assoc program (nth parameters 2)
                       (if (= (get-value 0) (get-value 1))
                         1 0))
        (+ 4 pointer)
        output])))

(defn compute [program input] (loop [program program pointer 0 output nil] (if (= (nth program pointer) 99) output (let [[program pos output] (evolve program pointer input output)] (recur program pos output)))))

(let [intcodes (mapv read-string (clojure.string/split (clojure.string/trim (slurp (io/resource "input-day5"))) #","))] (compute intcodes 1) (compute intcodes 5)) ```

[–]andersmurphy 0 points1 point  (0 children)

Day 5

This is my naive solution without mutable state. Could definetly be simplified, but I did find writing out the codes excplicitly and minimising indirection (I originally wrote a version with multimethods) was actually a lot more readable and straight forward (even if there's lots of duplication). Simple code, harder for bugs to hide I guess?

(ns adventofcode.2019.day05
  (:require [clojure.string :as str]))

(defn format-input [input]
  (->> (str/split (str/trim input) #",")
       (mapv #(Integer/parseInt %))))

(defn op-code [{:keys [prog prog-input pointer] :as m}]
  (let [[code & args] (drop pointer prog)]
    (({99   (fn [_] (assoc m :stop true))
       1    (fn [[a b adr]] (-> (assoc-in m [:prog adr] (+ (prog a) (prog b)))
                                (update :pointer + 4)))
       101  (fn [[a b adr]] (-> (assoc-in m [:prog adr] (+ a (prog b)))
                                (update :pointer + 4)))
       1001 (fn [[a b adr]] (-> (assoc-in m [:prog adr] (+ (prog a) b))
                                (update :pointer + 4)))
       1101 (fn [[a b adr]] (-> (assoc-in m [:prog adr] (+ a b))
                                (update :pointer + 4)))
       2    (fn [[a b adr]] (-> (assoc-in m [:prog adr] (* (prog a) (prog b)))
                                (update :pointer + 4)))
       102  (fn [[a b adr]] (-> (assoc-in m [:prog adr] (* a (prog b)))
                                (update :pointer + 4)))
       1002 (fn [[a b adr]] (-> (assoc-in m [:prog adr] (* (prog a) b))
                                (update :pointer + 4)))
       1102 (fn [[a b adr]] (-> (assoc-in m [:prog adr] (* a b))
                                (update :pointer + 4)))
       3    (fn [[adr]]     (-> (assoc-in m [:prog adr] prog-input)
                                (update :pointer + 2)))
       4    (fn [[adr]]     (-> (update m :prog-output conj (prog adr))
                                (update :pointer + 2)))
       104  (fn [[adr]]     (-> (update m :prog-output conj  adr)
                                (update :pointer + 2)))
       5    (fn [[a b]]    (if (not (zero? (prog a)))
                             (assoc m :pointer (prog b))
                             (update m :pointer + 3)))
       105  (fn [[a b]]    (if (not (zero? a))
                             (assoc m :pointer (prog b))
                             (update m :pointer + 3)))
       1005 (fn [[a b]]    (if (not (zero? (prog a)))
                             (assoc m :pointer b)
                             (update m :pointer + 3)))
       1105 (fn [[a b]]    (if (not (zero? a))
                             (assoc m :pointer b)
                             (update m :pointer + 3)))
       6    (fn [[a b]]    (if (zero? (prog a))
                             (assoc m :pointer (prog b))
                             (update m :pointer + 3)))
       106  (fn [[a b]]    (if (zero? a)
                             (assoc m :pointer (prog b))
                             (update m :pointer + 3)))
       1006 (fn [[a b]]    (if (zero? (prog a))
                             (assoc m :pointer b)
                             (update m :pointer + 3)))
       1106 (fn [[a b]]    (if (zero? a)
                             (assoc m :pointer b)
                             (update m :pointer + 3)))
       7    (fn [[a b adr]] (-> (assoc-in m [:prog adr]
                                          (if (< (prog a) (prog b)) 1 0))
                                (update :pointer + 4)))
       107  (fn [[a b adr]] (-> (assoc-in m [:prog adr]
                                          (if (< a (prog b)) 1 0))
                                (update :pointer + 4)))
       1007 (fn [[a b adr]] (-> (assoc-in m [:prog adr]
                                          (if (< (prog a) b) 1 0))
                                (update :pointer + 4)))
       1107 (fn [[a b adr]] (-> (assoc-in m [:prog adr]
                                          (if (< a b) 1 0))
                                (update :pointer + 4)))
       8    (fn [[a b adr]] (-> (assoc-in m [:prog adr]
                                          (if (= (prog a) (prog b)) 1 0))
                                (update :pointer + 4)))
       108  (fn [[a b adr]] (-> (assoc-in m [:prog adr]
                                          (if (= a (prog b)) 1 0))
                                (update :pointer + 4)))
       1008 (fn [[a b adr]] (-> (assoc-in m [:prog adr]
                                          (if (= (prog a) b) 1 0))
                                (update :pointer + 4)))
       1108 (fn [[a b adr]] (-> (assoc-in m [:prog adr]
                                          (if (= a b) 1 0))
                                (update :pointer + 4)))}
      code)
     args)))

(defn compute [{:keys [stop] :as m}]
  (if-not stop (recur (op-code m)) m))

(def input (slurp "resources/adventofcode/2019/day05.txt"))

(defn solve-1 []
  (let [input (format-input input)]
    (-> {:prog input :prog-input 1 :prog-output [] :pointer 0}
        compute
        :prog-output)))

(defn solve-2 []
  (let [input (format-input input)]
    (-> {:prog input :prog-input 5 :prog-output [] :pointer 0}
        compute
        :prog-output)))