Skip to content

Instantly share code, notes, and snippets.

@dosbol
Last active December 12, 2020 07:38
Show Gist options
  • Save dosbol/4e960dbb2b87a8fc0e2d54542233a0eb to your computer and use it in GitHub Desktop.
Save dosbol/4e960dbb2b87a8fc0e2d54542233a0eb to your computer and use it in GitHub Desktop.
(ns main
(:require
[clojure.string :as str]
[clojure.math.combinatorics :as combo]))
(comment
;; day 1
;;
(def input (->> (slurp "input1.txt")
((fn [v] (str/split v #"\s")))
(map #(Integer/parseInt %))))
(reduce (fn [_ [a b]] (when (= 2020 (+ a b)) (reduced (* a b))))
nil
(combo/combinations input 2))
(reduce (fn [_ [a b c]] (when (= 2020 (+ a b c)) (reduced (* a b c))))
nil
(combo/combinations input 3))
;; day 2
;;
;;
(def input (->> (slurp "input2.txt")
((fn [v] (str/split v #"\n")))
(map (fn [v] (str/split v #" ")))
(map (fn [[x y z]] [(map #(Integer/parseInt %) (str/split x #"-"))
(first y)
z]))))
(count (filter #{\a} "aaabbc"))
(->> input
(filter (fn [[[min max] c s]] (<= min (->> s (filter #{c}) count) max)))
count)
(get "abc" 1)
(->> input
(map (fn [[[frst scnd] c s]] (count (filter #{c} [(get s (dec frst)) (get s (dec scnd))]))))
(filter #{1})
count)
;;
;; day 3
;;
(def input (->> (slurp "input3.txt")
((fn [v] (str/split v #"\n")))))
(def height (count input))
(def width (* height 3))
(get (get input 1) 1)
(nth (take 10 (cycle "..#")) 8)
(def board (->> input (mapv #(take width (cycle %)))))
(def coords (map (fn [x y] [x y]) (range height) (range 0 width 3)))
(nth (nth board (ffirst coords)) 0)
(->> coords
(map (fn [[x y]] (-> (nth board x)
(nth y))))
(filter #{\#})
count) ;200
;;part 2
(def input (->> (slurp "input3.txt")
((fn [v] (str/split v #"\n")))))
(def height (count input))
(def width (* height 7))
(def board (->> input (mapv #(take width (cycle %)))))
(def coords (map (fn [x y] [x y]) (range height) (range width)))
(->> coords
(map (fn [[x y]] (-> (nth board x)
(nth y))))
(filter #{\#})
count) ;66
(def coords (map (fn [x y] [x y]) (range height) (range 0 width 5)))
(->> coords
(map (fn [[x y]] (-> (nth board x)
(nth y))))
(filter #{\#})
count);76
(def coords (map (fn [x y] [x y]) (range height) (range 0 width 7)))
(->> coords
(map (fn [[x y]] (-> (nth board x)
(nth y))))
(filter #{\#})
count);81
(def coords (map (fn [x y] [x y]) (range 0 height 2) (range width)))
(->> coords
(map (fn [[x y]] (-> (nth board x)
(nth y))))
(filter #{\#})
count);46
(* 46 81 76 66 200)
;;
;; day4
;;
(->> (slurp "input4.txt")
str/split-lines
(partition-by #(= "" %))
(remove #{'("")})
(map (fn [s] (str/split (str/join " " s) #"\s|:")))
(map (fn [xs] (filter #{"byr" "eyr" "iyr" "hgt" "hcl" "ecl" "pid"} xs)))
(filter (fn [xs] (= (count xs) 7)))
count)
(def passports (->> (slurp "input4.txt")
str/split-lines
(partition-by #(= "" %))
(remove #{'("")})
(map (fn [s] (str/split (str/join " " s) #"\s|:")))
(map #(->> (partition 2 %)
(map vec)
(into {})))))
(->> passports
;; (filter (fn [p] (= (count (filter #{"byr" "eyr" "iyr" "hgt" "hcl" "ecl" "pid"} (keys p))) 7)))
;;
(filter (fn [p] (and (= (count (get p "byr")) 4)
(<= 1920 (Integer/parseInt (get p "byr")) 2002))))
(filter (fn [p] (and (= (count (get p "iyr")) 4)
(<= 2010 (Integer/parseInt (get p "iyr")) 2020))))
(filter (fn [p] (and (= (count (get p "eyr")) 4)
(<= 2020 (Integer/parseInt (get p "eyr")) 2030))))
(filter (fn [p] (= (count (get p "pid")) 9)))
(filter (fn [p] (let [measure (str/join "" [(last (butlast (get p "hgt"))) (last (get p "hgt"))])
height-str (str/join "" (butlast (butlast (get p "hgt"))))
height (when-not (str/blank? height-str) (Integer/parseInt height-str))]
(and (some #{"cm" "in"} [measure])
(if (= measure "cm")
(<= 150 height 193)
(<= 59 height 76))))))
(filter (fn [p] (some #{"amb" "blu" "brn" "gry" "grn" "hzl" "oth"} [(get p "ecl")])))
(filter (fn [p] (let [hc (get p "hcl")
hc# (first (get p "hcl"))
hc- (str/join "" (next hc))]
(and (= hc# \#)
(= (count hc-) 6)
(every? #(re-matches #"[0-9]|[a-f]" (str %)) hc-)))))
count)
(some #{"cm" "in"} ["in"])
;; (Integer/parseInt (str/join "" (butlast (butlast "17"))))
(str/join "" (butlast (butlast "17")))
(re-matches #"[0-9]" "9")
(every? #(re-matches #"[a-f]" (str %)) "acd")
(some #{1 2 3} [4])
(= \# (first "#adsfsadf"))
(every? #(re-matches #"[0-9]" (str %)) "123456a")
;;
;; day 5
;;
"FBFBBFF" ;44
"FBFBBFFRLR" ;357
"BFFFBBFRRR" ;567
"FFFBBBFRRR" ;119
"BBFFBBFRLL" ;820
(def l->b {\B 1 \F 0 \R 1 \L 0})
(def powers-of-2 (iterate (partial * 2) 1))
(take 4 powers-of-2)
(->> "FBFBBFF"
(map l->b)
reverse
(map * powers-of-2)
(apply +))
(defn solve [s]
(+ (* 8
(->> s
(take 7)
(map l->b)
(reverse)
(map (fn [b x] (* b x)) [1 2 4 8 16 32 64])
(reduce +)))
(->> s
(reverse)
(take 3)
(map l->b)
(map (fn [b x] (* b x)) [1 2 4])
(reduce +))))
(solve "FBFBBFFRLR")
(solve "BFFFBBFRRR")
(solve "FFFBBBFRRR")
(solve "BBFFBBFRLL")
(->> (slurp "input5.txt")
str/split-lines
(map solve)
(apply max)) ;963
(->> (slurp "input5.txt")
str/split-lines
(map solve)
set
((fn [xs ys] (clojure.set/difference xs ys)) (set (range 963))))
;;
;; day 6
;;
(str/split "abc" #"")
(str/join ["a"])
(->> (slurp "input6.txt")
((fn [v] (str/split v #"\n\n")))
(map str/split-lines)
(map (fn [xs] (-> xs str/join (str/split #""))))
(map frequencies)
(map keys)
(map count)
(apply +))
(->> (slurp "input6.txt")
((fn [v] (str/split v #"\n\n")))
(map str/split-lines)
(map (fn [xs] [(count xs) (-> xs str/join (str/split #""))]))
(map (fn [[count xs]] (filter #(= count %) (vals (frequencies xs)))))
(map count)
(apply +))
;;
;; day 7
;;
(def data (->> (slurp "input7.txt")
((fn [v] (str/split v #"\n")))
(map (fn [v] (str/split v #" bags contain ")))
(map (fn [[color contains]] [color (str/split contains #" bags?\.?\,?")]))
(remove (fn [[_ contains]] (= contains ["no other"])))
(map (fn [[color contains]]
[color (set (flatten (map (partial drop 1)
(map (partial re-find #".?\d+ (.+)") contains))))]))
(into {})))
(clojure.set/intersection #{} #{:a})
(map first (filter #(seq (clojure.set/intersection (second %) #{"shiny gold"})) data))
(into #{} [:a :b])
(loop [bags #{"shiny gold"}
old-bags #{}]
(if (= bags old-bags)
(dec (count bags))
(let [new-bags (into bags (map first
(filter #(seq (clojure.set/intersection bags (second %))) data)))]
(recur new-bags bags))))
;; shiny gold bags contain 2 dark red bags.
;; dark red bags contain 2 dark orange bags.
;; dark orange bags contain 2 dark yellow bags.
;; dark yellow bags contain 2 dark green bags.
;; dark green bags contain 2 dark blue bags.
;; dark blue bags contain 2 dark violet bags.
;; dark violet bags contain no other bags.
;;
;; 2 red + 4 orange + 8 yellow + 16 green + 32 blue + 64 violet
(+ 2 4 8 16 32 64)
(def data (->> (slurp "input7.txt")
((fn [v] (str/split v #"\n")))
(map (fn [v] (str/split v #" bags contain ")))
(map (fn [[color contains]] [color (str/split contains #" bags?\.?\,?")]))
(remove (fn [[_ contains]] (= contains ["no other"])))
(map (fn [[color contains]]
[color (mapv (fn [[_ d c]] [c (Long/parseLong d)])
(map (partial re-find #".?(\d+) (.+)") contains))]))
(into {})))
(defn get-bags-inside [times [color amount]]
[(mapv (partial get-bags-inside (* times amount)) (data color)) (* times amount)])
(dec (apply + (flatten (get-bags-inside 1 ["shiny gold" 1]))))
;; day 8
(def program (->> (slurp "input8.txt")
((fn [v] (str/split v #"\n")))
(mapv (fn [v] (let [[op arg] (str/split v #" ")]
[op (Long/parseLong arg)])))))
(loop [acc 0
line 1
visited-lines #{}]
(let [[op arg] (nth program (dec line))]
(if (visited-lines line)
acc
(recur (if (= op "acc") (+ acc arg) acc)
(case op
"jmp" (+ line arg)
(inc line))
(conj visited-lines line)))))
(def nops (for [x (range (dec (count program)))
:let [[op arg] (nth program x)]
:when (= op "nop")]
[x ["jmp" arg]]))
(def jmps (for [x (range (dec (count program)))
:let [[op arg] (nth program x)]
:when (= op "jmp")]
[x ["nop" arg]]))
(def all-position-with-ops (vec (concat nops jmps)))
(defn solve2 [program]
(loop [acc 0
line 1
visited-lines #{}]
(if (>= line (inc (count program)))
acc
(let [[op arg] (nth program (dec line))]
(if (visited-lines line)
nil
(recur (if (= op "acc") (+ acc arg) acc)
(case op
"jmp" (+ line arg)
(inc line))
(conj visited-lines line)))))))
(for [[i change] all-position-with-ops
:when (solve2 (assoc program i change))]
(solve2 (assoc program i change)))
;; day 9
(def data (->> (slurp "input9.txt")
((fn [v] (str/split v #"\n")))
(map #(Long/parseLong %))))
(def length 25)
(defn valid? [data i]
(when-not (seq (for [x (range (- i length) i)
y (range (- i length) i)
:when (and (not= x y) (= (+ (nth data x)
(nth data y))
(nth data i)))]
true))
(nth data i)))
(some identity (map (partial valid? data) (range length (count data))))
;part 2
(def target (some identity (map (partial valid? data) (range length (count data)))))
(def target-range
(loop [lo 0
hi 0
remain target]
(let [curr (nth data hi)]
(cond
(= curr remain)
[lo (inc hi)]
(> curr remain)
(recur (inc lo) (inc lo) target)
(< curr remain)
(recur lo (inc hi) (- remain curr))))))
(->> (apply range target-range)
(map (partial nth data))
(apply (juxt min max))
(apply +))
;; day 10
(def data (->> (slurp "input10.txt")
((fn [v] (str/split v #"\n")))
(map #(Long/parseLong %))))
(def maximum (apply clojure.core/max data))
(loop [one 0
three 0
jolt 0]
(if (= jolt maximum)
(* one (inc three))
(cond
(some #{(+ jolt 1)} data)
(recur (inc one) three (+ jolt 1))
(some #{(+ jolt 2)} data)
(recur one three (+ jolt 2))
(some #{(+ jolt 3)} data)
(recur one (inc three) (+ jolt 3)))))
;; part 2
;;
(defn next-numbers [x]
(remove nil? [(when (some #{(+ x 1)} data) (+ x 1))
(when (some #{(+ x 2)} data) (+ x 2))
(when (some #{(+ x 3)} data) (+ x 3))]))
(loop [ways '(0)
result 0]
(prn ways)
(if-not (seq ways)
result
(let [next-xs (mapcat next-numbers ways)]
(recur (remove #{maximum} next-xs)
(+ result (count (filter #{maximum} next-xs)))))))
{0 1}
{1 1}
{4 1}
{5 1, 6 1, 7 1}
{6 1, 7 2, 10 1}
{7 1, 10 2, 11 1, 12 1}
{10 1, 11 2, 12 3, 15 1}
{11 1, 12 3, 15 3, 16 1}
{12 1, 15 3, 16 3, 19 1}
{15 1, 16 3, 19 4}
{16 1, 19 7}
{19 8}
(defn magic [m]
(reduce-kv
(fn [m k v]
(-> (reduce (fn [m key] (update m key (fnil + 0) v))
m
(next-numbers k))
(update k - v)
(->> (filter (fn [[_ y]] (not= y 0)))
(into {}))))
m
(dissoc m maximum)))
(loop [ways {0 1}]
(if (= (keys ways) (list maximum))
(ways maximum)
(recur (magic ways))))
;; day 11
(def data (->> (slurp "input11.txt")
((fn [v] (str/split v #"\n")))
(mapv (fn [v] (str/split v #"")))))
(get-in data [0 -1] ".")
(defn get-adjacents [data [x y]]
(for [dx [-1 0 1]
dy [-1 0 1]
:when (not (= dx dy 0))]
(get-in data [(+ x dx) (+ y dy)] ".")))
(defn no-occupied-adjacents? [data [x y]]
(not (some #{"#"} (get-adjacents data [x y]))))
(no-occupied-adjacents? data [4 4])
(defn four-or-more-occupied-adjacents? [data [x y]]
(<= 4 (count (filter #{"#"} (get-adjacents data [x y])))))
(four-or-more-occupied-adjacents? data [4 4])
(get-adjacents data [0 0])
(get-adjacents data [4 4])
(def rules {"." (fn [_ _] ".")
"L" (fn [data [x y]] (if (no-occupied-adjacents? data [x y])
"#"
"L"))
"#" (fn [data [x y]] (if (four-or-more-occupied-adjacents? data [x y])
"L"
"#"))})
(def all-x-y (for [x (range (count data))
y (range (count (first data)))]
[x y]))
(defn next-seat [data rules [x y]]
((rules (get-in data [x y])) data [x y]))
((rules (get-in data [0 0])) data [0 0])
(next-seat data rules [0 0])
(mapv vec (partition (count data) (mapv (partial next-seat data rules) all-x-y)))
(loop [old-data []
new-data data
step 0]
(if (= old-data new-data)
(count (filter #{"#"} (flatten new-data)))
(recur new-data (mapv vec
(partition
(count (first data))
(mapv (partial next-seat new-data rules) all-x-y))) (inc step))))
;; part 2
(def data (->> (slurp "input11.txt")
((fn [v] (str/split v #"\n")))
(mapv (fn [v] (str/split v #"")))))
(defn coords []
(for [dx [-1 0 1]
dy [-1 0 1]
:when (not (= dx dy 0))]
[dx dy]))
(defn diffs [data]
(map #(take (apply max [(count (first data)) (count data)]) %) (map repeat (coords))))
(diffs data)
(defn coords-look-for [data [x y]]
(map (fn [ds]
(reduce (fn [[acc [x y]] [dx dy]]
(if (or (> 0 (+ x dx))
(> 0 (+ y dy))
(<= (count data) (+ x dx))
(<= (count (first data)) (+ y dy)))
(reduced acc)
[(conj acc [(+ x dx) (+ y dy)]) [(+ x dx) (+ y dy)]]))
[[] [x y]]
ds))
(diffs data)))
(coords-look-for data [0 0])
(defn seen-seats [data [x y]]
(map
#(reduce
(fn [curr [x y]]
(let [seat (get-in data [x y] ".")]
(if-not (= curr seat)
(reduced seat)
curr)))
"."
%)
(coords-look-for data [x y])))
(seen-seats data [3 3])
(seen-seats data [0 0])
(defn no-occupied-seen-seats? [data [x y]]
(not (some #{"#"} (seen-seats data [x y]))))
(no-occupied-seen-seats? data [0 0])
(defn five-or-more-occupied-seen-seats? [data [x y]]
(<= 5 (count (filter #{"#"} (seen-seats data [x y])))))
(five-or-more-occupied-seen-seats? data [4 4])
(def rules {"." (fn [_ _] ".")
"L" (fn [data [x y]] (if (no-occupied-seen-seats? data [x y])
"#"
"L"))
"#" (fn [data [x y]] (if (five-or-more-occupied-seen-seats? data [x y])
"L"
"#"))})
(defn next-seat [data rules [x y]]
((rules (get-in data [x y])) data [x y]))
((rules (get-in data [0 0])) data [0 0])
(next-seat data rules [9 9])
(defn all-x-ys [data]
(for [x (range (count data))
y (range (count (first data)))]
[x y]))
(def x-ys (all-x-ys data))
(loop [old-data []
new-data data]
(if (= old-data new-data)
(count (filter #{"#"} (flatten new-data)))
(recur new-data (mapv vec
(partition
(count (first data))
(mapv
(partial next-seat new-data rules)
x-ys))))))
;; day 12
(def data (->> (slurp "input12.txt")
((fn [v] (str/split v #"\n")))
(map (fn [v]
(let [[_ inst n] (re-find #"(\w)(\d+)" v)]
[inst (Long/parseLong n)])))))
(def initial-state {:dir "E"
"S" 0
"N" 0
"E" 0
"W" 0})
(def rotate {"L" {90 {"N" "W"
"W" "S"
"S" "E"
"E" "N"}
180 {"N" "S"
"S" "N"
"W" "E"
"E" "W"}
270 {"N" "E"
"W" "N"
"S" "W"
"E" "S"}}
"R" {90 {"N" "E"
"E" "S"
"S" "W"
"W" "N"}
180 {"N" "S"
"S" "N"
"W" "E"
"E" "W"}
270 {"N" "W"
"W" "S"
"S" "E"
"E" "N"}}})
(def state (reduce
(fn [{dir :dir :as state} [instraction n]]
(case instraction
"F" (update state dir + n)
("L" "R") (assoc state :dir (get-in rotate [instraction n dir]))
("N" "S" "W" "E") (update state instraction + n)))
initial-state
data))
(+ (Math/abs (- (state "N") (state "S")))
(Math/abs (- (state "E") (state "W"))))
;; part 2
;;
(def data (->> (slurp "input12.txt")
((fn [v] (str/split v #"\n")))
(map (fn [v]
(let [[_ inst n] (re-find #"(\w)(\d+)" v)]
[inst (Long/parseLong n)])))))
(defn rotate [{{E "E" W "W" S "S" N "N"} :waypoint :as state}
dir
degree]
(assoc state :waypoint (get-in {"L" {90 {"N" E
"W" N
"S" W
"E" S}
180 {"N" S
"S" N
"W" E
"E" W}
270 {"N" W
"E" N
"S" E
"W" S}}
"R" {90 {"N" W
"E" N
"S" E
"W" S}
180 {"N" S
"S" N
"W" E
"E" W}
270 {"N" E
"W" N
"S" W
"E" S}}}
[dir degree])))
(rotate initial-state "R" 90)
(def initial-state {:waypoint {"E" 10
"N" 1
"W" 0
"S" 0}
"S" 0
"N" 0
"E" 0
"W" 0})
(defn move-forward [{waypoint :waypoint :as from} times]
(reduce (fn [state [dir n]] (update state dir + (* n times)))
from
waypoint))
(move-forward initial-state 10)
(def state (reduce
(fn [state [instruction n]]
(case instruction
"F" (move-forward state n)
("L" "R") (rotate state instruction n)
("N" "S" "W" "E") (update-in state [:waypoint instruction] + n)))
initial-state
data))
(+ (Math/abs (- (state "N") (state "S")))
(Math/abs (- (state "E") (state "W"))))
:a)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment