about summary refs log tree commit diff
path: root/aoc/2022/07/part-two.janet
blob: 36c25f167e25472d8a9d3b41817d538d38077ada (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
#!/usr/bin/env janet
(def grammar
  ~{:filename (<- (some :S))
    :dirname (+ (/ "/" :root)
                (/ ".." :parent)
                :filename)
    :cd (* "$ cd " (constant :cd)
           :dirname
           "\n")
    :file (* (<- :d+)
             " "
             (constant :name)
             :filename)
    :dir (* (constant :dir)
            "dir "
            (constant :name)
            :dirname)
    :ls (* "$ ls\n" (constant :ls)
           (group (any (/ (* (constant :stat)
                             (+ :file :dir)
                             "\n")
                          ,struct))))
    :main (some (/ (+ :cd :ls)
                   ,tuple))})

(defn du [fs]
  (if (number? fs)
    [fs]
    (reduce (fn [[parent & children] [child & grandchildren]]
                [(+ parent child)
                 (splice children)
                 (if (empty? grandchildren)
                   []
                   [child (splice grandchildren)])])
            [0]
            (map du (values fs)))))

(var path nil)
(let [fs (table)]
  (each [cmd rest]
        (peg/match grammar (:read stdin :all))
        (cond (= cmd :ls) (each {:name name :stat stat}
                            rest
                            (set ((array/peek path)
                                  name)
                                 (if (= stat :dir)
                                   (table)
                                   (scan-number stat))))
              (= rest :root) (set path (array fs))
              (= rest :parent) (array/pop path)
              (let [last (array/peek path)]
                (unless (last rest)
                  (set (last rest)
                       (table)))
                (array/push path (last rest)))))
  (let [usages (flatten (du fs))]
    (print (min (splice (filter (fn [n]
                                  (>= (+ n 40_000_000)
                                      (first usages)))
                                usages))))))