(ns edition2022.day10
  (:require [clojure.string :as str]))

(def example "addx 15\naddx -11\naddx 6\naddx -3\naddx 5\naddx -1\naddx -8\naddx 13\naddx 4\nnoop\naddx -1\naddx 5\naddx -1\naddx 5\naddx -1\naddx 5\naddx -1\naddx 5\naddx -1\naddx -35\naddx 1\naddx 24\naddx -19\naddx 1\naddx 16\naddx -11\nnoop\nnoop\naddx 21\naddx -15\nnoop\nnoop\naddx -3\naddx 9\naddx 1\naddx -3\naddx 8\naddx 1\naddx 5\nnoop\nnoop\nnoop\nnoop\nnoop\naddx -36\nnoop\naddx 1\naddx 7\nnoop\nnoop\nnoop\naddx 2\naddx 6\nnoop\nnoop\nnoop\nnoop\nnoop\naddx 1\nnoop\nnoop\naddx 7\naddx 1\nnoop\naddx -13\naddx 13\naddx 7\nnoop\naddx 1\naddx -33\nnoop\nnoop\nnoop\naddx 2\nnoop\nnoop\nnoop\naddx 8\nnoop\naddx -1\naddx 2\naddx 1\nnoop\naddx 17\naddx -9\naddx 1\naddx 1\naddx -3\naddx 11\nnoop\nnoop\naddx 1\nnoop\naddx 1\nnoop\nnoop\naddx -13\naddx -19\naddx 1\naddx 3\naddx 26\naddx -30\naddx 12\naddx -1\naddx 3\naddx 1\nnoop\nnoop\nnoop\naddx -9\naddx 18\naddx 1\naddx 2\nnoop\nnoop\naddx 9\nnoop\nnoop\nnoop\naddx -1\naddx 2\naddx -37\naddx 1\naddx 3\nnoop\naddx 15\naddx -21\naddx 22\naddx -6\naddx 1\nnoop\naddx 2\naddx 1\nnoop\naddx -10\nnoop\nnoop\naddx 20\naddx 1\naddx 2\naddx 2\naddx -6\naddx -11\nnoop\nnoop\nnoop\n")

(defn translate-to-action [[action args]]
  (if (= action "noop")
    [0]
    [0 (Integer/parseInt args)]))

(defn translate-to-actions [lines]
  (->> (map #(str/split % #" ") lines)
       (map translate-to-action)
       (flatten)))

(defn calculate-signals [actions]
  (loop [cycle-signal {}
         signal 1
         cycle 1
         actions actions]
    (if (empty? actions)
      cycle-signal
      (recur (assoc cycle-signal cycle signal) (+ signal (first actions)) (inc cycle) (rest actions)))))

(defn signal-strength [cycle-signals]
  (let [cycles [20 60 100 140 180 220]
        signals (map cycle-signals cycles)]
    (->> (interleave cycles signals)
         (partition 2)
         (map #(reduce * %))
         (reduce +)
         )))

(defn solution1 [input]
  (->> (str/split-lines input)
       (translate-to-actions)
       (calculate-signals)
       (signal-strength)))

(defn lid-pixel [display cycle signal]
  (let [sprite #{(dec signal) signal (inc signal)}
        display-idx (dec cycle)
        ]
    (if (contains? sprite (mod display-idx 40))
      (assoc display display-idx \#)
      (assoc display display-idx \.))))

(defn render [input]
  (loop [display (vec (repeat 240 \space))
         cycle 1
         signals (->> (str/split-lines input)
                      (translate-to-actions)
                      (calculate-signals))]
    (if (= cycle (inc (count display)))
      display
      (recur (lid-pixel display cycle (signals cycle)) (inc cycle) signals))
    ))

(defn print-render [display]
  (->> (partition 40 display)
       (map #(println %))))


(comment
  (translate-to-action ["noop"])
  (translate-to-action ["addv" "5"])
  (solution1 example)
  (solution1 (slurp "resources/day10.in"))
  (print-render (render example))
  (print-render (render (slurp "resources/day10.in")))
  )