Compare commits

..

78 Commits

Author SHA1 Message Date
56738fd7f9 Merge branch 'master' of git.ajet.fyi:ajet/advent-of-code 2026-05-15 09:39:52 -04:00
Adam Jeniski
b89c7ce3f2 do day 13 2026-05-15 09:27:49 -04:00
Adam Jeniski
a1db8ae128 do day 12 2026-05-15 09:27:46 -04:00
Adam Jeniski
e6357d9802 do day 11 2026-05-15 09:27:43 -04:00
b62c9346f5 cons is for boomers 2026-05-13 07:55:24 -04:00
505453974b refactor day 03 2026-05-13 07:39:51 -04:00
0aed472a32 do 2017 day 9 2026-05-04 08:47:30 -04:00
Adam Jeniski
9703c017a9 do 2017 day 8 2026-05-04 07:02:38 -04:00
Adam Jeniski
733c833f66 do 2017 day 7 2026-05-04 07:02:34 -04:00
1087a7649b do 2017 day 6 2026-04-26 11:01:02 -04:00
5077215205 do 2017 day 5 2026-04-26 11:00:57 -04:00
Adam Jeniski
8ff632503f use #() > (fn [] ,,,) 2026-04-23 15:39:59 -04:00
Adam Jeniski
a889d088ae franz newline 2026-04-23 15:38:55 -04:00
Adam Jeniski
484e507af1 init 2017 2026-04-23 15:36:25 -04:00
7057247936 do day 12 2025-12-31 19:37:09 -10:00
52e2bf8202 redundant do 2025-12-29 09:12:51 -05:00
0616318a09 add default pretty printed tap> 2025-12-29 09:11:22 -05:00
e851c41935 fix orderings to match comment better 2025-12-29 08:46:51 -05:00
ajet
5a1773ca77 update gitignore 2025-12-26 21:56:10 -05:00
db1a89199b golf 2025-12-22 18:06:10 -05:00
e51b3296d6 golf 2025-12-22 18:02:29 -05:00
14ac947ae3 golf 2025-12-22 18:00:33 -05:00
8fa11862e1 use java deps for z3 2025-12-22 17:55:11 -05:00
d55ca4c019 franz newline 2025-12-19 08:52:47 -10:00
f88a28cad2 finish day 11 2025-12-19 13:35:51 -05:00
d04209497b do day11 part 1 2025-12-19 08:07:31 -10:00
9ea11f35c9 rename 2025-12-12 12:21:02 -10:00
50e6464eba golf 2025-12-12 12:19:40 -10:00
56a1bed93d rename, format 2025-12-12 09:31:42 -10:00
d379c21296 do day 10 2025-12-12 09:17:55 -10:00
a2492b2b2a renames 2025-12-09 06:33:04 -10:00
d2e6f920f3 simplify 2025-12-09 06:20:28 -10:00
aae7ad038b simplify 2025-12-08 22:32:23 -10:00
5ca7f15404 golf + comments 2025-12-08 22:29:46 -10:00
c47c11a973 golf 2025-12-08 22:20:28 -10:00
055a37a089 rename var 2025-12-08 22:18:16 -10:00
37c2786336 spacing 2025-12-08 22:16:53 -10:00
bcffe4e5bf golf 2025-12-08 22:14:19 -10:00
b0bbb1fcdb do day 9 2025-12-08 21:42:38 -10:00
9e57a7dffb golf 2025-12-08 15:08:59 -10:00
4e5cba07bf golf 2025-12-08 15:07:48 -10:00
f70ba6d543 golf 2025-12-08 15:06:57 -10:00
4eae354f25 rename 2025-12-08 14:01:45 -10:00
da7b893c37 golf 2025-12-08 14:00:26 -10:00
e0fba7c72f remove dead code 2025-12-08 06:33:28 -10:00
4c101f2afa do day 8 2025-12-07 20:22:59 -10:00
4e548d4d40 do day 7 2025-12-06 20:03:01 -10:00
ac6c0097e6 golf 2025-12-06 05:58:21 -10:00
63746d88b8 remove lein repl history 2025-12-06 05:37:33 -10:00
c4cafb19b0 reduce superiority 2025-12-06 05:36:39 -10:00
2ef3eb8d2c inline var 2025-12-05 20:46:33 -10:00
b0d0cf5b59 golf 2025-12-05 20:44:22 -10:00
fdd38bd6b1 franz newline 2025-12-05 20:36:52 -10:00
5289e1dfdf simplify 2025-12-05 20:34:10 -10:00
d853e89137 clean up 2025-12-05 20:31:57 -10:00
0093533054 do day 6 2025-12-05 20:20:15 -10:00
940135c14c do day 5 2025-12-05 12:00:47 -10:00
7f4c260855 do day3 2025-12-04 11:06:46 -10:00
6306a76b7e remove unused dep 2025-12-04 11:04:17 -10:00
a9b1c35984 do day 4 2025-12-04 09:53:17 -10:00
318092c1c5 do day 2 2025-12-04 09:53:10 -10:00
4d525dd3a7 happy holidays 2025 2025-12-01 11:06:15 -10:00
de3c367d1c do 2015 day 5 pt1 2025-11-27 07:17:43 -10:00
171a4d285d do 2015 day4 2025-11-27 07:17:23 -10:00
66c7ee02d4 rewrite day 1 with franz 2025-11-26 12:18:45 -10:00
0492cb1155 init 2015 2025-11-26 12:18:22 -10:00
116bc23a2c add readme 2025-10-27 14:31:13 -09:00
4418b4da78 init day17 part 1 2025-10-27 16:50:32 -04:00
eb2ca945da day 17 parse input 2025-10-27 09:57:26 -09:00
249fcb00b6 add prioirty map 2025-10-26 05:46:25 -09:00
23b5ed2e90 do day16 part 1 2025-10-26 05:35:27 -09:00
aae825a9df do day 22 2025-10-26 05:34:30 -09:00
463a291744 rename 2025-10-20 08:08:14 -09:00
f7b77d4fd0 simplify 2025-10-20 08:06:52 -09:00
b2339a21a6 day 20 init pt 1 2025-10-20 08:04:14 -09:00
5e55767409 format 2025-10-20 03:17:37 -09:00
Adam Jeniski
4a5ee3d100 fix comment 2025-10-19 11:50:50 -04:00
Adam Jeniski
1cd6a07cf8 golf 2025-10-19 11:49:57 -04:00
49 changed files with 6164 additions and 51 deletions
+3
View File
@@ -17,3 +17,6 @@ target/
.cpcache
.calva
.nrepl-port
## intellij nonsense
.idea
+3
View File
@@ -0,0 +1,3 @@
input/
.lein-repl-history
*.iml
+13
View File
@@ -0,0 +1,13 @@
(defproject org.ajet/advent-of-code "0.0.0-SNAPSHOT"
:description "my 2024 advent of code solutions in clojure"
:url "http://github.com/ajetski/advent-of-code"
:min-lein-version "2.0.0"
:jvm-opts ["-Xmx16g"]
:plugins [[cider/cider-nrepl "0.57.0"]]
:dependencies [[org.clojure/clojure "1.12.0"]
[org.clojure/data.priority-map "1.2.0"]
[org.clojure/math.combinatorics "0.3.0"]
[babashka/fs "0.5.23"]
[org.babashka/http-client "0.4.22"]
[org.clojure/core.match "1.1.0"]]
:source-paths ["src" "../shared/clj/src"])
+27
View File
@@ -0,0 +1,27 @@
(ns day01
(:require input-manager))
(def input (input-manager/get-input-raw 2015 01))
(def up? #{\(})
(def down? #{\)})
;; part 1
(-
(count (filter up? input))
(count (filter down? input)))
;; part 2
(loop [i 0
floor 0]
(cond
(< floor 0) i
(up? (.charAt input i))
(recur (inc i)
(inc floor))
:else
(recur (inc i)
(dec floor))))
+38
View File
@@ -0,0 +1,38 @@
(ns day02
(:require [input-manager]))
(defn parse-line
"s is a string in the form of lxwxh, whee l, w, and h are integral patterns"
[s]
(map parse-long (re-seq #"\d+" s)))
(def input (->> (input-manager/get-input 2015 2)
(map parse-line)))
(defn smallest-side [[l w h]]
(min (* l w)
(* h w)
(* l h)))
(defn paper-needed [[l w h :as args]]
(+ (* 2 (+ (* l w) (* w h) (* h l)))
(smallest-side args)))
;; part 1
(->> input
(map paper-needed)
(apply +))
(defn smallest-perimeter [[l w h]]
(* 2 (min (+ l w)
(+ h w)
(+ l h))))
(defn volume [[l w h]]
(* l w h))
;; part 2
(->> input
(map (juxt smallest-perimeter volume))
(map #(apply + %))
(apply +))
+26
View File
@@ -0,0 +1,26 @@
(ns day03
(:require [input-manager]
[clojure.set]))
(def input (input-manager/get-input-raw 2015 3))
(defn get-houses [input]
(->> input
(reduce (fn [[[x y] visited]
el]
(let [pos' (condp = el
\> [(inc x) y]
\< [(dec x) y]
\^ [x (inc y)]
\v [x (dec y)])]
[pos' (conj visited pos')]))
[[0 0] #{}])
second))
;; part 1
(count (get-houses input))
;; part 2
(count (clojure.set/union (get-houses (take-nth 2 input))
(get-houses (take-nth 2 (rest input)))))
+21
View File
@@ -0,0 +1,21 @@
(ns day04
(:require [input-manager]
[clojure.set])
(:import java.security.MessageDigest java.math.BigInteger))
(def input (input-manager/get-input-raw 2015 4))
(defn string->md5 [s]
(let [algorithm (MessageDigest/getInstance "MD5")
raw (.digest algorithm (.getBytes s))]
(format "%032x" (BigInteger. 1 raw))))
(defn solution [target-prefix]
(loop [i 0]
(let [md5 (string->md5 (str input i))]
(if (.startsWith md5 target-prefix)
i
(recur (inc i))))))
(solution "00000")
(solution "000000")
+14
View File
@@ -0,0 +1,14 @@
(ns day05
(:require [input-manager]
[clojure.string :as str]))
(def input (input-manager/get-input 2015 5))
(def bad #{"ab" "cd" "pq" "xy"})
;; part 1
(count (filter #(and (not (some (partial str/includes? %) bad))
(>= (count (filter #{\a \e \i \o \u} %)) 3)
(some (partial apply =) (concat (partition 2 %)
(partition 2 (rest %)))))
input))
+4
View File
@@ -0,0 +1,4 @@
input/
.lein-repl-history
.idea/
*.iml
+15
View File
@@ -0,0 +1,15 @@
(defproject org.ajet/advent-of-code "0.0.0-SNAPSHOT"
:description "my 2017 advent of code solutions in clojure"
:url "http://github.com/ajetski/advent-of-code"
:min-lein-version "2.0.0"
:jvm-opts ["-Xmx16g"]
:plugins [[cider/cider-nrepl "0.57.0"]]
:dependencies [[org.clojure/clojure "1.12.0"]
[org.clojure/data.priority-map "1.2.0"]
[org.clojure/math.combinatorics "0.3.0"]
[babashka/fs "0.5.23"]
[org.babashka/http-client "0.4.22"]
[org.clojure/core.match "1.1.0"]
[clj-python/libpython-clj "2.025"]
[tools.aqua/z3-turnkey "4.14.1"]]
:source-paths ["src" "../shared/clj/src"])
+23
View File
@@ -0,0 +1,23 @@
(ns day01
(:require input-manager))
(defn to-digit [c] (Character/digit c 10))
(def input (mapv to-digit (input-manager/get-input-raw 2017 01)))
(defn solve [offset]
(let [lookup (fn [idx]
(input (mod idx (count input))))]
(->> input
(map-indexed vector)
(filter (fn [[idx el]]
(= el (lookup (+ offset idx)))))
(map second)
(apply +))))
;; part 1
(solve 1)
;; part 2
(solve (/ (count input) 2))
+25
View File
@@ -0,0 +1,25 @@
(ns day02
(:require input-manager
core))
(def input (mapv (comp #(mapv parse-long %)
core/split-whitespace)
(input-manager/get-input 2017 02)))
;; part 1
(->> input
(map (comp #(apply - %)
(juxt #(apply max %)
#(apply min %))))
(apply +))
(defn find-divisible [l]
(or (first
(for [a (range (count l))
b (range (count l))
:when (and (not= a b)
(= (mod (l a) (l b)) 0))]
(/ (l a) (l b))))
0))
(apply + (map find-divisible input))
+18
View File
@@ -0,0 +1,18 @@
(ns day04
(:require input-manager
core))
(def input (map core/split-whitespace (input-manager/get-input 2017 04)))
;; part 1
(->> input
(filter #(= (count %)
(count (into #{} %))))
count)
;; part 2
(->> input
(filter #(= (count (into #{} (map frequencies %)))
(count %)))
count)
+30
View File
@@ -0,0 +1,30 @@
(ns day05
(:require input-manager))
(def input (->> (input-manager/get-input 2017 5)
(mapv parse-long)))
(def MAX_IDX (count input))
;; part 1
(loop [steps 0
maze input
idx 0]
(let [maze' (update maze idx inc)
idx' (+ (maze idx) idx)]
(if (< -1 idx' MAX_IDX)
(recur (inc steps) maze' idx')
(inc steps))))
;; part 2
(loop [steps 0
maze input
idx 0]
(let [offset (maze idx)
maze' (update maze idx (if (>= offset 3)
dec
inc))
idx' (+ offset idx)]
(if (< -1 idx' MAX_IDX)
(recur (inc steps) maze' idx')
(inc steps))))
+26
View File
@@ -0,0 +1,26 @@
(ns day06
(:require [input-manager]
[core :refer [split-whitespace]]))
(def input
(->> (input-manager/get-input-raw 2017 6)
split-whitespace
(mapv parse-long)))
(loop [state input
i 0
seen {}]
(if (contains? seen state)
{:part-one i
:part-two (- i (seen state))}
(let [cnt (apply max state)
idx (->> state
(map-indexed vector)
(filter #(= (second %) cnt))
ffirst)]
(recur (->> (range cnt)
(map #(mod (+ idx 1 %) (count state)))
(reduce #(update %1 %2 inc) (assoc state idx 0)))
(inc i)
(assoc seen state i)))))
+67
View File
@@ -0,0 +1,67 @@
(ns day07
(:require
[clojure.string :as str]
[core :refer [split-whitespace]]
[input-manager]))
(def input
(->> (input-manager/get-input-raw 2017 7)
str/split-lines
(map (comp split-whitespace
#(str/replace % #"," "")))))
;; part 1
(def base-node
(->> input
(filter (fn [[_ _ _ & children]] children))
(filter (fn [[node]]
(empty? (filter (fn [[_ _ _ & children]]
(some #(= % node) children))
input))))
ffirst))
(do
(def get-depth
(memoize (fn [node]
(let [[_ w-str _ & children] (first (filter (fn [[n]] (= node n))
input))
w (parse-long (subs w-str 1 (dec (count w-str))))]
(apply + w (map get-depth children))))))
(def get-weight
(memoize (fn [node]
(let [w-str (->> input
(filter (fn [[n]] (= node n)))
first
second)]
(parse-long (subs w-str 1 (dec (count w-str))))))))
(def get-children
(memoize (fn [node] (->> input
(filter (fn [[n]] (= node n)))
first
(drop 3))))))
(defn get-children-data [node]
(map (juxt identity get-depth get-weight) (get-children node)))
(defn get-counts [data]
(->> data
(map second)
frequencies
(sort-by second)))
;; part 2
(let [[bad-parent bad-node]
(loop [parent nil
node base-node]
(let [data (get-children-data node)
counts (get-counts data)
row (first (filter #(= (second %) (ffirst counts)) data))]
(if (= (count counts) 1)
[parent node]
(recur node (first row)))))
diff (->> bad-parent
get-children-data
get-counts
(map first)
(apply -))]
(- (get-weight bad-node) diff))
+46
View File
@@ -0,0 +1,46 @@
(ns day08
(:require
[clojure.string :as str]
[core]
[input-manager]))
(def op {"inc" +
"dec" -})
(def cond-op {"<" <
"<=" <=
">" >
">=" >=
"==" =
"!=" not=})
(def input (map (comp
(fn [[name operation num _ cond-name cond-operation cond-val]]
[name
(op operation)
(parse-long num)
cond-name
(cond-op cond-operation)
(parse-long cond-val)])
core/split-whitespace)
(input-manager/get-input 2017 8)))
(defn compute [acc [reg reg-op val cond-reg cond-op cond-val]]
(if (cond-op (acc cond-reg 0) cond-val)
(assoc acc reg (reg-op (acc reg 0) val))
acc))
;; part 1
(->> input
(reduce compute {})
(sort-by second)
last
second)
;; part 2
(->> input
(reductions compute {})
(mapcat identity)
set
(sort-by second)
last
second)
+34
View File
@@ -0,0 +1,34 @@
(ns day09
(:require [clojure.string :as str]
core
input-manager))
(def input (input-manager/get-input-raw 2017 9))
(defn sum-recursive-depths [s sum idx depth]
(if (>= idx (count s))
sum
(condp = (.charAt s idx)
\, (recur s sum (inc idx) depth)
\{ (recur s
(+ sum depth)
(inc idx)
(inc depth))
\} (recur s
sum
(inc idx)
(max (dec depth) 0)))))
(defn exlam-canceler [s] (str/replace s #"!." ""))
(def angle-bracket-regex #"<[^>]*>")
(-> input
exlam-canceler
(str/replace angle-bracket-regex "")
(sum-recursive-depths 0 0 1))
(->> input
exlam-canceler
(re-seq angle-bracket-regex)
(map #(- (count %) 2))
(reduce +))
+27
View File
@@ -0,0 +1,27 @@
(ns day11
(:require [core]
input-manager
[clojure.string :as str]))
(def input (-> (input-manager/get-input-raw 2017 11)
(str/split #",")))
(def offsets {"n" [0 1]
"ne" [0.5 0.5]
"se" [0.5 -0.5]
"s" [0 -1]
"sw" [-0.5 -0.5]
"nw" [-0.5 0.5]})
(defn distance-from-origin [pos]
(let [[x y] (map abs pos)]
(+ (* x 2) (- y x))))
(->> input
(map offsets)
(reductions #(map + %1 %2) [0 0])
(map distance-from-origin)
((juxt last (partial apply max)))
(zipmap [:part-one :part-two]))
+34
View File
@@ -0,0 +1,34 @@
(ns day12
(:require
[clojure.string :as str]
core
input-manager
[clojure.set :refer [difference]]))
(def input (->> (input-manager/get-input 2017 12)
(map #(str/replace % #"," ""))
(map core/split-whitespace)
(map (fn [[a _ & rst]]
[(parse-long a) (mapv parse-long rst)]))
(into {})))
(defn group-from-start [start]
(loop [visited #{}
queue [start]]
(if-not (seq queue)
visited
(let [[curr & rst] queue
ns (filter (complement visited) (input curr))]
(recur (into visited ns)
(concat rst ns))))))
;; part one
(count (group-from-start 0))
;; part two
(loop [ks (into #{} (keys input))
i 0]
(if-not (seq ks)
i
(recur (difference ks (group-from-start (first ks)))
(inc i))))
+58
View File
@@ -0,0 +1,58 @@
(ns day13
(:require
[clojure.string :as str]
[core]
[input-manager]))
(def lengths (->> (input-manager/get-input 2017 13)
(map (comp #(mapv parse-long %)
#(str/split % #": ")))
(into {})))
(defn move-sensor [{:keys [idx depth increasing-depth] :as sensor}]
(let [[keep-moving reverse-step] (if increasing-depth [inc dec] [dec inc])
depth' (keep-moving depth)]
(if (or (> depth' (dec (lengths idx)))
(< depth' 0))
(-> sensor
(update :depth reverse-step)
(update :increasing-depth not))
(assoc sensor :depth depth'))))
(def initial-sensors (->> lengths
keys
(map #(hash-map :depth 0
:idx %
:increasing-depth true))))
(defn is-spotted-by-sensors [acc pos]
(some #(when (and (= (:idx %) pos)
(= (:depth %) 0))
%)
(:sensors acc)))
(->> lengths keys (apply max) inc range
(reduce (fn [acc pos]
(let [spotted (is-spotted-by-sensors acc pos)]
(-> acc
(update :sensors (partial map move-sensor))
(update :solution + (if spotted
(* pos (lengths pos))
0)))))
{:sensors initial-sensors
:solution 0})
:solution)
(loop [i 0
start-val initial-sensors]
(if
(= true
(->> lengths keys (apply max) inc range
(reduce (fn [acc pos]
(let [spotted (is-spotted-by-sensors acc pos)]
(if spotted
(reduced true)
(update acc :sensors (partial map move-sensor)))))
{:sensors start-val})))
(recur (inc i) (map move-sensor start-val))
i))
+11
View File
@@ -0,0 +1,11 @@
(ns user
(:require
[clojure.pprint :as pprint]))
(defonce printer (bound-fn* pprint/pprint))
(add-tap printer)
(comment
;; tap debugging
(remove-tap printer))
+1
View File
@@ -1,2 +1,3 @@
input/
.lein-repl-history
*.iml
+9
View File
@@ -0,0 +1,9 @@
# AOC 2024
## todo (spoilers)
15) reimplement to support wide rock
16) add backtracking to find all viable paths
17) find right input to make computer program output itself
20) search in 20x20 grid for larger cheat jumps
21) dp for long keypad input sequence
24) find the 4 swaps (8 wires) such that the adding machine works for all inputs
-4
View File
@@ -1,4 +0,0 @@
{:deps {org.clojure/clojure {:mvn/version "1.12.0"}
org.clojure/math.combinatorics {:mvn/version "0.3.0"}}
:paths ["src" "../shared/clj/src"]
:tasks {}}
+3 -1
View File
@@ -5,7 +5,9 @@
:jvm-opts ["-Xmx16g"]
:plugins [[cider/cider-nrepl "0.57.0"]]
:dependencies [[org.clojure/clojure "1.12.0"]
[org.clojure/data.priority-map "1.2.0"]
[org.clojure/math.combinatorics "0.3.0"]
[babashka/fs "0.5.23"]
[org.babashka/http-client "0.4.22"]]
[org.babashka/http-client "0.4.22"]
[org.clojure/core.match "1.1.0"]]
:source-paths ["src" "../shared/clj/src"])
+14 -16
View File
@@ -1,26 +1,24 @@
(ns day01
(:require
[input-manager :refer [get-input]]
[core :as c]))
(def input (->> (get-input 1)
(map #(first (c/get-match-groups #"(\d+)\s+(\d+)" %)))
(map #(mapv parse-long %))
(into {})
((juxt keys vals))))
(:require input-manager))
;; part 1
(defn every-other [coll]
(take-nth 2 coll))
(def input (->> (input-manager/get-input-raw 2024 1)
(re-seq #"\d+")
(map parse-long)
((juxt every-other (comp every-other rest)))))
(->> input
(map sort)
(apply zipmap)
(map #(abs (apply - %)))
(reduce +))
(apply map (comp abs -))
(apply +))
;; part 2
(let [[a b] input
freqs (frequencies b)]
(->> a
(let [[left-col right-col] input
freqs (frequencies right-col)]
(->> left-col
(map #(* (or (freqs %) 0) %))
(reduce +)))
+19 -25
View File
@@ -1,37 +1,31 @@
(ns day03
(:require [core :as c]
[input-manager :refer [get-input]]
(:require [input-manager]
[clojure.string :as str]))
(def input (str/join (get-input 3)))
(def input (input-manager/get-input-raw 2024 3))
(defn parse-muls
"takes in a string containing mul instructions
returns list of parsed integral multiplication results"
[s]
(->> (c/get-match-groups #"mul\((\d{1,3}),(\d{1,3})\)" s)
(map #(map parse-long %))
(map #(reduce * %))))
(defn compute-muls [s]
(map (comp #(reduce * %)
#(map parse-long %)
#(str/split % #",")
#(subs % 4 (dec (count %)))) ;; remove `mul(` prefix and `)` suffix
s))
(defn enforce-toggles [[el & rst]]
(cond (= el "do()") (recur rst)
(= el "don't()") (recur (drop-while #(not= % "do()") rst))
el (conj (lazy-seq (enforce-toggles rst)) el)))
;; part 1
(->> input
parse-muls
(re-seq #"mul\(\d{1,3},\d{1,3}\)")
compute-muls
(reduce +))
;; part 2
(->> input
(c/re-pos #"mul\((\d{1,3}),(\d{1,3})\)|(do\(\))|(don't\(\))")
(sort-by key)
(reduce
(fn [acc [_idx instr]]
(cond
(.startsWith instr "mul") (if (:on acc)
(update acc :val
+ (->> instr parse-muls first))
acc)
(.startsWith instr "don't") (assoc acc :on false)
(.startsWith instr "do") (assoc acc :on true)))
{:on true
:val 0})
:val)
(re-seq #"mul\(\d{1,3},\d{1,3}\)|do\(\)|don't\(\)")
enforce-toggles
compute-muls
(reduce +))
+98
View File
@@ -0,0 +1,98 @@
(ns day16
(:require
[input-manager :refer [get-input]]
[core :as c]
[clojure.data.priority-map :refer [priority-map]]))
(def maze
#_(c/split-whitespace "###############
#.......#....E#
#.#.###.#.###.#
#.....#.#...#.#
#.###.#####.#.#
#.#.#.......#.#
#.#.#####.###.#
#...........#.#
###.#.#####.#.#
#...#.....#.#.#
#.#.#.###.#.#.#
#.....#...#.#.#
#.###.#.#.#.#.#
#S..#.....#...#
###############")
(get-input 2024 16))
(def grid (->> maze
(map-indexed (fn [row-idx row]
(map-indexed (fn [col-idx c]
[[row-idx col-idx] c])
row)))
(mapcat identity)
(into {})))
(defn find-char [c]
(->> grid
(filter (comp #{c} second))
ffirst))
(def start (find-char \S))
(def end (find-char \E))
(defn rotate-clockwise [dir]
(condp = dir
:right :down
:down :left
:left :up
:up :right))
(defn rotate-counterclockwise [dir]
(condp = dir
:down :right
:left :down
:up :left
:right :up))
(defn direction-offset [dir]
(condp = dir
:up [-1 0]
:right [0 1]
:down [1 0]
:left [0 -1]))
(defn find-search-path [[start start-dir] goal]
(loop [[[[pos dir] cost] & _ :as whole] (priority-map [start start-dir] 0)
visited #{[start start-dir]}
shortest {start 0}
n 0]
(if (= pos goal)
shortest
(let [searches (->> [[[(mapv + pos (direction-offset dir)) dir] (inc cost)]
[[pos (rotate-clockwise dir)] (+ 1000 cost)]
[[pos (rotate-counterclockwise dir)] (+ 1000 cost)]]
(filter (comp not visited first))
(filter (comp grid ffirst))
(filter (comp not #{\#} grid ffirst)))
searches-no-costs (mapv (comp first pop) searches)
seaches-no-dirs (mapv (juxt ffirst last) searches)]
(recur (into (pop whole) searches)
(into visited searches-no-costs)
(into (into {} seaches-no-dirs) shortest)
(inc n))))))
(def searched (find-search-path [start :right] end))
;; part 1 solution
(searched end)
(def max-idx (->> (keys grid)
(map first)
(apply max)))
(def updated-grid (->> grid
(map (fn [[k :as entry]] (if (and (contains? searched k) (#{\S \E \.} (grid k)))
[k \O]
entry)))
(into {})))
(->> (range 0 max-idx)
(map (fn [row] (map #(vector row %) (range 0 max-idx))))
(map (partial map updated-grid))
(map (partial apply str))
(interpose "\n")
(apply str)
print)
+96
View File
@@ -0,0 +1,96 @@
(ns day17
(:require input-manager
[core :as c]
[clojure.string :as str]))
(let [[registers _ [program]]
(->> #_(input-manager/get-input 2024 17)
"Register A: 729\nRegister B: 0\nRegister C: 0\n\nProgram: 0,1,5,4,3,0"
(str/split-lines)
(partition-by (partial = "")))]
(def registers (update-vals
(into {}
(map (comp vec
rest
first
(partial re-seq #"(\w)+: (.*)")) registers))
parse-long))
(def program (mapv parse-long
(-> program
(str/split #" ")
second
(str/split #",")))))
(defn combo-op->value [combo-op registers]
(condp = combo-op
4 (registers "A")
5 (registers "B")
6 (registers "C")
7 (throw (ex-message "invalid"))
combo-op))
(defn compute
([registers program]
(compute registers program 0 []))
([{A "A", B "B", C "C" :as registers} program instr-ptr out]
(if (>= instr-ptr (count program))
[out registers]
(let [operation (program instr-ptr)
operand (program (inc instr-ptr))
combo-operand (delay (combo-op->value operand registers))
instr-ptr' (+ 2 instr-ptr)]
(condp = operation
0 (recur (->> (int (/ A (max 1 (bit-shift-left 2 (dec @combo-operand)))))
(assoc registers "A"))
program instr-ptr' out)
1 (recur (->> operand
(bit-xor B)
(assoc registers "B"))
program instr-ptr' out)
2 (recur (->> (mod @combo-operand 8)
(assoc registers "B"))
program instr-ptr' out)
3 (if (= A 0)
(recur registers program instr-ptr' out)
(recur registers program operand out))
4 (recur (->> (bit-xor B C)
(assoc registers "B"))
program instr-ptr' out)
5 (recur registers
program
instr-ptr'
(conj out (mod @combo-operand 8)))
6 (recur (->> (int (/ A (max 1 (bit-shift-left 2 (dec @combo-operand)))))
(assoc registers "B"))
program instr-ptr' out)
7 (recur (->> (int (/ A (max 1 (bit-shift-left 2 (dec @combo-operand)))))
(assoc registers "C"))
program instr-ptr' out))))))
;; part 1
(->> (compute registers program)
first
(interpose ",")
(apply str))
;; part 2
(loop [n 0]
(when (= (mod n 10000) 0)
(println n))
(let [res (try (compute (merge registers {"A" n}) program)
(catch Exception _e
nil))]
(if (= (first res) program)
n
(recur (inc n)))))
(comment
registers
program
(compute {"C" 1} [2 6])
(compute {"A" 10} [5, 0, 5, 1, 5, 4])
(compute {"A" 2024} [0, 1, 5, 4, 3, 0])
(compute {"B" 29} [1, 7])
(compute {"B" 2024, "C" 43690} [4 0])
)
+4 -5
View File
@@ -22,8 +22,7 @@
(mapv (constantly 0) puzzle))
last))
(let [[w _ & p]
(input-manager/get-input 2024 19)]
(let [[w _ & p] (input-manager/get-input 2024 19)]
(def words (into #{} (str/split w #", ")))
(def puzzles p))
@@ -36,8 +35,8 @@
(apply + (map (partial valid-combination-count words) puzzles))
(comment
(increment-counts-for-matching-words #{"a"} "atest" [0 0 0 0 0 0] 0) ; [1 0 0 0 0 0]
(increment-counts-for-matching-words #{"a"} "btest" [0 0 0 0 0 0] 0) ; [0 0 0 0 0 0]
(increment-counts-for-matching-words #{"a"} "atest" [0 0 0 0 0 0] 0) ; [1 0 0 0 0 0]
(increment-counts-for-matching-words #{"a"} "btest" [0 0 0 0 0 0] 0) ; [0 0 0 0 0 0]
(increment-counts-for-matching-words #{"te"} "atest" [1 0 0 0 0 0] 1) ; [1 0 1 0 0 0]
(increment-counts-for-matching-words #{"wo" "rd"} "word" [0 1 0 0] 2) ; [0 1 0 1]
@@ -45,5 +44,5 @@
(valid-combination-count #{"word"} "word") ; 1
(increment-counts-for-matching-words #{"wo" "or" "w" "rd" "d"} "word" [0 0 0 0] 0) ; [1 1 0 0]
(valid-combination-count #{"wo" "or" "w" "rd" "d"} "word") ; 2, because ("wo" "r" "d") and ("w")
(valid-combination-count #{"wo" "or" "w" "rd" "d"} "word") ; 2, because ("wo" "r" "d") and ("w" "or" "d")
)
+61
View File
@@ -0,0 +1,61 @@
(ns day20
(:require
input-manager))
(def maze (input-manager/get-input 2024 20))
(def grid (->> maze
(map-indexed (fn [row-idx row]
(map-indexed (fn [col-idx c]
[[row-idx col-idx] c])
row)))
(mapcat identity)
(into {})))
(defn find-char [c]
(->> grid
(filter (comp #{c} second))
ffirst))
(def start (find-char \S))
(def end (find-char \E))
(def direction-offsets #{[0 1] [1 0] [0 -1] [-1 0]})
(defn find-search-path []
(loop [[[pos steps] & rst] [[start 0]]
visited #{start}
shortest {start 0}]
(if (= pos end)
shortest
(let [searches (->> direction-offsets
(map (partial mapv + pos))
(filter grid)
(filter (comp not visited))
(filter (comp not #{\#} grid)))
searches-w-path-lengths (mapv #(vector % (inc steps)) searches)]
(recur (into rst searches-w-path-lengths)
(into visited searches)
(into shortest searches-w-path-lengths))))))
(defn find-cheats []
(let [search-path (find-search-path)
walls (->> grid
(filter (comp #{\#} second))
(map first))
cheats (->> walls
(map (fn [pos]
(->> direction-offsets
(map (partial mapv + pos))
(map search-path)
(filter identity))))
(filter not-empty)
(filter (comp (partial <= 2) count))
(map sort)
(mapcat (fn [[a & bs]]
(map #(- % a) bs))))]
(frequencies cheats)))
;; part 1
(->> (find-cheats)
(filter (comp #(> % 100) first))
(map second)
(apply +))
+52
View File
@@ -0,0 +1,52 @@
(ns day22
(:require input-manager))
(def input (->> (input-manager/get-input 2024 22)
(map parse-long)))
(def prune-const 16777216)
(defn prune [x] (mod x prune-const))
(defn mix [secret v] (bit-xor secret v))
(defn next-step [secret]
(let [a (prune (mix secret (* secret 64)))
b (prune (mix a (int (/ a 32))))
c (prune (mix b (* b 2048)))]
c))
(defn get-nums
([n] (get-nums n 0))
([n i] (lazy-seq (cons n (get-nums (next-step n) (inc i))))))
(def solutions (->> input
(map get-nums)
(mapv (comp (partial into [])
(partial take 2001)))))
;; part 1 sol
(->> solutions
(map last)
(apply +))
;; part 2 sol
(->> (map (partial map #(mod % 10)) solutions)
(map #(map (fn [& prices]
(let [price-diff-list (map - (rest prices) prices)
sell-price (last prices)]
[price-diff-list sell-price]))
% (rest %) (drop 2 %) (drop 3 %) (drop 4 %)))
(reduce (fn [acc buyer]
(->> (reduce (fn [[visited acc2] [price-diff-list price]]
(if (visited price-diff-list)
[visited acc2]
[(conj visited
price-diff-list)
(update acc2
price-diff-list
#(+ (or % 0) price))]))
[#{} acc]
buyer)
second))
{})
vals
(apply max))
+4
View File
@@ -0,0 +1,4 @@
input/
.lein-repl-history
.idea/
*.iml
File diff suppressed because it is too large Load Diff
+15
View File
@@ -0,0 +1,15 @@
(defproject org.ajet/advent-of-code "0.0.0-SNAPSHOT"
:description "my 2024 advent of code solutions in clojure"
:url "http://github.com/ajetski/advent-of-code"
:min-lein-version "2.0.0"
:jvm-opts ["-Xmx16g"]
:plugins [[cider/cider-nrepl "0.57.0"]]
:dependencies [[org.clojure/clojure "1.12.0"]
[org.clojure/data.priority-map "1.2.0"]
[org.clojure/math.combinatorics "0.3.0"]
[babashka/fs "0.5.23"]
[org.babashka/http-client "0.4.22"]
[org.clojure/core.match "1.1.0"]
[clj-python/libpython-clj "2.025"]
[tools.aqua/z3-turnkey "4.14.1"]]
:source-paths ["src" "../shared/clj/src"])
+37
View File
@@ -0,0 +1,37 @@
(ns day01
(:require input-manager))
(defn parse-line [line]
[(.charAt line 0)
(parse-long (.substring line 1))])
(def input (->> (input-manager/get-input 2025 01)
(map parse-line)))
(def op {\R +, \L -})
(defn normalize [n]
(mod n 100))
;; part 1
(->> input
(reductions (fn [acc [dir turn-cnt]]
(normalize ((op dir) acc turn-cnt)))
50)
(filter (partial = 0))
count)
;; part 2
(->> input
(reduce (fn [[acc dial] [dir turn-cnt]]
(let [next-dial ((op dir) dial turn-cnt)]
[(+ acc (cond (> next-dial 99) (int (/ next-dial 100))
(< next-dial 0) (+ (abs (int (/ next-dial 100)))
(if (= dial 0)
0
1))
(= next-dial 0) 1
:else 0))
(normalize next-dial)]))
[0 50])
first)
+55
View File
@@ -0,0 +1,55 @@
(ns day02
(:require
[clojure.string :as str]
input-manager))
(defn split-comma [s] (str/split s #","))
(def input (->> (input-manager/get-input-raw 2025 2)
#_"11-22,95-115,998-1012,1188511880-1188511890,222220-222224,1698522-1698528,446443-446449,38593856-38593862,565653-565659,824824821-824824827,2121212118-2121212124"
split-comma
(map (comp #(map parse-long %)
#(str/split % #"-")))))
(defn splitable-num? [n]
(let [s (str n)
len (count s)
parition (int (/ len 2))]
(and (even? len)
(= (.substring s 0 parition) (.substring s parition)))))
;; part 1
(->> input
(map (fn [[a b]]
(filter splitable-num? (range a (inc b)))))
(mapcat identity)
(apply +))
(defn repeated-num? [n]
(let [s (str n)
len (count s)]
(loop [L 1]
(cond
;; Stop if the potential substring length L exceeds half the total length
;; (a repetition must be at least twice the substring length)
(> L (/ len 2)) false
;; Check if L is a divisor of len. If not, this L can't form a full repetition.
(not= (mod len L) 0) (recur (inc L))
;; L is a divisor. Check if the string is formed by repeating the first L characters.
:else
(let [substring (subs s 0 L)
num-repetitions (/ len L)
repeated-string (apply str (repeat num-repetitions substring))]
(if (= s repeated-string)
true
(recur (inc L))))))))
;; part 2
(->> input
(map (fn [[a b]]
(filter repeated-num? (range a (inc b)))))
(mapcat identity)
(apply +))
+26
View File
@@ -0,0 +1,26 @@
(ns day03
(:require input-manager))
(def input (input-manager/get-input 2025 3))
(defn max-joltage [bank num-batteries-to-activate]
(let [len (count bank)]
(loop [n num-batteries-to-activate
acc ""
idx-iter 0]
(let [search-space (.substring bank idx-iter (- len (dec n)))
max-char (apply max (map int search-space))
max-char-idx (.indexOf bank max-char idx-iter)]
(if (= n 1)
(parse-long (str acc (char max-char)))
(recur (dec n)
(str acc (char max-char))
(inc max-char-idx)))))))
(->> input
(map #(max-joltage % 2))
(apply +))
(->> input
(map #(max-joltage % 12))
(apply +))
+41
View File
@@ -0,0 +1,41 @@
(ns day04
(:require input-manager
core))
(def input (input-manager/get-input 2025 4))
(def grid (core/map-by-coords input))
(def offsets [[-1 -1] [-1 0] [-1 1]
[0 -1] [0 1]
[1 -1] [1 0] [1 1]])
;; part 1
(->> grid
(filter (fn [[_ v]]
(= v \@)))
(map first)
(filter (fn [pos]
(< (count (filter (comp (partial = \@) grid)
(for [o offsets]
(mapv + pos o))))
4)))
count)
;; part 2
(loop [grid grid
acc 0]
(let [locs
(->> grid
(filter (fn [[_ v]]
(= v \@)))
(map first)
(filter (fn [pos]
(< (count (filter (comp (partial = \@) grid)
(for [o offsets]
(mapv + pos o))))
4))))]
(if (empty? locs)
acc
(recur (reduce #(dissoc %1 %2) grid locs)
(+ acc (count locs))))))
+28
View File
@@ -0,0 +1,28 @@
(ns day05
(:require input-manager))
(let [[ranges [_ & nums]] (->> (input-manager/get-input 2025 5)
(split-with (partial not= "")))]
(def ranges (sort (mapv (comp #(mapv parse-long %)
#(re-seq #"\d+" %))
ranges)))
(def nums (mapv parse-long nums)))
(defn fresh? [num]
(some (fn [[a b]]
(<= a num b))
ranges))
;; part 1
(count (filter fresh? nums))
;; part 2
(->> ranges
(reduce (fn [[fresh-cnt max-seen :as acc]
[a b]]
(cond (>= max-seen b) acc
(>= max-seen a) [(+ fresh-cnt (- b max-seen)) b]
:else [(+ fresh-cnt (inc (- b a))) b]))
[0 0])
first)
+35
View File
@@ -0,0 +1,35 @@
(ns day06
(:require input-manager))
(def input (input-manager/get-input 2025 6))
(def numeric-line? (comp not #{\* \+} first))
(def numeric-lines (take-while numeric-line? input))
(def nums (map #(map parse-long (re-seq #"\d+" %)) numeric-lines))
(def ops (->> (drop-while numeric-line? input)
first
(filter (partial not= \space))
(mapv {\+ +, \* *})))
;; part 1
(apply + (apply map (fn [op & rst] (apply op rst))
ops
nums))
;; part 2
(->> (range (count (first numeric-lines)))
(reduce (fn [{:keys [op-idx curr-nums] :as acc} col-idx]
(let [op (ops op-idx)
col (->> (map #(.charAt % col-idx) numeric-lines)
(filter (partial not= \space))
(map #(- (int %) (int \0))))]
(if (empty? col)
(-> (update acc :ans + (apply op curr-nums))
(update :op-idx inc)
(assoc :curr-nums []))
(update acc :curr-nums conj (parse-long (apply str col))))))
{:ans 0, :op-idx 0, :curr-nums []})
((juxt :ans
#(apply (last ops) (:curr-nums %))))
(apply +))
+55
View File
@@ -0,0 +1,55 @@
(ns day07
(:require input-manager
core))
(def input (input-manager/get-input 2025 7))
(def start ((core/map-to-coords input) \S))
(def grid (core/map-by-coords input))
(def NUM_ROWS (count input))
(defn left [loc] (update loc 1 dec))
(defn right [loc] (update loc 1 inc))
(defn down [loc] (update loc 0 inc))
(defn splitter? [loc] (= (grid loc) \^))
;; part 1
(->> (range NUM_ROWS)
(reduce (fn [{:keys [acc search-locs]} _]
(if (empty? search-locs)
(reduced acc)
(let [next-locs (map down search-locs)
splitters (filter splitter? next-locs)
next-locs (-> #{}
(into (filter (complement splitter?) next-locs))
(into (mapcat (juxt left right) splitters)))]
{:acc (into acc splitters)
:search-locs next-locs})))
{:acc #{}, :search-locs #{start}})
:acc
count)
(defn left-entry [[loc cnt]] [(left loc) cnt])
(defn right-entry [[loc cnt]] [(right loc) cnt])
(defn splitter-entry? [[loc _]] (= (grid loc) \^))
(defn join-flows [flows]
(reduce (fn [acc [loc cnt]]
(if (acc loc)
(update acc loc + cnt)
(assoc acc loc cnt)))
{}
flows))
;; part 2
(->> (range NUM_ROWS)
(reduce (fn [{:keys [acc search-locs]} _]
(if (empty? search-locs)
(reduced acc)
(let [next-locs (update-keys search-locs down)
splitters (filter splitter-entry? next-locs)
next-locs (join-flows (concat (filter (complement splitter-entry?) next-locs)
(mapcat (juxt left-entry right-entry) splitters)))]
{:acc (apply + acc (map (fn [[_ cnt]] cnt) splitters))
:search-locs next-locs})))
{:acc 1, :search-locs {start 1}})
:acc)
+51
View File
@@ -0,0 +1,51 @@
(ns day08
(:require input-manager clojure.set))
(def input (->> (input-manager/get-input 2025 8)
(mapv (comp (partial mapv parse-long)
(partial re-seq #"\d+")))))
(def initial-circuits (into #{} (map hash-set input)))
(defn square [x] (* x x))
(defn dist-squared [[ax ay az] [bx by bz]]
(+ (square (- ax bx))
(square (- ay by))
(square (- az bz))))
(def closest-points (->> (for [a input
b input
:when (not= a b)]
#{a b})
distinct
(map vec)
(sort-by (partial apply dist-squared))))
;; part 1
(->> (take 1000 closest-points)
(reduce (fn [circuits [a b]]
(let [circuit-a (first (filter #(% a) circuits))
circuit-b (first (filter #(% b) circuits))]
(if (= circuit-a circuit-b)
circuits
(let [combined (clojure.set/union circuit-a circuit-b)]
(-> circuits (disj circuit-a) (disj circuit-b) (conj combined))))))
initial-circuits)
(sort-by count)
(take-last 3)
(map count)
(apply *))
;; part 2
(->> (take 6498 closest-points)
(reduce (fn [circuits [a b]]
(let [circuit-a (first (filter #(% a) circuits))
circuit-b (first (filter #(% b) circuits))]
(if (= circuit-a circuit-b)
circuits
(let [combined (clojure.set/union circuit-a circuit-b)
circuits' (-> circuits (disj circuit-a) (disj circuit-b) (conj combined))]
(if (= 1 (count circuits'))
(reduced [a b])
circuits')))))
initial-circuits)
(map first)
(apply *))
+51
View File
@@ -0,0 +1,51 @@
(ns day09
(:require [input-manager]))
(def input (->> (input-manager/get-input 2025 9)
(mapv #(mapv parse-long (re-seq #"\d+" %)))))
(defn area [[ax ay] [bx by]]
(* (inc (abs (- ax bx)))
(inc (abs (- ay by)))))
(def largest-rects (->> (for [a input
b input
:when (not= a b)]
#{a b})
distinct
(map vec)
(sort-by #(apply area %))))
;; part 1
(->> largest-rects
last
(apply area))
(defn normalize [x] (min 1 (max -1 x)))
(defn orientation
"returns a value indicating if point B is to the left, right, or on the line AC"
[[ax ay] [bx by] [cx cy]]
(normalize (- (* (- by ay) (- cx bx))
(* (- bx ax) (- cy by)))))
(defn intersect?
"Lines AB and CD intersect if points A and B falls on different sides of CD
and if C and D fall on different sides of AB"
[[a b] [c d]]
(let [o1 (orientation a c b)
o2 (orientation a d b)
o3 (orientation c a d)
o4 (orientation c b d)]
(and (not= o1 o2) (not= o3 o4))))
(def line-segments (map vector input (rest input)))
;; part 2
(->> largest-rects
(filter (fn [[a b :as rect]]
(let [segments (filter (fn overlapping? [[c d]]
(and (not= a c) (not= a d)
(not= b c) (not= b d))) ;; filter out segments that include points a or b
line-segments)
[[cx cy] [dx dy]] rect
reverse-diag [[cx dy] [dx cy]]]
(and (not (some #(intersect? rect %) segments))
(not (some #(intersect? reverse-diag %) segments))))))
(map (partial apply area))
sort
last)
+71
View File
@@ -0,0 +1,71 @@
(ns day10
(:require [clojure.math.combinatorics :as combo]
[input-manager])
(:import (com.microsoft.z3 Context Expr IntNum Optimize Optimize$Handle)))
(defn parse-line [line]
{:indicators (->> line
(drop 1)
(take-while (complement #{\]}))
(mapv (partial = \#)))
:buttons (->> line
(re-seq #"\([\d,]+\)")
(map #(map parse-long (re-seq #"\d+" %))))
:joltages (->> line
(drop-while #(not= % \{))
(drop 1)
(take-while #(not= % \}))
(apply str)
(re-seq #"\d+")
(mapv parse-long))})
(def input (map parse-line (input-manager/get-input 2025 10)))
(defn minimum-button-mashing [{:keys [buttons indicators]}]
(loop [i 0
cnt 1]
(if (>= i (combo/count-combinations buttons cnt))
(recur 0 (inc cnt))
(let [indicators' (reduce (partial reduce #(update %1 %2 not))
indicators
(combo/nth-combination buttons cnt i))]
(if (every? (complement identity) indicators')
cnt
(recur (inc i) cnt))))))
;; part 1
(apply + (map minimum-button-mashing input))
;; part 2
(defn add-expressions [opt expressions]
(.Add opt (into-array Expr expressions)))
(->> input
(map (fn [{:keys [joltages buttons]}]
(let [ctx (Context.)
^Optimize opt (.mkOptimize ctx)
bs (->> buttons
count
range
(map #(.mkIntConst ctx (str "b" %))))
js (->> joltages
count
range
(map #(.mkIntConst ctx (str "j" %))))]
(add-expressions opt (for [idx (range (count joltages))]
(.mkEq ctx (nth js idx) (->> buttons
(map set)
(map-indexed vector)
(filter #(contains? (second %) idx))
(map first)
(map #(nth bs %))
(into-array Expr)
(.mkAdd ctx)))))
(add-expressions opt (for [[idx joltage] (map-indexed vector joltages)]
(.mkEq ctx (nth js idx) (.mkInt ctx (long joltage)))))
(add-expressions opt (for [b bs]
(.mkGe ctx b (.mkInt ctx (long 0)))))
(let [^Optimize$Handle mx (.MkMinimize opt (.mkAdd ctx (into-array Expr bs)))]
(.Check opt (into-array Expr []))
(.getInt ^IntNum (.getValue mx))))))
(apply +))
+21
View File
@@ -0,0 +1,21 @@
(ns day11
(:require [input-manager]))
(def input (->> (input-manager/get-input 2025 11)
(map (comp (fn [[node & edges]]
[node (into #{} edges)])
(partial re-seq #"[a-z]{3}")))
(into {})))
(def count-paths (memoize (fn [start target]
(let [edges (input start)]
(if (contains? edges target)
1
(apply + (map #(count-paths % target) edges)))))))
;; part 1
(count-paths "you" "out")
;; part 2
(+ (* (count-paths "svr" "dac") (count-paths "dac" "fft") (count-paths "fft" "out"))
(* (count-paths "svr" "fft") (count-paths "fft" "dac") (count-paths "dac" "out")))
+84
View File
@@ -0,0 +1,84 @@
(ns day12
(:require input-manager
core
[clojure.string :as str]
clojure.set))
(def requirements (->> (input-manager/get-input-raw 2025 12)
(core/split-on-double-newlines)
(map str/split-lines)
last
(map (comp (fn [[x y & cnts]]
[[x y] (into {} (map-indexed vector cnts))])
(partial map parse-long)
(partial re-seq #"\d+")))))
(defn fits-trivially?
"is it trivially possible to fit all the pieces if they were 3x3 blocks instead of jigsaws"
[[dimensions cnts]]
(let [area (apply * dimensions)
guess (->> cnts vals (reduce +) (* 9))]
(>= area guess)))
;; part 1
(->> requirements
(filter fits-trivially?)
count)
(comment
;; NP Hard... general solution is not fast enough
(defn flip [grid]
(vec (reverse grid)))
(defn rotations [grid]
(->> [(for [x (range 0 3)]
(for [y (range 0 3)]
(.charAt (grid x) y)))
(for [y (range 2 -1 -1)]
(for [x (range 0 3)]
(.charAt (grid x) y)))
(for [x (range 2 -1 -1)]
(for [y (range 2 -1 -1)]
(.charAt (grid x) y)))
(for [y (range 2 -1 -1)]
(for [x (range 3)]
(.charAt (grid x) y)))]
(map (partial map-indexed (fn [row-idx row]
(map-indexed (fn [col-idx cell]
(when (= cell \#)
[row-idx col-idx]))
row))))
(map (partial mapcat (partial filter identity)))
(mapv (partial mapv vec))
set))
#_(def jigsaws (->> (drop-last (->> (input-manager/get-input-raw 2025 12)
(core/split-on-double-newlines)
(map str/split-lines)))
(map (fn [[idx & puzzle-lines]]
[(parse-long (apply str (drop-last idx)))
(clojure.set/union (rotations (vec puzzle-lines)) (rotations (flip puzzle-lines)))]))
(into {})))
(defn placeable? [jigsaw filled]
(every? #(not (contains? filled %)) jigsaw))
(defn offset [loc jigsaw]
(into #{} (map #(mapv + % loc) jigsaw)))
(defn fits? [[[rows cols :as dimensions] cnts] jigsaws filled]
(cond
(every? (partial = 0) (vals cnts)) true
:else
(let [[id] (first (filter (fn [[_ cnt]] (> cnt 0)) cnts))
orientations (jigsaws id)
locs (for [row (range (- rows 2))
col (range (- cols 2))]
[row col])
cnts' (update cnts id dec)]
(some (fn [loc]
(->> orientations
(map #(offset loc %))
(filter #(placeable? % filled))
(map #(fits? [dimensions cnts'] jigsaws (clojure.set/union filled %)))
(filter identity)
first))
locs)))))
+11
View File
@@ -0,0 +1,11 @@
(ns user
(:require
[clojure.pprint :as pprint]))
(defonce printer (bound-fn* pprint/pprint))
(add-tap printer)
(comment
;; tap debugging
(remove-tap printer))