From 31348da8d4d144b987d6c67ea7306603dd8e3fb2 Mon Sep 17 00:00:00 2001 From: Adam Jeniski Date: Fri, 15 Dec 2023 22:55:05 -0500 Subject: [PATCH] add memoizing utils --- 2023/src/core.clj | 25 ++++++++++++++++- 2023/src/day12.clj | 67 ++++++++++++++++++++++------------------------ 2 files changed, 56 insertions(+), 36 deletions(-) diff --git a/2023/src/core.clj b/2023/src/core.clj index 7f22c8e..3637f8c 100644 --- a/2023/src/core.clj +++ b/2023/src/core.clj @@ -46,6 +46,29 @@ ([f] #(reduce f %)) ([f init] #(reduce f init %))) +(defmacro mfn + "like fn but memoizes return values, including recursive calls" + [name arglist & body] + `(let [dp# (atom {}) + f# (fn ~name ~arglist + (or (@dp# [~@arglist]) + (let [res# ~@body] + (swap! dp# assoc [~@arglist] res#) + res#)))] + f#)) + +(defmacro defmfn + "like defn but for a memoized fn, see ajet.core/mfn" + [name & args] + `(def ~name (mfn ~name ~@args))) + (comment (map (static-fn Long/parseLong) ["123" "456"]) - input-cache) + input-cache + + (defmfn fib [x] + (if (< x 2) + x + (+ (fib (dec x)) + (fib (- x 2))))) + (fib 200N)) diff --git a/2023/src/day12.clj b/2023/src/day12.clj index 0b8f4cb..debba71 100644 --- a/2023/src/day12.clj +++ b/2023/src/day12.clj @@ -1,50 +1,47 @@ (ns day12 (:require [clojure.string :as str] - [core :refer [get-puzzle-input]])) + [core :refer [get-puzzle-input mfn]])) (defn parse-line [line] (-> (str/split line #" ") (update 1 #(->> (str/split % #",") (mapv parse-long))))) (defn ans [dots blocks] - (let [dp (atom {}) - f - (fn f [dots blocks i bi current] - (or (@dp [i bi current]) - (let [len-blocks (count blocks) - dot_i (when (< i (count dots)) (get dots i)) - v (if (= i (count dots)) - (cond (and (= bi len-blocks) - (= current 0)) - 1 - (and (= bi (dec len-blocks)) - (= current (get blocks bi))) - 1 - :else - 0) - (->> [\. \#] - (map #(if (or (= dot_i %) - (= dot_i \?)) - (cond (and (= % \.) - (= current 0)) - (f dots blocks (inc i) bi 0) + (let + [len-blocks (count blocks) + f + (mfn f [i bi current] + (let [dot-i (when (< i (count dots)) (get dots i))] + (if (= i (count dots)) + (cond (and (= bi len-blocks) + (= current 0)) + 1 + (and (= bi (dec len-blocks)) + (= current (get blocks bi))) + 1 + :else + 0) + (->> [\. \#] + (map #(if (or (= dot-i %) + (= dot-i \?)) + (cond (and (= % \.) + (= current 0)) + (f (inc i) bi 0) - (and (= % \.) - (> current 0) - (< bi len-blocks) - (= (get blocks bi) current)) - (f dots blocks (inc i) (inc bi) 0) + (and (= % \.) + (> current 0) + (< bi len-blocks) + (= (get blocks bi) current)) + (f (inc i) (inc bi) 0) - (= % \#) - (f dots blocks (inc i) bi (inc current)) + (= % \#) + (f (inc i) bi (inc current)) - :else 0) - 0)) - (reduce +)))] - (swap! dp assoc [i bi current] v) - v)))] - (f dots blocks 0 0 0))) + :else 0) + 0)) + (reduce +)))))] + (f 0 0 0))) ;; part 1 (->> (get-puzzle-input 12)