10000 Solve 07 2022 · motform/advent-of-clojure@08f8041 · GitHub
[go: up one dir, main page]

Skip to content

Commit 08f8041

Browse files
committed
Solve 07 2022
1 parent 0218dcf commit 08f8041

File tree

1 file changed

+113
-0
lines changed
  • src/advent_of_clojure/2022

1 file changed

+113
-0
lines changed

src/advent_of_clojure/2022/07.clj

Lines changed: 113 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,113 @@
1+
(ns advent-of-clojure.2022.07
2+
(:require [clojure.string :as str]
3+
[clojure.walk :as walk]))
4+
5+
(defmulti parse first)
6+
7+
(defmethod parse \$ [line]
8+
(let [[command target] (re-seq #"\w+|\/|\.+" line)]
9+
{:type :command :command (keyword command) :target target}))
10+
11+
(defmethod parse \d [line]
12+
(let [[_ name] (str/split line #" ")]
13+
{:type :dir :name name}))
14+
15+
(defmethod parse :default [line]
16+
(let [[size name] (str/split line #" ")]
17+
{:type :file :size (parse-long size) :name name}))
18+
19+
(def input (->> "resources/2022/07.dat" slurp str/split-lines (mapv parse)))
20+
21+
(defmulti build-tree #(-> % :commands first :type))
22+
23+
(defn change-dir [state target]
24+
(case target
25+
"/" (assoc state :path ["/"])
26+
".." (update state :path pop)
27+
(update state :path conj target)))
28+
29+
(defmethod build-tree :command [{:keys [commands] :as state}]
30+
(let [{:keys [command target]} (first commands)]
31+
(cond-> state
32+
(= command :cd) (change-dir target)
33+
:always (update :commands rest))))
34+
35+
(defmethod build-tree :default [{:keys [path commands] :as state}]
36+
(let [{:keys [type size name]} (first commands)]
37+
(-> state
38+
(update :tree assoc-in (conj path name) {:file/type type :file/size size})
39+
(update :commands rest))))
40+
41+
(defn dir-size [tree]
42+
(for [[_ v] tree]
43+
(when (map? v)
44+
(if-let [size (:file/size v)]
45+
size
46+
(dir-size v)))))
47+
48+
(defn dir? [node]
49+
(= :dir (get node :file/type)))
50+
51+
(defn calculate-dir-sizes [node]
52+
(if (dir? node)
53+
(assoc node :file/size (->> node dir-size flatten (remove nil?) (apply +)))
54+
node))
55+
56+
(defn dir-sizes [tree]
57+
(let [sizes (atom [])]
58+
(walk/prewalk
59+
(fn [node]
60+
(when (dir? node) (swap! sizes conj (:file/size node)))
61+
node)
62+
tree)
63+
@sizes))
64+
65+
(defn filesystem-tree [commands]
66+
(->> {:tree {"/" {:file/type :dir}} :path [] :commands commands}
67+
(iterate build-tree)
68+
(take-while #(-> % :commands seq))
69+
last build-tree))
70+
71+
(def max-size 100000)
72+
73+
(def part-one
74+
(->> input
75+
filesystem-tree
76+
(walk/prewalk calculate-dir-sizes)
77+
dir-sizes
78+
(filter #(> max-size %))
79+
(reduce +)))
80+
81+
(defn find-dir-to-delete [input]
82+
(let [filesystem-tree (walk/prewalk calculate-dir-sizes (filesystem-tree input))
83+
sizes (dir-sizes filesystem-tree)
84+
free (- 70000000 (apply max sizes))]
85+
(->> sizes
86+
(map (fn [size] [(+ free size) size]))
87+
(filter #(< 30000000 (first %)))
88+
(map second)
89+
(apply min))))
90+
91+
(def part-two (find-dir-to-delete input))
92+
93+
(comment
94+
;; We want a tree to look like this:
95+
(def example-tree
96+
{"/" {:file/type :dir,
97+
"a" {:file/type :dir,
98+
"e" {:file/type :dir,
99+
"i" #:file{:type :file, :size 584}},
100+
"f" #:file{:type :file, :size 29116},
101+
"g" #:file{:type :file, :size 2557},
102+
"h.lst" #:file{:type :file, :size 62596}},
103+
"b.txt" #:file{:type :file, :size 14848514},
104+
"c.dat" #:file{:type :file, :size 8504156},
105+
"d" {:file/type :dir,
106+
"j" #:file{:type :file, :size 4060174},
107+
"d.log" #:file{:type :file, :size 8033020},
108+
"d.ext" #:file{:type :file, :size 5626152},
109+
"k" #:file{:type :file, :size 7214296}}}})
110+
;; So that we can (get-in tree path) as path is a vector of keys.
111+
)
112+
113+

0 commit comments

Comments
 (0)
0