Skip to content

Instantly share code, notes, and snippets.

@galuque
Last active December 8, 2021 15:01
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
Star You must be signed in to star a gist
Save galuque/fdeba14c6103bf6482b6f7c53fd645db to your computer and use it in GitHub Desktop.
AOC_2021_clj
(ns io.github.galuque.aoc-2021.day-1
(:require [clojure.java.io :as io]
[clojure.string :as str]))
(def input
(->> "day_1/input.txt"
io/resource
slurp
str/split-lines
(mapv parse-long)))
(def sample-input [199
200
208
210
200
207
240
269
260
263])
(defn part-1 [coll]
(->> coll
(partition 2 1)
(filter (fn [[a b]] (< a b)))
count))
(comment
(part-1 sample-input)
;; => 7
(part-1 input)
;; => 1715
)
(defn part-2
[window-size coll]
(->> coll
(partition window-size 1)
(map #(apply + %))
part-1))
(comment
(part-2 3 sample-input)
;; => 5
(part-2 3 input)
;; => 1739
)
(ns io.github.galuque.aoc-2021.day-2
(:require [clojure.java.io :as io]
[clojure.string :as str]))
(def input
(->> "day_2/input.txt"
io/resource
slurp))
(def sample-input "forward 5
down 5
forward 8
up 3
down 8
forward 2")
(defn parse-input [input]
(->> input
str/split-lines
(map (fn [s] (str/split s #" ")))
(map (fn [[direction amount]] [(keyword direction) (parse-long amount)]))))
(def parsed-sample-input (parse-input sample-input))
(def parsed-input (parse-input input))
(def inital-position {:horizontal 0
:depth 0
:aim 0})
(defn next-position [current-position [instruction amount]]
(case instruction
:forward (update current-position :horizontal + amount)
:down (update current-position :depth + amount)
:up (update current-position :depth - amount)))
(defn final-product [{:keys [horizontal depth]}]
(* horizontal depth))
(defn part-1 [input]
(->> input
(reduce next-position inital-position)
final-product))
(comment
(part-1 parsed-sample-input)
;; => 150
(part-1 parsed-input)
;; => 1727835
)
(defn next-position-2 [current-position [instruction amount]]
(case instruction
:forward (-> current-position
(update :horizontal + amount)
(update :depth + (* amount (:aim current-position))))
:down (update current-position :aim + amount)
:up (update current-position :aim - amount)))
(defn part-2 [input]
(->> input
(reduce next-position-2 inital-position)
final-product))
(comment
(part-2 parsed-sample-input)
;; => 900
(part-2 parsed-input)
;; => 1544000595
)
(ns io.github.galuque.aoc-2021.day-3
(:require [clojure.java.io :as io]
[clojure.string :as str]))
(def input
(-> "day_3/input.txt"
io/resource
slurp))
(def sample-input "00100
11110
10110
10111
10101
01111
00111
11100
10000
11001
00010
01010
")
(defn parse-input [input]
(->> input
str/split-lines
(mapv #(str/split % #""))
(mapv #(mapv parse-long %))))
(defn transpose [mx]
(apply mapv vector mx))
(defn parse-binary [s]
(Long/valueOf s 2))
(defn bit-frequecies [mx]
(->> mx
transpose
(mapv frequencies)))
(def coeff {:gamma []
:epsilon []})
(defn get-most-common-bit [m]
(let [zeroes (m 0)
ones (m 1)]
(if (<= zeroes ones) 1 0)))
(defn get-least-common-bit [m]
(let [zeroes (m 0)
ones (m 1)]
(if (<= zeroes ones) 0 1)))
(defn report [coeff m]
(let [most-common-bit (get-most-common-bit m)
least-common-bit ({1 0 0 1} most-common-bit)]
(-> coeff
(update :gamma conj most-common-bit)
(update :epsilon conj least-common-bit))))
(defn part-1 [input]
(let [freqs (bit-frequecies input)
rates (reduce report coeff freqs)
gamma (-> (:gamma rates) str/join parse-binary)
epsilon (-> (:epsilon rates) str/join parse-binary)]
(* gamma epsilon)))
(comment
(part-1 (parse-input sample-input))
;; => 198
(part-1 (parse-input input))
;; => 2640986
)
(defn find-rating [criteria-fn input]
(loop [numbers input
idx 0]
(let [bit (-> numbers bit-frequecies (nth idx) criteria-fn)
filtered (into []
(filter (fn [v] (= bit (nth v idx))))
numbers)]
(if (= 1 (count filtered))
(first filtered)
(recur filtered (inc idx))))))
(defn part-2 [input]
(let [o2-vec (find-rating get-most-common-bit input)
co2-vec (find-rating get-least-common-bit input)
o2 (-> o2-vec str/join parse-binary)
co2 (-> co2-vec str/join parse-binary)]
(* o2 co2)))
(comment
(part-2 (parse-input sample-input))
;; => 230
(part-2 (parse-input input))
;; => 6822109
)
(ns io.github.galuque.aoc-2021.day-4
(:require [clojure.java.io :as io]
[clojure.string :as str]))
(def input (-> "day_4/input.txt"
io/resource
slurp))
(def sample-input "7,4,9,5,11,17,23,2,0,14,21,24,10,16,13,6,15,25,12,22,18,20,8,19,3,26,1
22 13 17 11 0
8 2 23 4 24
21 9 14 16 7
6 10 3 18 5
1 12 20 15 19
3 15 0 2 22
9 18 13 17 5
19 8 7 25 23
20 11 10 24 4
14 21 16 12 6
14 21 17 24 4
10 16 15 9 19
18 8 23 26 20
22 11 13 6 5
2 0 12 3 7")
(def grid-size 5)
(defn transpose [mx]
(apply mapv vector mx))
(defn split-input [input]
(let [[numbers & cards] (->> input
str/split-lines
(remove empty?))]
[numbers cards]))
(defn parse-numbers [numbers]
(mapv parse-long (str/split numbers #",")))
(defn parse-cards [cards]
(->> cards
(map (comp (partial mapv parse-long)
(partial re-seq #"\d+")))
(partition grid-size)))
(defn parse-input [input]
(let [[numbers cards] (split-input input)]
[(parse-numbers numbers) (parse-cards cards)]))
(defn mark [card draw]
(map #(replace {draw nil} %) card))
(defn bingo? [card]
(or (some (partial every? nil?)
card)
(some (partial every? nil?)
(transpose card))))
(defn sum [v]
(reduce (fnil + 0 0) v))
(defn sum-card [card]
(sum (flatten card)))
(defn part-1 [[nums cards]]
(loop [cards cards
[draw & nums] nums]
(let [marked-cards (map #(mark % draw) cards)
bingo-card (first (filter bingo? marked-cards))]
(if bingo-card
(* draw (sum-card bingo-card))
(recur marked-cards nums)))))
(comment
(part-1 (parse-input sample-input))
;; => 4512
(part-1 (parse-input input))
;; => 32844
)
(defn part-2 [[nums cards]]
(loop [cards cards
[draw & nums] nums]
(let [marked-cards (map #(mark % draw) cards)
remaining-cards (remove bingo? marked-cards)]
(if (empty? remaining-cards)
(* draw (sum-card (first marked-cards)))
(recur remaining-cards nums)))))
(comment
(part-2 (parse-input sample-input))
;; => 1924
(part-2 (parse-input input))
;; => 4920
)
(ns io.github.galuque.aoc-2021.day-5
(:require [clojure.java.io :as io]
[clojure.string :as str]
[clojure.set :as set]))
(def input (-> "day_5/input.txt"
io/resource
slurp))
(def sample-input "0,9 -> 5,9
8,0 -> 0,8
9,4 -> 3,4
2,2 -> 2,1
7,0 -> 7,4
6,4 -> 2,0
0,9 -> 2,9
3,4 -> 1,4
0,0 -> 8,8
5,5 -> 8,2
")
(defn parse-point [s]
(mapv parse-long (str/split s #",")))
(defn parse-line [line]
(mapv parse-point line))
(defn parse-input [input]
(->> input
(re-seq #"\d+,\d+ -> \d+,\d+")
(mapv (comp
(partial parse-line)
(partial re-seq #"\d+,\d+")))))
(defn horizontal-line? [line]
(let [[_ y1 _ y2] (flatten line)]
(= y1 y2)))
(defn vertical-line? [line]
(let [[x1 _ x2 _] (flatten line)]
(= x1 x2)))
(defn line->points* [a b common]
(partition 2 (interleave (repeat common) (range a (inc b)))))
(defn diag-range [a b]
(if (< a b)
(range a (inc b))
(range a (dec b) -1 )))
(defn line->points [line]
(let [[x1 y1 x2 y2] (flatten line)]
(cond
(vertical-line? line)
(if (< y1 y2)
(line->points* y1 y2 x1)
(line->points* y2 y1 x1))
(horizontal-line? line)
(if (< x1 x2)
(map reverse (line->points* x1 x2 y1))
(map reverse (line->points* x2 x1 y1)))
:else
(partition 2
(interleave (diag-range x1 x2)
(diag-range y1 y2))))))
(defn intersections [line1 line2]
(set/intersection (set (line->points line1))
(set (line->points line2))))
(defn solution [lines]
(let [inters (for [line1 lines
line2 lines
:when (not= line1 line2)]
(intersections line1 line2))]
(->> inters
(filter not-empty)
frequencies
(filter #(-> % val (>= 2)))
(map first)
(apply set/union)
count)))
(defn part-1 [input]
(let [lines (filterv (some-fn vertical-line?
horizontal-line?)
input)]
(solution lines)))
(comment
(part-1 (parse-input sample-input))
;; => 5
(part-1 (parse-input input))
;; => 6710
)
(def part-2 solution)
(comment
(part-2 (parse-input sample-input))
;; => 12
(part-2 (parse-input input))
;; => 20121
)
(ns io.github.galuque.aoc-2021.day-6
(:require [clojure.java.io :as io]
[clojure.string :as str]))
(def input (->> "day_6/input.txt"
io/resource
slurp))
(def sample-input "3,4,3,1,2")
(def init-ages (into [] (repeat 9 0)))
(defn ages-vec [coll [v f]]
(update coll v + f))
(defn parse-input [input]
(->> (str/split (str/trim input) #",")
(map parse-long)
frequencies
(reduce ages-vec init-ages)))
(defn day-passed [ages]
(reduce conj [(subvec ages 1 7)
(+ (nth ages 7) (nth ages 0))
(nth ages 8)
(nth ages 0)]))
(defn count-fish [days ages]
(->> ages
(iterate day-passed)
(take (inc days))
last
(apply +)))
(def part-1 (partial count-fish 80))
(comment
(part-1 (parse-input sample-input))
;; => 5934
(part-1 (parse-input input))
;; => 374994
)
(def part-2 (partial count-fish 256))
(comment
(part-2 (parse-input sample-input))
;; => 26984457539
(part-2 (parse-input input))
;; => 1686252324092
)
(ns io.github.galuque.aoc-2021.day-7
(:require [clojure.java.io :as io]
[clojure.string :as str]
[clojure.java.math :as m]))
(set! *warn-on-reflection* true)
(set! *unchecked-math* :warn-on-boxed)
(def input (->> "day_7/input.txt" io/resource slurp))
(def sample-input "16,1,2,0,4,2,7,1,2,14")
(defn parse-input [input]
(->> (str/split input #",")
(mapv parse-long)))
(def sum (partial apply +))
(def min* (partial apply min))
(def max* (partial apply max))
(defn cost [^long n coll]
(->> coll
(map (fn [^long a] (m/abs (- n a))))
sum))
(defn solution [cost input]
(min* (for [n (range (min* input) (inc ^long (max* input)))]
(cost n input))))
(def part-1 (partial solution cost))
(comment
(part-1 (parse-input sample-input))
;; => 37
(part-1 (parse-input input))
;; => 357353
)
(defn sum-range [^long n]
(/ (* n (+ n 1)) 2))
(defn cost-2 [^long n coll]
(->> coll
(map (fn [^long a]
(sum-range (m/abs (- n a)))))
sum))
(def part-2 (partial solution cost-2))
(comment
(part-2 (parse-input sample-input))
;; => 168
(part-2 (parse-input input))
;; => 104822130
)
(ns io.github.galuque.aoc-2021.day-8
(:require [clojure.java.io :as io]
[clojure.string :as str]
[clojure.set :as set]))
(def input (-> "day_8/input.txt" io/resource slurp))
(def sample-input (-> "day_8/sample.txt" io/resource slurp))
(defn parse-input [input]
(->> (str/split-lines input)
(map #(str/split % #" "))))
(defn part-1 [input]
(->> input
(mapcat #(drop 11 %))
(map count)
(filter #(or (= 2 %) (= 3 %) (= 4 %) (= 7 %)))
count))
(comment
(part-1 (parse-input sample-input))
;; => 26
(part-1 (parse-input input))
;; => 245
)
(def set-first-filter (comp set first filter))
(defn decode [entry]
(let [ssd1 (set-first-filter #(= 2 (count %)) entry)
ssd7 (set-first-filter #(= 3 (count %)) entry)
ssd4 (set-first-filter #(= 4 (count %)) entry)
ssd8 (set-first-filter #(= 7 (count %)) entry)
ssd3 (set-first-filter (fn [s]
(and (= 5 (count s))
(set/subset? ssd1 (set s))))
entry)
ssd9 (set-first-filter (fn [s]
(and (= 6 (count s))
(set/subset? ssd4 (set s))))
entry)
ssd5 (set-first-filter (fn [s]
(and (= 5 (count s))
(not (set/subset? ssd1 (set s)))
(set/subset? (set s) ssd9)))
entry)
ssd2 (set-first-filter (fn [s]
(and (= 5 (count s))
(not= (set s) ssd5)
(not= (set s) ssd3)))
entry)
ssd6 (set-first-filter (fn [s]
(and (= 6 (count s))
(set/subset? ssd5 (set s))
(not (set/subset? ssd4 (set s)))))
entry)
ssd0 (set-first-filter (fn [s]
(and (= 6 (count s))
(set/subset? (set/union (set/difference ssd6
ssd3)
ssd1)
(set s))))
entry)]
{ssd0 0
ssd1 1
ssd2 2
ssd3 3
ssd4 4
ssd5 5
ssd6 6
ssd7 7
ssd8 8
ssd9 9}))
(defn solve [entry]
(map (decode entry) (map set entry)))
(defn part-2 [input]
(->> input
(map (fn [coll]
(remove #(= "|" %) coll)))
(map solve)
(map #(drop 10 %))
(map #(parse-long (str/join (map str %))))
(apply +)))
(comment
(part-2 (parse-input sample-input))
;; => 61229
(part-2 (parse-input input))
;; => 983026
)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment