-
Notifications
You must be signed in to change notification settings - Fork 6
/
day03.clj
46 lines (37 loc) · 1.73 KB
/
day03.clj
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
(ns advent-2021-clojure.day03
(:require
[advent-2021-clojure.utils :refer [parse-binary]]
[clojure.string :as str]))
(defn parse-nums [input] (->> input str/split-lines (map parse-binary)))
(defn range-down-from [n] (range n -1 -1))
(defn most-significant-bit [nums]
(let [n (apply max nums)]
(int (/ (Math/log n) (Math/log 2)))))
(defn bit-diff [nums bit]
(reduce #(if (bit-test %2 bit) (inc %1) (dec %1))
0
nums))
(defn most-common-bit [nums bit] (if (neg-int? (bit-diff nums bit)) 0 1))
(defn least-common-bit [nums bit] (if (neg-int? (bit-diff nums bit)) 1 0))
(defn one-pass-bit-check [nums bit-fn]
(->> (range-down-from (most-significant-bit nums))
(map (partial bit-fn nums))
(apply str)
parse-binary))
(defn multi-pass-bit-check [nums bit-fn]
(first (reduce (fn [remaining bit] (if (= 1 (count remaining))
(reduced remaining)
(let [test (= 1 (bit-fn remaining bit))]
(filter #(= test (bit-test % bit)) remaining))))
nums
(range-down-from (most-significant-bit nums)))))
(defn gamma-rate [nums] (one-pass-bit-check nums most-common-bit))
(defn epsilon-rate [nums] (one-pass-bit-check nums least-common-bit))
(defn oxygen-generator-rating [nums] (multi-pass-bit-check nums most-common-bit))
(defn co2-scrubber-rating [nums] (multi-pass-bit-check nums least-common-bit))
(defn multiply-rates [input & rate-fns]
(->> (parse-nums input)
((apply juxt rate-fns))
(apply *)))
(defn part1 [input] (multiply-rates input gamma-rate epsilon-rate))
(defn part2 [input] (multiply-rates input oxygen-generator-rating co2-scrubber-rating))