291 lines
8.2 KiB
Clojure
291 lines
8.2 KiB
Clojure
(ns aoc2025
|
|
(:require [clojure.string :as str]))
|
|
|
|
(defn get-input [day] (slurp (str "2025/day" day "-input.txt")))
|
|
|
|
(defn remove-index
|
|
"Removes an item at the specified position in a vector"
|
|
[coll ^long index]
|
|
(-> (into (subvec coll 0 index)
|
|
(subvec coll (inc index)))
|
|
(with-meta (meta coll))))
|
|
|
|
(def directions {:N [-1 0] :S [1 0] :W [0 -1] :E [0 1]
|
|
:NW [-1 -1] :NE [-1 1] :SW [1 -1] :SE [1 1]})
|
|
;; _____ __
|
|
;; | __ \ /_ |
|
|
;; | | | | __ _ _ _ | |
|
|
;; | | | |/ _` | | | | | |
|
|
;; | |__| | (_| | |_| | | |
|
|
;; |_____/ \__,_|\__, | |_|
|
|
;; __/ |
|
|
;; |___/
|
|
|
|
(def day1-input-test
|
|
"L68
|
|
L30
|
|
R48
|
|
L5
|
|
R60
|
|
L55
|
|
L1
|
|
L99
|
|
R14
|
|
L82")
|
|
|
|
(defn day1 [input zero-count-fn]
|
|
(let [sequence (map (fn [line]
|
|
[(if (= "R" (str (first line)))
|
|
#'+
|
|
#'-)
|
|
(parse-long (str/join (rest line)))])
|
|
(str/split-lines input))]
|
|
(loop [s sequence
|
|
curr 50
|
|
zero-count 0]
|
|
(if (not (seq s))
|
|
zero-count
|
|
(let [[f amount] (first s)
|
|
new-dial-pos (mod (f curr amount) 100)
|
|
spins (zero-count-fn curr (f amount) new-dial-pos)]
|
|
(println curr new-dial-pos amount spins)
|
|
(recur (rest s) new-dial-pos (+ zero-count spins)))))))
|
|
|
|
(defn day1-p1 [input]
|
|
(day1 input (fn [_ _ new-dial-pos] (if (zero? new-dial-pos) 1 0))))
|
|
|
|
(defn day1-p2 [input]
|
|
(day1 input (fn [curr rotation _]
|
|
(let [amount (abs rotation)]
|
|
(if (and (neg? rotation)
|
|
(not (zero? curr)))
|
|
(quot (+ (- 100 curr) (abs amount)) 100)
|
|
(quot (+ curr amount) 100))))))
|
|
|
|
(comment
|
|
(day1-p1 day1-input-test)
|
|
(day1-p1 (get-input 1))
|
|
(day1-p2 day1-input-test)
|
|
(day1-p2 (get-input 1))
|
|
:-)
|
|
|
|
;; _____ ___
|
|
;; | __ \ |__ \
|
|
;; | | | | __ _ _ _ ) |
|
|
;; | | | |/ _` | | | | / /
|
|
;; | |__| | (_| | |_| | / /_
|
|
;; |_____/ \__,_|\__, | |____|
|
|
;; __/ |
|
|
;; |___/
|
|
|
|
(def day2-input-test
|
|
"11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124")
|
|
|
|
(defn day2-parse-input [input]
|
|
(->> (str/split (str/trim input) #",")
|
|
(map #(str/split % #"-"))
|
|
(map #(mapv parse-long %))
|
|
(map (fn [[lo hi]] (range lo (inc hi))))
|
|
flatten))
|
|
|
|
(defn day2-p1 [input]
|
|
(->> input
|
|
(keep #(let [num-str (str %)
|
|
length (count num-str)
|
|
half (/ length 2)]
|
|
(when (and (even? length)
|
|
(= (subs num-str 0 half)
|
|
(subs num-str half length)))
|
|
%)))
|
|
(reduce +)))
|
|
|
|
(defn day2-p2 [input]
|
|
(->> input
|
|
(keep #(let [num-str (str %)
|
|
length (count num-str)]
|
|
(loop [p-size (quot length 2)]
|
|
(cond
|
|
(zero? p-size)
|
|
nil
|
|
(apply = (partition-all p-size num-str))
|
|
%
|
|
:else
|
|
(recur (dec p-size))))))
|
|
(reduce +)))
|
|
|
|
(comment
|
|
(day2-p1 (day2-parse-input day2-input-test))
|
|
(day2-p1 (day2-parse-input (get-input 2)))
|
|
|
|
(day2-p2 (day2-parse-input day2-input-test))
|
|
(day2-p2 (day2-parse-input (get-input 2)))
|
|
:-)
|
|
|
|
;; _____ ____
|
|
;; | __ \ |___ \
|
|
;; | | | | __ _ _ _ __) |
|
|
;; | | | |/ _` | | | | |__ <
|
|
;; | |__| | (_| | |_| | ___) |
|
|
;; |_____/ \__,_|\__, | |____/
|
|
;; __/ |
|
|
;; |___/
|
|
|
|
(def day3-input-test
|
|
"987654321111111
|
|
811111111111119
|
|
234234234234278
|
|
818181911112111")
|
|
|
|
(defn day3-get-max-battery [total-digits bank]
|
|
(loop [remaining (dec total-digits)
|
|
curr-idx 0
|
|
nums []]
|
|
(if (= (count nums) total-digits)
|
|
(reduce (fn [acc digit] (+ (* acc 10) digit)) 0 nums)
|
|
(let [subbank (subvec bank curr-idx (- (count bank) remaining))
|
|
[idx max-num] (->> (map-indexed vector subbank)
|
|
(reduce (fn [[idx max] [i n]]
|
|
(if (> n max)
|
|
[i n]
|
|
[idx max]))
|
|
[-1 -1]))]
|
|
(recur (dec remaining) (+ curr-idx idx 1) (conj nums max-num))))))
|
|
|
|
(defn day3 [total-digits input]
|
|
(->> (str/split-lines input)
|
|
(mapv #(mapv (fn [c] (Character/digit c 10)) (vec %)))
|
|
(map (partial day3-get-max-battery total-digits))
|
|
(reduce +)))
|
|
|
|
(comment
|
|
(day3 2 day3-input-test)
|
|
(day3 2 (get-input 3))
|
|
(day3 12 day3-input-test)
|
|
(day3 12 (get-input 3))
|
|
:-)
|
|
|
|
;; _____ _ _
|
|
;; | __ \ | || |
|
|
;; | | | | __ _ _ _ | || |_
|
|
;; | | | |/ _` | | | | |__ _|
|
|
;; | |__| | (_| | |_| | | |
|
|
;; |_____/ \__,_|\__, | |_|
|
|
;; __/ |
|
|
;; |___/
|
|
|
|
(def day4-input-test
|
|
"..@@.@@@@.
|
|
@@@.@.@.@@
|
|
@@@@@.@.@@
|
|
@.@@@@..@.
|
|
@@.@@@@.@@
|
|
.@@@@@@@.@
|
|
.@.@.@.@@@
|
|
@.@@@.@@@@
|
|
.@@@@@@@@.
|
|
@.@.@@@.@.")
|
|
|
|
(defn day4-adjacent-count [grid [row col]]
|
|
(when (= \@ (get-in grid [row col]))
|
|
(->> (for [[dir [dy dx]] directions]
|
|
(get-in grid [(+ row dy) (+ col dx)]))
|
|
concat
|
|
(filter #(= % \@))
|
|
count)))
|
|
|
|
(defn day4-p1 [input]
|
|
(let [grid (str/split-lines input)]
|
|
(->> (for [row (range (count grid))
|
|
col (range (count (first grid)))]
|
|
(day4-adjacent-count grid [row col]))
|
|
(remove nil?)
|
|
(filter #(< % 4))
|
|
count)))
|
|
|
|
(defn day4-p2 [input]
|
|
(let [grid (str/split-lines input)
|
|
ROWS (count grid)
|
|
COLS (count (first grid))]
|
|
(loop [grid grid
|
|
removed-count 0]
|
|
(let [marked-cells (->> (for [row (range ROWS)
|
|
col (range COLS)]
|
|
(when-let [adj-count (day4-adjacent-count grid [row col])]
|
|
(when (< adj-count 4)
|
|
[row col])))
|
|
(remove nil?)
|
|
set)]
|
|
(if (empty? marked-cells)
|
|
removed-count
|
|
(recur (->> (for [row (range ROWS)
|
|
col (range COLS)]
|
|
(if (contains? marked-cells [row col])
|
|
\x
|
|
(get-in grid [row col])))
|
|
(partition COLS)
|
|
(mapv #(reduce str %)))
|
|
(+ removed-count (count marked-cells))))))))
|
|
|
|
(comment
|
|
(day4-p1 day4-input-test)
|
|
(day4-p1 (get-input 4))
|
|
(day4-p2 day4-input-test)
|
|
(day4-p2 (get-input 4))
|
|
:-)
|
|
|
|
;; _____ _____
|
|
;; | __ \ | ____|
|
|
;; | | | | __ _ _ _ | |__
|
|
;; | | | |/ _` | | | | |___ \
|
|
;; | |__| | (_| | |_| | ___) |
|
|
;; |_____/ \__,_|\__, | |____/
|
|
;; __/ |
|
|
;; |___/
|
|
|
|
(def day5-input-test
|
|
"3-5
|
|
10-14
|
|
16-20
|
|
12-18
|
|
|
|
1
|
|
5
|
|
8
|
|
11
|
|
17
|
|
32")
|
|
|
|
(defn day5-parse-input [input]
|
|
(let [[ranges ids] (->> (str/split input #"\n\n")
|
|
(map #(str/split-lines %)))]
|
|
[(map #(mapv parse-long (str/split % #"-")) ranges)
|
|
(map parse-long ids)]))
|
|
|
|
(defn day5-p1 [input]
|
|
(let [[ranges ids] (day5-parse-input input)]
|
|
(->> (map #(some (fn [[min max]] (<= min % max)) ranges) ids)
|
|
(remove nil?)
|
|
count)))
|
|
|
|
(defn day5-p2 [input]
|
|
(let [[ranges _] (day5-parse-input input)]
|
|
(->> (reduce (fn [acc elem]
|
|
(if (empty? acc)
|
|
(list elem)
|
|
(let [next-min (first elem)
|
|
[curr-min curr-max] (first acc)]
|
|
(if (<= curr-min next-min curr-max)
|
|
(cons [curr-min (max (second elem) curr-max)] (rest acc))
|
|
(cons elem acc)))))
|
|
'()
|
|
(sort ranges))
|
|
(map #(inc (- (second %) (first %))))
|
|
(reduce +))))
|
|
|
|
(comment
|
|
(day5-p1 day5-input-test)
|
|
(day5-p1 (get-input 5))
|
|
(day5-p2 day5-input-test)
|
|
(day5-p2 (get-input 5))
|
|
:-)
|