mirror of
https://github.com/Ajetski/advent-of-code.git
synced 2025-09-30 09:23:17 -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]
|
||||
[clojure.string :as string]))
|
||||
|
||||
(def input-cache (atom {}))
|
||||
(def cookie (str "session=" (slurp "session")))
|
||||
|
||||
(defn get-puzzle-input
|
||||
"retrieves and caches aoc input for 2023 given a day"
|
||||
[day]
|
||||
(or (@input-cache day)
|
||||
(swap! input-cache assoc day
|
||||
(-> (str "https://adventofcode.com/2023/day/" day "/input")
|
||||
(let [file (java.io.File. (str "inputs/day" day ".txt"))]
|
||||
(or (when (.exists file)
|
||||
(string/split-lines (slurp file)))
|
||||
(let [data (-> (str "https://adventofcode.com/2023/day/" day "/input")
|
||||
(client/get {:throw-entire-message? true
|
||||
:headers {"Cookie" cookie}})
|
||||
:body
|
||||
string/split-lines))))
|
||||
:body)]
|
||||
(spit file data)
|
||||
(string/split-lines data)))))
|
||||
|
||||
(defn re-seq-pos
|
||||
"re-seq that produces a seq of {:start :end :group}"
|
||||
@ -40,32 +41,14 @@
|
||||
~@body)))
|
||||
|
||||
(defmacro comp>
|
||||
"comp, but fn-args are composed from left to right with currying
|
||||
previous result inserted as first element to next function application"
|
||||
[& ls]
|
||||
(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)))
|
||||
"generates a closure that composes inputs with clojure.core/-> semantics"
|
||||
[& forms]
|
||||
`(fn [v#] (-> v# ~@forms)))
|
||||
|
||||
(defmacro comp>>
|
||||
"comp, but fn-args are composed from left to right with currying
|
||||
previous result inserted as last element to next function application"
|
||||
[& ls]
|
||||
(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)))
|
||||
"generates a closure that composes inputs with clojure.core/->> semantics"
|
||||
[& forms]
|
||||
`(fn [v#] (->> v# ~@forms)))
|
||||
|
||||
(defmacro w-fn
|
||||
"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
|
||||
an f from fs to the corresponding v from vs"
|
||||
[& args]
|
||||
;; TODO: add spec or manual validation for args
|
||||
(let [n (/ (count args) 2)]
|
||||
(->> (zipmap (take n args)
|
||||
(take-last n args))
|
||||
@ -126,17 +110,19 @@
|
||||
|
||||
this function returns a vector where each value is the result of applying
|
||||
an f from fs to the corresponding value from v"
|
||||
;; TODO: add spec or manual validation for args
|
||||
[& args]
|
||||
(->> (zipmap (drop-last args)
|
||||
(last args))
|
||||
(mapv #((first %) (second %)))))
|
||||
|
||||
(def p partial)
|
||||
(defmacro assert-all [& assertions]
|
||||
`(do ~@(map (fn [assertion]
|
||||
`(assert ~assertion))
|
||||
assertions)))
|
||||
|
||||
(defmacro assert= [& abs]
|
||||
`(do ~@(map (fn [[a b]]
|
||||
`(assert (= ~a ~b)))
|
||||
(partition 2 abs))))
|
||||
(defn partial< [f & args1]
|
||||
(fn [& args2] (apply f (concat args2 args1))))
|
||||
|
||||
(comment
|
||||
|
||||
@ -152,18 +138,18 @@
|
||||
(dec 2)
|
||||
(+ (/ 1 2)
|
||||
(/ 1 2))))
|
||||
|
||||
(assert=
|
||||
8 ((comp> (+ 1) (/ 2) (abc 1) (inc) ;; currying / partial fn applicaiton
|
||||
(assert
|
||||
(= ((comp> (+ 1) (/ 2) (abc 1) (inc) ;; currying / partial fn applicaiton
|
||||
inc ;; named fn
|
||||
#(+ 1 %) (fn [v] (+ v 1))) ;; using lambdas
|
||||
5)
|
||||
|
||||
3 ((comp> (- 5) (- 2))
|
||||
8))
|
||||
(assert (= ((comp> (- 5) (- 2))
|
||||
10)
|
||||
|
||||
7 ((comp>> (- 5) (- 2))
|
||||
10))
|
||||
3))
|
||||
(assert (= ((comp>> (- 5) (- 2))
|
||||
10)
|
||||
7))
|
||||
|
||||
(map (w-fn Long/parseLong) ["123" "456"])
|
||||
input-cache
|
||||
@ -172,14 +158,20 @@
|
||||
((reducef + 0) [1 2])
|
||||
|
||||
(let [v 20]
|
||||
(assert= ((comp> #(* % 3) #(+ % 2) #(* % 4))
|
||||
(assert (= ((comp> #(* % 3) #(+ % 2) #(* % 4))
|
||||
v)
|
||||
((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-v #(* % 2) #(+ % 5) [5 10]))
|
||||
(apply-each-v #(* % 2) #(+ % 5) [5 10])
|
||||
[10 15]))
|
||||
|
||||
(log (+ 5 5)
|
||||
(- 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