mirror of
https://github.com/Ajetski/advent-of-code.git
synced 2025-09-30 13:03:19 -09:00
start day23, todo: optimize part 2
This commit is contained in:
parent
bd784d925c
commit
d0ef346755
@ -2,19 +2,20 @@
|
|||||||
(:require [clj-http.client :as client]
|
(:require [clj-http.client :as client]
|
||||||
[clojure.string :as string]))
|
[clojure.string :as string]))
|
||||||
|
|
||||||
(def input-cache (atom {}))
|
|
||||||
(def cookie (str "session=" (slurp "session")))
|
(def cookie (str "session=" (slurp "session")))
|
||||||
|
|
||||||
(defn get-puzzle-input
|
(defn get-puzzle-input
|
||||||
"retrieves and caches aoc input for 2023 given a day"
|
"retrieves and caches aoc input for 2023 given a day"
|
||||||
[day]
|
[day]
|
||||||
(or (@input-cache day)
|
(let [file (java.io.File. (str "inputs/day" day ".txt"))]
|
||||||
(swap! input-cache assoc day
|
(or (when (.exists file)
|
||||||
(-> (str "https://adventofcode.com/2023/day/" day "/input")
|
(string/split-lines (slurp file)))
|
||||||
|
(let [data (-> (str "https://adventofcode.com/2023/day/" day "/input")
|
||||||
(client/get {:throw-entire-message? true
|
(client/get {:throw-entire-message? true
|
||||||
:headers {"Cookie" cookie}})
|
:headers {"Cookie" cookie}})
|
||||||
:body
|
:body)]
|
||||||
string/split-lines))))
|
(spit file data)
|
||||||
|
(string/split-lines data)))))
|
||||||
|
|
||||||
(defn re-seq-pos
|
(defn re-seq-pos
|
||||||
"re-seq that produces a seq of {:start :end :group}"
|
"re-seq that produces a seq of {:start :end :group}"
|
||||||
@ -40,32 +41,14 @@
|
|||||||
~@body)))
|
~@body)))
|
||||||
|
|
||||||
(defmacro comp>
|
(defmacro comp>
|
||||||
"comp, but fn-args are composed from left to right with currying
|
"generates a closure that composes inputs with clojure.core/-> semantics"
|
||||||
previous result inserted as first element to next function application"
|
[& forms]
|
||||||
[& ls]
|
`(fn [v#] (-> v# ~@forms)))
|
||||||
(let [fs (map (fn [l]
|
|
||||||
(if (and (list? l)
|
|
||||||
(not= 'fn (first l)))
|
|
||||||
(let [[f & fargs] l]
|
|
||||||
`(fn [v#] (~f v# ~@fargs)))
|
|
||||||
l))
|
|
||||||
ls)
|
|
||||||
r (reverse fs)]
|
|
||||||
`(comp ~@r)))
|
|
||||||
|
|
||||||
(defmacro comp>>
|
(defmacro comp>>
|
||||||
"comp, but fn-args are composed from left to right with currying
|
"generates a closure that composes inputs with clojure.core/->> semantics"
|
||||||
previous result inserted as last element to next function application"
|
[& forms]
|
||||||
[& ls]
|
`(fn [v#] (->> v# ~@forms)))
|
||||||
(let [fs (map (fn [l]
|
|
||||||
(if (and (list? l)
|
|
||||||
(not= 'fn (first l)))
|
|
||||||
(let [[f & fargs] l]
|
|
||||||
`(fn [v#] (~f ~@fargs v#)))
|
|
||||||
l))
|
|
||||||
ls)
|
|
||||||
r (reverse fs)]
|
|
||||||
`(comp ~@r)))
|
|
||||||
|
|
||||||
(defmacro w-fn
|
(defmacro w-fn
|
||||||
"wraps s-expr such as java static methods or macro calls
|
"wraps s-expr such as java static methods or macro calls
|
||||||
@ -114,6 +97,7 @@
|
|||||||
this function returns a vector where each value is the result of applying
|
this function returns a vector where each value is the result of applying
|
||||||
an f from fs to the corresponding v from vs"
|
an f from fs to the corresponding v from vs"
|
||||||
[& args]
|
[& args]
|
||||||
|
;; TODO: add spec or manual validation for args
|
||||||
(let [n (/ (count args) 2)]
|
(let [n (/ (count args) 2)]
|
||||||
(->> (zipmap (take n args)
|
(->> (zipmap (take n args)
|
||||||
(take-last n args))
|
(take-last n args))
|
||||||
@ -126,17 +110,19 @@
|
|||||||
|
|
||||||
this function returns a vector where each value is the result of applying
|
this function returns a vector where each value is the result of applying
|
||||||
an f from fs to the corresponding value from v"
|
an f from fs to the corresponding value from v"
|
||||||
|
;; TODO: add spec or manual validation for args
|
||||||
[& args]
|
[& args]
|
||||||
(->> (zipmap (drop-last args)
|
(->> (zipmap (drop-last args)
|
||||||
(last args))
|
(last args))
|
||||||
(mapv #((first %) (second %)))))
|
(mapv #((first %) (second %)))))
|
||||||
|
|
||||||
(def p partial)
|
(defmacro assert-all [& assertions]
|
||||||
|
`(do ~@(map (fn [assertion]
|
||||||
|
`(assert ~assertion))
|
||||||
|
assertions)))
|
||||||
|
|
||||||
(defmacro assert= [& abs]
|
(defn partial< [f & args1]
|
||||||
`(do ~@(map (fn [[a b]]
|
(fn [& args2] (apply f (concat args2 args1))))
|
||||||
`(assert (= ~a ~b)))
|
|
||||||
(partition 2 abs))))
|
|
||||||
|
|
||||||
(comment
|
(comment
|
||||||
|
|
||||||
@ -152,18 +138,18 @@
|
|||||||
(dec 2)
|
(dec 2)
|
||||||
(+ (/ 1 2)
|
(+ (/ 1 2)
|
||||||
(/ 1 2))))
|
(/ 1 2))))
|
||||||
|
(assert
|
||||||
(assert=
|
(= ((comp> (+ 1) (/ 2) (abc 1) (inc) ;; currying / partial fn applicaiton
|
||||||
8 ((comp> (+ 1) (/ 2) (abc 1) (inc) ;; currying / partial fn applicaiton
|
|
||||||
inc ;; named fn
|
inc ;; named fn
|
||||||
#(+ 1 %) (fn [v] (+ v 1))) ;; using lambdas
|
#(+ 1 %) (fn [v] (+ v 1))) ;; using lambdas
|
||||||
5)
|
5)
|
||||||
|
8))
|
||||||
3 ((comp> (- 5) (- 2))
|
(assert (= ((comp> (- 5) (- 2))
|
||||||
10)
|
10)
|
||||||
|
3))
|
||||||
7 ((comp>> (- 5) (- 2))
|
(assert (= ((comp>> (- 5) (- 2))
|
||||||
10))
|
10)
|
||||||
|
7))
|
||||||
|
|
||||||
(map (w-fn Long/parseLong) ["123" "456"])
|
(map (w-fn Long/parseLong) ["123" "456"])
|
||||||
input-cache
|
input-cache
|
||||||
@ -172,14 +158,20 @@
|
|||||||
((reducef + 0) [1 2])
|
((reducef + 0) [1 2])
|
||||||
|
|
||||||
(let [v 20]
|
(let [v 20]
|
||||||
(assert= ((comp> #(* % 3) #(+ % 2) #(* % 4))
|
(assert (= ((comp> #(* % 3) #(+ % 2) #(* % 4))
|
||||||
v)
|
v)
|
||||||
((comp #(* % 4) #(+ % 2) #(* % 3))
|
((comp #(* % 4) #(+ % 2) #(* % 3))
|
||||||
v)))
|
v))))
|
||||||
|
|
||||||
(assert=
|
(assert-all
|
||||||
|
(=
|
||||||
|
(apply-each #(* % 2) #(+ % 5) 1 2)
|
||||||
|
(apply-each-v #(* % 2) #(+ % 5) [1 2])
|
||||||
|
[2 7])
|
||||||
|
(=
|
||||||
(apply-each #(* % 2) #(+ % 5) 5 10)
|
(apply-each #(* % 2) #(+ % 5) 5 10)
|
||||||
(apply-each-v #(* % 2) #(+ % 5) [5 10]))
|
(apply-each-v #(* % 2) #(+ % 5) [5 10])
|
||||||
|
[10 15]))
|
||||||
|
|
||||||
(log (+ 5 5)
|
(log (+ 5 5)
|
||||||
(- 2 1))
|
(- 2 1))
|
||||||
|
90
2023/src/day23.clj
Normal file
90
2023/src/day23.clj
Normal file
@ -0,0 +1,90 @@
|
|||||||
|
(ns day23
|
||||||
|
(:require
|
||||||
|
[clojure.string :as str]
|
||||||
|
[lonocloud.synthread.macros :refer :all]
|
||||||
|
[core :refer [get-puzzle-input]]))
|
||||||
|
|
||||||
|
; (def input (get-puzzle-input 23))
|
||||||
|
|
||||||
|
(def input (str/split-lines "#.#####################
|
||||||
|
#.......#########...###
|
||||||
|
#######.#########.#.###
|
||||||
|
###.....#.>.>.###.#.###
|
||||||
|
###v#####.#v#.###.#.###
|
||||||
|
###.>...#.#.#.....#...#
|
||||||
|
###v###.#.#.#########.#
|
||||||
|
###...#.#.#.......#...#
|
||||||
|
#####.#.#.#######.#.###
|
||||||
|
#.....#.#.#.......#...#
|
||||||
|
#.#####.#.#.#########v#
|
||||||
|
#.#...#...#...###...>.#
|
||||||
|
#.#.#v#######v###.###v#
|
||||||
|
#...#.>.#...>.>.#.###.#
|
||||||
|
#####v#.#.###v#.#.###.#
|
||||||
|
#.....#...#...#.#.#...#
|
||||||
|
#.#########.###.#.#.###
|
||||||
|
#...###...#...#...#.###
|
||||||
|
###.###.#.###v#####v###
|
||||||
|
#...#...#.#.>.>.#.>.###
|
||||||
|
#.###.###.#.###.#.#v###
|
||||||
|
#.....###...###...#...#
|
||||||
|
#####################.#"))
|
||||||
|
|
||||||
|
(def start [0 1])
|
||||||
|
(def end [(dec (count input))
|
||||||
|
(- (count (last input)) 2)])
|
||||||
|
|
||||||
|
(def char-map (->> input
|
||||||
|
(map-indexed (fn [row line]
|
||||||
|
(map-indexed (fn [col c]
|
||||||
|
[[row col] c])
|
||||||
|
line)))
|
||||||
|
(apply concat)
|
||||||
|
(into {})))
|
||||||
|
|
||||||
|
(def offsets [[0 1] [0 -1] [1 0] [-1 0]])
|
||||||
|
|
||||||
|
;; part 1
|
||||||
|
(->> (loop [q [{:loc start, :visited #{}}]
|
||||||
|
ans #{}]
|
||||||
|
(if (empty? q)
|
||||||
|
ans
|
||||||
|
(let [[{:keys [loc visited]}] q
|
||||||
|
visited' (conj visited loc)
|
||||||
|
[x y] loc]
|
||||||
|
(if (= end loc)
|
||||||
|
(recur (rest q) (conj ans (count visited)))
|
||||||
|
(recur (concat (rest q)
|
||||||
|
(-> []
|
||||||
|
(>for [o offsets]
|
||||||
|
(>let [[x' y' :as loc'] (mapv + loc o)]
|
||||||
|
(>when (and (not (visited loc'))
|
||||||
|
(or (= \. (char-map loc'))
|
||||||
|
(and (= \> (char-map loc')) (< y y'))
|
||||||
|
(and (= \< (char-map loc')) (> y y'))
|
||||||
|
(and (= \v (char-map loc')) (< x x'))
|
||||||
|
(and (= \^ (char-map loc')) (> x x'))))
|
||||||
|
(conj loc'))))
|
||||||
|
(>each (#(hash-map :loc % :visited visited')))))
|
||||||
|
ans)))))
|
||||||
|
(apply max))
|
||||||
|
|
||||||
|
;; part 2
|
||||||
|
(->> (loop [q [{:loc start, :visited #{}}]
|
||||||
|
ans #{}]
|
||||||
|
(if (empty? q)
|
||||||
|
ans
|
||||||
|
(let [[{:keys [loc visited]}] q
|
||||||
|
visited' (conj visited loc)]
|
||||||
|
(if (= end loc)
|
||||||
|
(recur (rest q) (conj ans (count visited)))
|
||||||
|
(recur (concat (rest q)
|
||||||
|
(-> []
|
||||||
|
(>for [o offsets]
|
||||||
|
(>let [[x' y' :as loc'] (mapv + loc o)]
|
||||||
|
(>when (and (not (visited loc'))
|
||||||
|
(#{ \. \> \< \v \^} (char-map loc')))
|
||||||
|
(conj loc'))))
|
||||||
|
(>each (#(hash-map :loc % :visited visited')))))
|
||||||
|
ans)))))
|
||||||
|
(apply max))
|
Loading…
x
Reference in New Issue
Block a user