From a496300ed475c87de6a17a79ff6ba6f0ee607ab8 Mon Sep 17 00:00:00 2001 From: Nikita Hasert Date: Sat, 16 Dec 2023 12:34:43 +0100 Subject: [PATCH] Day 16: Solve part 1 and 2 --- src/advent_of_code_2023/day15.clj | 64 +++++++++++++++++++++++-- test/advent_of_code_2023/day15_test.clj | 21 ++++---- 2 files changed, 73 insertions(+), 12 deletions(-) diff --git a/src/advent_of_code_2023/day15.clj b/src/advent_of_code_2023/day15.clj index 7c6da76..243e3d4 100644 --- a/src/advent_of_code_2023/day15.clj +++ b/src/advent_of_code_2023/day15.clj @@ -2,8 +2,66 @@ (:require [advent-of-code-2023.utils.string :as u])) -(defn parse-input [input]) +(defn parse-input [input] + (mapv (fn [ascii] + (let [op (re-find #"=|-" ascii) + [label focal-length] (u/split-sections ascii #"=|-")] + (if (= op "=") + [ascii label :assign (Long/parseLong focal-length)] + [ascii label :remove]))) + (u/split-sections input #","))) -(defn day15-1 [parsed-input]) +(defonce ^:private ascii-hash + (memoize (fn [ascii] + (reduce (fn [^long cv ^long a] (-> cv (+ a) (* 17) (rem 256))) + 0 (mapv long ascii))))) -(defn day15-2 [parsed-input]) \ No newline at end of file +(defn day15-1 [lenses] + (transduce + (comp + (map first) + (map ascii-hash)) + + lenses)) + +(defn- add-lens [{:keys [positions] :as b} label focal-length] + (let [ah (ascii-hash label) + relevant-box (positions ah) + pos (or (get relevant-box label) (count relevant-box))] + (-> b + (assoc-in ,,, [:focal-lengths label] focal-length) + (assoc-in ,,, [:positions ah label] pos)))) + +(defn- remove-lens [{:keys [positions] :as b} label] + (let [ah (ascii-hash label) + relevant-box (positions ah)] + (if-let [pos (get relevant-box label)] + (transduce + (comp + (filter (fn [[_ ^long p]] (< ^long pos p))) + (map first)) + (fn + ([box] box) + ([box lbl] + (update-in box [:positions ah lbl] dec))) + (update-in b [:positions ah] dissoc label) relevant-box) + b))) + +(defn- focus-power [{:keys [focal-lengths positions]}] + (transduce + (comp + (mapcat (fn [[^long box-nr order]] + (mapv (fn [[lbl ^long pos]] (* (inc box-nr) + (inc pos) + ^long (focal-lengths lbl))) + order)))) + + positions)) + +(defn day15-2 [lenses] + (focus-power + (reduce (fn [boxes [_ label op focal-length]] + (if (= op :assign) + (add-lens boxes label focal-length) + (remove-lens boxes label))) + {:focal-lengths {} + :positions {}} + lenses))) \ No newline at end of file diff --git a/test/advent_of_code_2023/day15_test.clj b/test/advent_of_code_2023/day15_test.clj index fe50fcb..4f07779 100644 --- a/test/advent_of_code_2023/day15_test.clj +++ b/test/advent_of_code_2023/day15_test.clj @@ -4,26 +4,29 @@ [advent-of-code-2023.day15 :refer :all] [advent-of-code-2023.test-utils :as tu])) -(defonce ^:private example-input (parse-input "")) +(defonce ^:private example-ascii "HASH") + +(defonce ^:private example-input + (parse-input "rn=1,cm-,qp=3,cm=2,qp-,pc=4,ot=9,ab=5,pc-,pc=6,ot=7")) (def ^:private input (parse-input (tu/slurp-input "resources/day15.txt"))) +(deftest day15-1-example-ascii-test + (testing "day15-1 example ascii" + (is (= 52 (day15-1 [[example-ascii nil]]))))) + (deftest day15-1-example-test (testing "day15-1 example" - (is (= nil - (day15-1 example-input))))) + (is (= 1320 (day15-1 example-input))))) (deftest day15-1-test (testing "day15-1" - (is (= nil - (day15-1 input))))) + (is (= 504449 (day15-1 input))))) (deftest day15-2-example-test (testing "day15-2 example" - (is (= nil - (day15-2 example-input))))) + (is (= 145 (day15-2 example-input))))) (deftest day15-2-test (testing "day15-2" - (is (= nil - (day15-2 input))))) + (is (= 262044 (day15-2 input)))))