Last active
December 21, 2019 16:58
-
-
Save dosbol/206c4755bd726c2ab626cb39f1cf0d3d to your computer and use it in GitHub Desktop.
advent-of-code-2019.clj
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(defn solve1-1 [x] | |
(int (- (Math/floor (/ x 3)) 2))) | |
(->> input | |
(map solve1-1) | |
(apply +)) | |
(defn solve1-2 [s x] | |
(if (<= (solve1-1 x) 0) s | |
(recur (+ s (solve1-1 x)) (solve1-1 x)))) | |
(+ (->> input | |
(map solve1-1) | |
(apply +)) | |
(->> input | |
(map solve1-1) | |
(map (partial solve1-2 0)) | |
(apply +))) | |
***************************************************** | |
(defn solve2 [input pos] | |
(let [op (get input pos)] | |
(cond | |
(or (> (- pos 1) (count input)) | |
(= op 99)) | |
(first input) | |
(and (not= op 1) | |
(not= op 2)) | |
"error" | |
:else | |
(recur (assoc input (get input (+ pos 3)) (if (= op 1) | |
(+ (get input (get input (+ pos 1))) (get input (get input (+ pos 2)))) | |
(* (get input (get input (+ pos 1))) (get input (get input (+ pos 2)))))) (+ pos 4))))) | |
(solve2 input 0) | |
(for [x (range 100) | |
y (range 100)] | |
(if (= 19690720 | |
(solve2 (assoc input 1 x 2 y) 0)) | |
[x y] | |
"")) | |
(solve2 (assoc input 1 52 2 8) 0) | |
(+ (* 52 100) 8) | |
***************************************************** | |
(defn op->points [[op count] points] | |
(let [lst (last points)] | |
(case op | |
\U (concat points (map #(identity [(first lst) %]) (take count (iterate inc (inc (last lst)))))) | |
\D (concat points (map #(identity [(first lst) %]) (take count (iterate dec (dec (last lst)))))) | |
\R (concat points (map #(identity [% (last lst)]) (take count (iterate inc (inc (first lst)))))) | |
\L (concat points (map #(identity [% (last lst)]) (take count (iterate dec (dec (first lst)))))) | |
points))) | |
(defn ops->points [ops] | |
(reduce (fn [points op] (op->points op points)) [[0 0]] ops)) | |
(->> (slurp "input.txt") | |
((fn [v] (clojure.string/split v #"\s"))) | |
(map (fn [x] (clojure.string/split x #","))) | |
(map (fn [xs] (map (fn [x] [(first x) (Integer/parseInt (apply str (rest x)))]) xs))) | |
(map ops->points) | |
(map rest) | |
(map set) | |
((fn [v] (clojure.set/intersection (first v) (last v)))) | |
(map (fn [[x y]] (+ (Math/abs x) (Math/abs y)))) | |
sort | |
first) | |
***************************************************** | |
(def wires (->> (slurp "input.txt") | |
((fn [v] (clojure.string/split v #"\s"))) | |
(map (fn [x] (clojure.string/split x #","))) | |
(map (fn [xs] (map (fn [x] [(first x) (Integer/parseInt (apply str (rest x)))]) xs))) | |
(map ops->points))) | |
(def intersections (->> (slurp "input.txt") | |
((fn [v] (clojure.string/split v #"\s"))) | |
(map (fn [x] (clojure.string/split x #","))) | |
(map (fn [xs] (map (fn [x] [(first x) (Integer/parseInt (apply str (rest x)))]) xs))) | |
(map ops->points) | |
(map rest) | |
(map set) | |
((fn [v] (clojure.set/intersection (first v) (last v)))))) | |
(defn intersection->length [point] | |
(+ (.indexOf (first wires) point) | |
(.indexOf (last wires) point))) | |
(->> intersections | |
(map intersection->length) | |
sort | |
first) | |
***************************************************** | |
(defn never-decrease? [n] | |
(let [iter (fn [prev curr] | |
(cond | |
(= curr 0) true | |
(< prev (mod curr 10)) false | |
:default (recur (mod curr 10) (int (/ curr 10)))))] | |
(iter (mod n 10) (int (/ n 10))))) | |
(defn two-adj-same? [n] | |
(let [iter (fn [prev curr] | |
(cond | |
(= curr 0) false | |
(= prev (mod curr 10)) true | |
:default (recur (mod curr 10) (int (/ curr 10)))))] | |
(iter (mod n 10) (int (/ n 10))))) | |
(count (filter #(and (never-decrease? %) (two-adj-same? %)) (range 256310 732737))) | |
***************************************************** | |
(defn num->list [n] | |
(let [iter (fn [acc num] | |
(if | |
(= (count acc) 6) acc | |
(recur (conj acc (mod num 10)) (int (/ num 10)))))] | |
(iter '() n))) | |
(defn never-decrease-1? [xs] | |
(= xs (sort xs))) | |
(defn two-adj-same-1? [xs] | |
(seq (filter (fn [[_ v]] (= 2 (count v))) (group-by identity xs)))) | |
(count (filter #(and (never-decrease-1? %) (two-adj-same-1? %)) (map num->list (range 256310 732737)))) | |
***************************************************** | |
(defn solve5 [pos input] | |
(if (> (+ pos 1) (count input)) | |
:finish | |
(let [op (get input pos) | |
opcode (mod op 100) | |
first-mode-position (= (mod (quot op 100) 10) 0) | |
second-mode-position (= (mod (quot op 1000) 10) 0) | |
nextpos (case opcode | |
(3 4) (+ pos 2) | |
(1 2) (+ pos 4) | |
pos) | |
nextinput (case opcode | |
3 (assoc input (get input (inc pos)) 1) | |
1 (assoc input | |
(get input (+ pos 3)) | |
(+ (if first-mode-position | |
(get input (get input (+ pos 1))) | |
(get input (+ pos 1))) | |
(if second-mode-position | |
(get input (get input (+ pos 2))) | |
(get input (+ pos 2))))) | |
2 (assoc input | |
(get input (+ pos 3)) | |
(* (if first-mode-position | |
(get input (get input (+ pos 1))) | |
(get input (+ pos 1))) | |
(if second-mode-position | |
(get input (get input (+ pos 2))) | |
(get input (+ pos 2))))) | |
input) | |
_ (when (= opcode 4 ) (prn (if first-mode-position (get input (get input (inc pos))) (get input (inc pos)))))] | |
(if (= opcode 99) | |
:halt | |
(recur nextpos nextinput))))) | |
(->> "input.txt" | |
slurp | |
((fn [v] (clojure.string/split v #"\n"))) | |
first | |
((fn [x] (clojure.string/split x #","))) | |
(map #(Integer/parseInt %)) | |
vec | |
((partial solve5 0))) | |
***************************************************** | |
(defn solve5-2 [pos input] | |
(if (> (+ pos 1) (count input)) | |
:finish | |
(let [op (get input pos) | |
opcode (mod op 100) | |
first-mode-position (= (mod (quot op 100) 10) 0) | |
second-mode-position (= (mod (quot op 1000) 10) 0) | |
nextpos (case opcode | |
(1 2 7 8) (+ pos 4) | |
(3 4) (+ pos 2) | |
5 (if (not= | |
(if first-mode-position | |
(get input (get input (+ pos 1))) | |
(get input (+ pos 1))) | |
0) | |
(if second-mode-position | |
(get input (get input (+ pos 2))) | |
(get input (+ pos 2))) | |
(+ pos 3)) | |
6 (if (= (if first-mode-position | |
(get input (get input (+ pos 1))) | |
(get input (+ pos 1))) | |
0) | |
(if second-mode-position | |
(get input (get input (+ pos 2))) | |
(get input (+ pos 2))) | |
(+ pos 3)) | |
pos) | |
nextinput (case opcode | |
3 (assoc input (get input (inc pos)) 5) | |
1 (assoc input | |
(get input (+ pos 3)) | |
(+ (if first-mode-position | |
(get input (get input (+ pos 1))) | |
(get input (+ pos 1))) | |
(if second-mode-position | |
(get input (get input (+ pos 2))) | |
(get input (+ pos 2))))) | |
2 (assoc input | |
(get input (+ pos 3)) | |
(* (if first-mode-position | |
(get input (get input (+ pos 1))) | |
(get input (+ pos 1))) | |
(if second-mode-position | |
(get input (get input (+ pos 2))) | |
(get input (+ pos 2))))) | |
7 (assoc input | |
(get input (+ pos 3)) | |
(if (< | |
(if first-mode-position | |
(get input (get input (+ pos 1))) | |
(get input (+ pos 1))) | |
(if second-mode-position | |
(get input (get input (+ pos 2))) | |
(get input (+ pos 2)))) | |
1 | |
0)) | |
8 (assoc input | |
(get input (+ pos 3)) | |
(if (= | |
(if first-mode-position | |
(get input (get input (+ pos 1))) | |
(get input (+ pos 1))) | |
(if second-mode-position | |
(get input (get input (+ pos 2))) | |
(get input (+ pos 2)))) | |
1 | |
0)) | |
input) | |
_ (when (= opcode 4) (prn (if first-mode-position (get input (get input (inc pos))) (get input (inc pos)))))] | |
(if (= opcode 99) | |
:halt | |
(recur nextpos nextinput))))) | |
***************************************************** | |
(def inp6 (->> "input.txt" | |
slurp | |
((fn [v] (clojure.string/split v #"\n"))) | |
(map (fn [v] (clojure.string/split v #"\)"))))) | |
(defn orb-counts [inp orb] | |
(let [parent (ffirst (filter (fn [[p c]] (= c orb)) inp))] | |
(if parent | |
(+ 1 (orb-counts inp parent)) | |
0))) | |
(->> inp6 | |
(apply concat) | |
set | |
(map (partial orb-counts inp6)) | |
(apply +)) | |
***************************************************** | |
(defn orb-path [inp orb path] | |
(let [parent (ffirst (filter (fn [[p c]] (= c orb)) inp))] | |
(if-not parent | |
path | |
(recur inp parent (conj path parent))))) | |
(let [you-path (orb-path inp6 "YOU" []) | |
san-path (orb-path inp6 "SAN" [])] | |
(loop [i 0] | |
(if (some #(= (get you-path i) %) san-path) | |
(+ (- (count you-path) (count (orb-path inp6 (get you-path i) []))) | |
(- (count san-path) (count (orb-path inp6 (get you-path i) [])))) | |
(recur (inc i))))) ;; (- res 2) | |
***************************************************** | |
;; refactored | |
(defn int-code [inputv prog] | |
(let [iter (fn [pos input-pos prog result] | |
(let [op (get prog pos) | |
opcode (mod op 100) | |
first-mode-position (= (mod (quot op 100) 10) 0) | |
second-mode-position (= (mod (quot op 1000) 10) 0) | |
next-val (if first-mode-position | |
(get prog (get prog (+ pos 1))) | |
(get prog (+ pos 1))) | |
next-next-val (if second-mode-position | |
(get prog (get prog (+ pos 2))) | |
(get prog (+ pos 2))) | |
nextpos (case opcode | |
(1 2 7 8) (+ pos 4) | |
(3 4) (+ pos 2) | |
5 (if (not= next-val 0) next-next-val (+ pos 3)) | |
6 (if (= next-val 0) next-next-val (+ pos 3)) | |
pos) | |
nextprog (case opcode | |
3 (assoc prog (get prog (+ pos 1)) (get inputv input-pos)) | |
1 (assoc prog (get prog (+ pos 3)) (+ next-val next-next-val)) | |
2 (assoc prog (get prog (+ pos 3)) (* next-val next-next-val)) | |
7 (assoc prog (get prog (+ pos 3)) (if (< next-val next-next-val) 1 0)) | |
8 (assoc prog (get prog (+ pos 3)) (if (= next-val next-next-val) 1 0)) | |
prog) | |
input-pos (if (= opcode 3) (inc input-pos) input-pos) | |
result (if (= opcode 4) next-val result)] | |
(case opcode | |
99 :halt | |
4 result | |
(recur nextpos input-pos nextprog result))))] | |
(iter 0 0 prog nil))) | |
***************************************************** | |
(def program (->> "input.txt" | |
slurp | |
((fn [v] (clojure.string/split v #"\n"))) | |
first | |
((fn [x] (clojure.string/split x #","))) | |
(map #(Integer/parseInt %)) | |
vec)) | |
(defn phase->signal [program phase] | |
(loop [i 0 inp 0] | |
(if (= i 5) | |
inp | |
(recur (inc i) (int-code [(get phase i) inp] program))))) | |
(def phases (for [a [0 1 2 3 4] | |
b [0 1 2 3 4] | |
c [0 1 2 3 4] | |
d [0 1 2 3 4] | |
e [0 1 2 3 4] | |
:when (= (count (group-by identity [a b c d e])) 5)] | |
[a b c d e])) | |
(->> phases | |
(map (partial phase->signal program)) | |
(apply max)) | |
***************************************************** | |
;; refactored | |
(defn int-code [initial-input prog] | |
(let [initial (atom initial-input)] | |
(fn [input] | |
(let [iter (fn [pos prog result] | |
(let [op (get prog pos) | |
opcode (mod op 100) | |
first-mode-position (= (mod (quot op 100) 10) 0) | |
second-mode-position (= (mod (quot op 1000) 10) 0) | |
get-from-next-n (fn [n] (get prog (+ pos n))) | |
next-val (if first-mode-position | |
(get prog (get-from-next-n 1)) | |
(get-from-next-n 1)) | |
next-next-val (if second-mode-position | |
(get prog (get-from-next-n 2)) | |
(get-from-next-n 2)) | |
nextpos (case opcode | |
(1 2 7 8) (+ pos 4) | |
(3 4) (+ pos 2) | |
5 (if (not= next-val 0) next-next-val (+ pos 3)) | |
6 (if (= next-val 0) next-next-val (+ pos 3)) | |
pos) | |
next-input (or @initial input) | |
_ (when (= opcode 3) (reset! initial nil)) | |
nextprog (case opcode | |
3 (assoc prog (get-from-next-n 1) next-input) | |
1 (assoc prog (get-from-next-n 3) (+ next-val next-next-val)) | |
2 (assoc prog (get-from-next-n 3) (* next-val next-next-val)) | |
7 (assoc prog (get-from-next-n 3) (if (< next-val next-next-val) 1 0)) | |
8 (assoc prog (get-from-next-n 3) (if (= next-val next-next-val) 1 0)) | |
prog) | |
result (if (= opcode 4) next-val result)] | |
(case opcode | |
99 :halt | |
4 result | |
(recur nextpos nextprog result))))] | |
(iter 0 prog nil))))) | |
***************************************************** | |
;;refactored | |
(defn int-code [initial-input prog] | |
(let [state (atom {:initial initial-input :pos 0 :prog prog})] | |
(fn [input] | |
(let [iter (fn [result] | |
(if (or (> (+ (:pos @state) 1) (count prog)) | |
(= input :halt)) | |
:halt | |
(let [pos (:pos @state) | |
prog (:prog @state) | |
op (get prog pos) | |
opcode (mod op 100) | |
first-mode-position (= (mod (quot op 100) 10) 0) | |
second-mode-position (= (mod (quot op 1000) 10) 0) | |
get-from-next-n (fn [n] (get prog (+ pos n))) | |
next-val (if first-mode-position | |
(get prog (get-from-next-n 1)) | |
(get-from-next-n 1)) | |
next-next-val (if second-mode-position | |
(get prog (get-from-next-n 2)) | |
(get-from-next-n 2)) | |
nextpos (case opcode | |
(1 2 7 8) (+ pos 4) | |
(3 4) (+ pos 2) | |
5 (if (not= next-val 0) next-next-val (+ pos 3)) | |
6 (if (= next-val 0) next-next-val (+ pos 3)) | |
pos) | |
next-input (or (:initial @state) input) | |
nextprog (case opcode | |
3 (assoc prog (get-from-next-n 1) next-input) | |
1 (assoc prog (get-from-next-n 3) (+ next-val next-next-val)) | |
2 (assoc prog (get-from-next-n 3) (* next-val next-next-val)) | |
7 (assoc prog (get-from-next-n 3) (if (< next-val next-next-val) 1 0)) | |
8 (assoc prog (get-from-next-n 3) (if (= next-val next-next-val) 1 0)) | |
prog) | |
result (if (= opcode 4) next-val result) | |
_ (when (= opcode 3) (reset! state (merge @state {:initial nil}))) | |
_ (reset! state (merge @state {:pos nextpos :prog nextprog}))] | |
(case opcode | |
99 :halt | |
4 result | |
(recur result)))))] | |
(iter nil))))) | |
(defn phase->signal-2 [program [a b c d e]] | |
(let [amp-a (int-code a program) | |
amp-b (int-code b program) | |
amp-c (int-code c program) | |
amp-d (int-code d program) | |
amp-e (int-code e program)] | |
(loop [input 0 i 0] | |
(let [res (-> input amp-a amp-b amp-c amp-d amp-e)] | |
(if (= res :halt) | |
input | |
(recur res (inc i))))))) | |
(def phases-2 (for [a [5 6 7 8 9] | |
b [5 6 7 8 9] | |
c [5 6 7 8 9] | |
d [5 6 7 8 9] | |
e [5 6 7 8 9] | |
:when (= (count (group-by identity [a b c d e])) 5)] | |
[a b c d e])) | |
(->> phases-2 | |
(map (partial phase->signal-2 program)) | |
(apply max)) | |
***************************************************** | |
(def layer (->> "input.txt" | |
slurp | |
(partition 150) | |
(map #(group-by identity %)) | |
(map-indexed (fn [idx m] [idx (count (get m \0))])) | |
(sort-by last) | |
ffirst)) | |
(->> (nth (->> "input.txt" | |
slurp | |
(partition 150)) | |
layer) | |
(group-by identity) | |
((fn [m] (* (count (get m \1)) (count (get m \2)))))) | |
***************************************************** | |
(defn first-not-two [& x] | |
(if-let [first (first x)] | |
(if (not= first \2) | |
first | |
(recur (rest x))))) | |
(defn char-to-str [char] | |
(if (= char \0) " " "x")) | |
(defn printer [x] | |
(if (= x "\n") | |
(println) | |
(print x))) | |
(->> "input.txt" | |
slurp | |
(partition 150) | |
(apply map first-not-two) | |
flatten | |
(map char-to-str) | |
(partition 25) | |
(interpose "\n") | |
(map printer)) | |
********************** day-9 ******************************* | |
(defn int-code [initial-input prog] | |
(let [state (atom {:initial initial-input :prog (into {} (map-indexed hash-map prog)) :pos 0 :base 0})] | |
(fn [input] | |
(let [iter (fn [results] | |
(if (= input :halt) | |
:halt | |
(let [{:keys [pos prog base initial]} @state | |
op (get prog pos) | |
opcode (mod op 100) | |
get-from-next-n (fn [n] (get prog (+ pos n) 0)) | |
next-val (case (mod (quot op 100) 10) | |
0 (get prog (get-from-next-n 1) 0) | |
1 (get-from-next-n 1) | |
2 (get prog (+ base (get-from-next-n 1)) 0)) | |
next-next-val (case (mod (quot op 1000) 10) | |
0 (get prog (get-from-next-n 2) 0) | |
1 (get-from-next-n 2) | |
2 (get prog (+ base (get-from-next-n 2)) 0)) | |
get-write-pos (fn [n] (case (mod (quot op (* 10 (int (Math/pow 10 n)))) 10) ; 1 -> 100, 3 -> 10000 | |
2 (+ base (get-from-next-n n)) | |
0 (get-from-next-n n))) | |
nextpos (case opcode | |
(1 2 7 8) (+ pos 4) | |
(3 4 9) (+ pos 2) | |
5 (if (not= next-val 0) next-next-val (+ pos 3)) | |
6 (if (= next-val 0) next-next-val (+ pos 3)) | |
pos) | |
next-input (or initial input) | |
nextprog (case opcode | |
1 (assoc prog (get-write-pos 3) (+ next-val next-next-val)) | |
2 (assoc prog (get-write-pos 3) (* next-val next-next-val)) | |
3 (assoc prog (get-write-pos 1) next-input) | |
7 (assoc prog (get-write-pos 3) (if (< next-val next-next-val) 1 0)) | |
8 (assoc prog (get-write-pos 3) (if (= next-val next-next-val) 1 0)) | |
prog) | |
next-initial (if (= opcode 3) nil initial) | |
next-base (if (= opcode 9) (+ base next-val) base) | |
_ (reset! state {:pos nextpos :prog nextprog :initial next-initial :base next-base})] | |
(case opcode | |
99 (do (println results) :halt) | |
(recur (if (= opcode 4) (conj results next-val) results))))))] | |
(iter []))))) | |
(def program (->> "input.txt" | |
slurp | |
((fn [v] (clojure.string/split v #"\n"))) | |
first | |
((fn [x] (clojure.string/split x #","))) | |
(map #(Integer/parseInt %)) | |
vec)) | |
((int-code 1 program) nil) | |
***********************day-10************************** | |
(def inp (-> "input.txt" | |
slurp | |
(clojure.string/split #"\n"))) | |
(defn colinear? [[x1 y1] [x3 y3] [x2 y2]] | |
(= (* (- y2 y1) (- x3 x1)) | |
(* (- y3 y1) (- x2 x1)))) | |
(defn blocked? [[x1 y1] [x3 y3] [x2 y2]] | |
(and (colinear? [x1 y1] [x3 y3] [x2 y2]) | |
(and (or (>= x1 x2 x3) (<= x1 x2 x3)) | |
(or (>= y1 y2 y3) (<= y1 y2 y3))))) | |
(def x-length (count (get inp 0))) | |
(def y-length (count inp)) | |
(defn no-found-linear? [p1 p2 detects] | |
(not-any? (partial blocked? p1 p2) detects)) | |
(defn detects [[x1 y1]] | |
(let [state (atom []) | |
add-if-detect (fn [x y] (when (and (= (get-in inp [x y]) \#) | |
(no-found-linear? [x1 y1] [x y] @state)) | |
(swap! state conj [x y])))] | |
(doall (for [x (range x1 x-length) | |
y (take y1 (iterate dec (dec y1)))] | |
(add-if-detect x y))) | |
(doall (for [x (range x1 x-length) | |
y (range y1 y-length) | |
:when (or (not= x x1) (not= y y1))] | |
(add-if-detect x y))) | |
(doall (for [x (take x1 (iterate dec (dec x1))) | |
y (range y1 y-length) | |
:when (or (not= x x1) (not= y y1))] | |
(add-if-detect x y))) | |
(doall (for [x (take x1 (iterate dec (dec x1))) | |
y (take y1 (iterate dec (dec y1))) | |
:when (or (not= x x1) (not= y y1))] | |
(add-if-detect x y))) | |
@state)) | |
(def result (for [x (range x-length) | |
y (range y-length) | |
:when (= (get-in inp [x y]) \#)] | |
[(count (detects [x y])) x y])) | |
(->> result | |
(sort-by first) | |
last) | |
******************************************************* |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment