-
-
Save galuque/fdeba14c6103bf6482b6f7c53fd645db to your computer and use it in GitHub Desktop.
AOC_2021_clj
This file contains 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
(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 | |
) |
This file contains 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
(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 | |
) |
This file contains 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
(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 | |
) |
This file contains 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
(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 | |
) | |
This file contains 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
(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 | |
) |
This file contains 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
(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 | |
) |
This file contains 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
(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 | |
) |
This file contains 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
(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