No Space Left On Device


Fork me on GitHub
2022-12-07

Day 07: No Space Left On Device

Description:
--- Day 7: No Space Left On Device ---

You can hear birds chirping and raindrops hitting leaves as the expedition proceeds. Occasionally, you can even hear much louder sounds in the distance; how big do the animals get out here, anyway?

The device the Elves gave you has problems with more than just its communication system. You try to run a system update:

$ system-update --please --pretty-please-with-sugar-on-top
Error: No space left on device

Perhaps you can delete some files to make space for the update?

You browse around the filesystem to assess the situation and save the resulting terminal output (your puzzle input). For example:

$ cd /
$ ls
dir a
14848514 b.txt
8504156 c.dat
dir d
$ cd a
$ ls
dir e
29116 f
2557 g
62596 h.lst
$ cd e
$ ls
584 i
$ cd ..
$ cd ..
$ cd d
$ ls
4060174 j
8033020 d.log
5626152 d.ext
7214296 k

The filesystem consists of a tree of files (plain data) and directories (which can contain other directories or files). The outermost directory is called /. You can navigate around the filesystem, moving into or out of directories and listing the contents of the directory you're currently in.

Within the terminal output, lines that begin with $ are commands you executed, very much like some modern computers:

cd means change directory. This changes which directory is the current directory, but the specific result depends on the argument:
cd x moves in one level: it looks in the current directory for the directory named x and makes it the current directory.
cd .. moves out one level: it finds the directory that contains the current directory, then makes that directory the current directory.
cd / switches the current directory to the outermost directory, /.
ls means list. It prints out all of the files and directories immediately contained by the current directory:
123 abc means that the current directory contains a file named abc with size 123.
dir xyz means that the current directory contains a directory named xyz.

Given the commands and output in the example above, you can determine that the filesystem looks visually like this:

- / (dir)
- a (dir)
- e (dir)
- i (file, size=584)
- f (file, size=29116)
- g (file, size=2557)
- h.lst (file, size=62596)
- b.txt (file, size=14848514)
- c.dat (file, size=8504156)
- d (dir)
- j (file, size=4060174)
- d.log (file, size=8033020)
- d.ext (file, size=5626152)
- k (file, size=7214296)

Here, there are four directories: / (the outermost directory), a and d (which are in /), and e (which is in a). These directories also contain files of various sizes.

Since the disk is full, your first step should probably be to find directories that are good candidates for deletion. To do this, you need to determine the total size of each directory. The total size of a directory is the sum of the sizes of the files it contains, directly or indirectly. (Directories themselves do not count as having any intrinsic size.)

The total sizes of the directories above can be found as follows:

The total size of directory e is 584 because it contains a single file i of size 584 and no other directories.
The directory a has total size 94853 because it contains files f (size 29116), g (size 2557), and h.lst (size 62596), plus file i indirectly (a contains e which contains i).
Directory d has total size 24933642.
As the outermost directory, / contains every file. Its total size is 48381165, the sum of the size of every file.

To begin, find all of the directories with a total size of at most 100000, then calculate the sum of their total sizes. In the example above, these directories are a and e; the sum of their total sizes is 95437 (94853 + 584). (As in this example, this process can count files more than once!)

Find all of the directories with a total size of at most 100000. What is the sum of the total sizes of those directories?

--- Part Two ---

Now, you're ready to choose a directory to delete.

The total disk space available to the filesystem is 70000000. To run the update, you need unused space of at least 30000000. You need to find a directory you can delete that will free up enough space to run the update.

In the example above, the total size of the outermost directory (and thus the total amount of used space) is 48381165; this means that the size of the unused space must currently be 21618835, which isn't quite the 30000000 required by the update. Therefore, the update still requires a directory with total size of at least 8381165 to be deleted before it can run.

To achieve this, you have the following options:

Delete directory e, which would increase unused space by 584.
Delete directory a, which would increase unused space by 94853.
Delete directory d, which would increase unused space by 24933642.
Delete directory /, which would increase unused space by 48381165.

Directories e and a are both too small; deleting them would not free up enough space. However, directories d and / are both big enough! Between these, choose the smallest: d, increasing unused space by 24933642.

Find the smallest directory that, if deleted, would free up enough space on the filesystem to run the update. What is the total size of that directory?

Input:
$ cd /
$ ls
dir lhrfs
193233 mvsjmrtn
dir nwh
dir pjsd
dir qfrrtb
31987 zzdfcs
$ cd lhrfs
$ ls
197903 hzl.jdj
42249 wsbpzmbq.hws
$ cd ..
$ cd nwh
$ ls
63077 bgrccm.tqh
69961 dznccwl.bnw
dir pmdj
187013 rsbvj.jtd
$ cd pmdj
$ ls
292527 rlgfd.rrd
68737 tbj.grn
153072 wsbpzmbq.hws
$ cd ..
$ cd ..
$ cd pjsd
$ ls
dir czzcslm
dir dgwpl
dir fqg
dir lszhdjr
dir mmpf
dir wtwhzzwz
149748 zzdfcs
$ cd czzcslm
$ ls
249237 bvrnzhd.vzp
16960 ssvqllt.ccv
$ cd ..
$ cd dgwpl
$ ls
23547 brsbfqbm.hls
dir ljzrwpv
$ cd ljzrwpv
$ ls
dir btnzjtlr
dir czr
$ cd btnzjtlr
$ ls
191998 tbj.mwg
$ cd ..
$ cd czr
$ ls
dir fqg
$ cd fqg
$ ls
276766 llhzr.pjh
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd fqg
$ ls
275942 bhcg
dir fqg
dir gghdbzz
dir hswgvpt
75273 hzl
dir lfpblmwt
dir sdcwn
dir wmrwd
$ cd fqg
$ ls
dir bpbtnq
267620 btnzjtlr.mgr
174395 fqg.vpw
dir tfbfgzw
dir twhvbbr
$ cd bpbtnq
$ ls
194542 mtztnd.hdb
$ cd ..
$ cd tfbfgzw
$ ls
dir cgdlflbt
10814 fqg.cqp
40235 fztb.jzr
dir hzl
$ cd cgdlflbt
$ ls
176005 wsbpzmbq.hws
$ cd ..
$ cd hzl
$ ls
dir ccpdp
dir hgwpjvn
dir hzl
203730 pbn.rzl
88179 tbj
295466 zdbmfmzs.jjh
$ cd ccpdp
$ ls
172836 btnzjtlr
$ cd ..
$ cd hgwpjvn
$ ls
122725 hnsrdnl.ctv
261470 tmgpjbj
$ cd ..
$ cd hzl
$ ls
59843 lffmd.fwr
$ cd ..
$ cd ..
$ cd ..
$ cd twhvbbr
$ ls
134874 hnsrdnl.ctv
$ cd ..
$ cd ..
$ cd gghdbzz
$ ls
dir fqg
$ cd fqg
$ ls
233336 ssvqllt.ccv
$ cd ..
$ cd ..
$ cd hswgvpt
$ ls
dir fwfhnbc
dir hcp
221595 hnsrdnl.ctv
230875 hzl
257695 jbfnlc.qqn
126050 tbj.qlc
dir wdlh
$ cd fwfhnbc
$ ls
293848 zhz.mff
$ cd ..
$ cd hcp
$ ls
288118 gdndr.gwn
$ cd ..
$ cd wdlh
$ ls
227328 btnzjtlr.msq
dir hzl
94325 hzl.wjp
272466 zzdfcs
$ cd hzl
$ ls
184779 ssvqllt.ccv
$ cd ..
$ cd ..
$ cd ..
$ cd lfpblmwt
$ ls
151071 ssvqllt.ccv
$ cd ..
$ cd sdcwn
$ ls
61632 hzl.mvp
dir tbj
dir tdwc
dir tnjcf
dir tstqdt
$ cd tbj
$ ls
dir btnzjtlr
dir cwsv
1318 tbj
293645 wnv
$ cd btnzjtlr
$ ls
2441 hnsrdnl.ctv
$ cd ..
$ cd cwsv
$ ls
238930 gwr
236116 tlzqtch
$ cd ..
$ cd ..
$ cd tdwc
$ ls
dir btnzjtlr
dir fqg
dir zgjpfj
$ cd btnzjtlr
$ ls
177427 tbj.hgf
$ cd ..
$ cd fqg
$ ls
241003 dbnwzbn.flv
$ cd ..
$ cd zgjpfj
$ ls
249565 fqg
238012 tbj.csq
$ cd ..
$ cd ..
$ cd tnjcf
$ ls
188504 lljwfglp.wnb
35384 wsbpzmbq.hws
$ cd ..
$ cd tstqdt
$ ls
dir lszhdjr
$ cd lszhdjr
$ ls
252181 ssvqllt.ccv
$ cd ..
$ cd ..
$ cd ..
$ cd wmrwd
$ ls
117914 btnzjtlr
224916 hnsrdnl.ctv
dir lszhdjr
112511 trjm.mrw
20365 trn
$ cd lszhdjr
$ ls
183834 sdnlhh.ntt
$ cd ..
$ cd ..
$ cd ..
$ cd lszhdjr
$ ls
dir gjlms
dir hrwjmrwf
dir vblznslv
$ cd gjlms
$ ls
301712 bbs.fhq
dir btnzjtlr
148329 cnvlrpbs.tqv
dir hzl
107466 hzl.zps
dir jgflpb
9865 trjm.mrw
$ cd btnzjtlr
$ ls
60204 nhmc
$ cd ..
$ cd hzl
$ ls
99518 lszhdjr.stz
$ cd ..
$ cd jgflpb
$ ls
251545 hzl.ncm
$ cd ..
$ cd ..
$ cd hrwjmrwf
$ ls
65264 btnzjtlr.qgg
123207 pqsn
30133 zzdfcs
$ cd ..
$ cd vblznslv
$ ls
19460 hzl
$ cd ..
$ cd ..
$ cd mmpf
$ ls
200340 dnsq
109756 snl
$ cd ..
$ cd wtwhzzwz
$ ls
dir bpwjhpgr
dir btnzjtlr
dir dgqljsbq
dir fqg
dir mbbtzgmf
dir vvmzhhtv
dir wglhbp
dir zcwmf
$ cd bpwjhpgr
$ ls
1514 mjczjz
$ cd ..
$ cd btnzjtlr
$ ls
209165 lszhdjr
$ cd ..
$ cd dgqljsbq
$ ls
160750 btnzjtlr
dir fqg
dir hrncl
5964 hzvr.ftp
dir jldnlddj
267082 qdc.grf
205213 sjpdjt.ngt
dir vws
175214 wzwwqq.stp
$ cd fqg
$ ls
dir ghsdjhj
$ cd ghsdjhj
$ ls
166720 jqcjngn.fmf
298171 zzdfcs
$ cd ..
$ cd ..
$ cd hrncl
$ ls
dir hzl
82355 trjm.mrw
dir vrqbf
261260 wsbpzmbq.hws
18593 wtmlmprg.whh
$ cd hzl
$ ls
344 drndgmgz.flz
241877 zzdfcs
$ cd ..
$ cd vrqbf
$ ls
dir blf
dir pzrfw
dir tbj
$ cd blf
$ ls
68629 wdhfbtj.ncc
$ cd ..
$ cd pzrfw
$ ls
dir hzl
dir mdh
dir tbj
$ cd hzl
$ ls
12677 gvdh.ltp
$ cd ..
$ cd mdh
$ ls
222003 qbvfdv
$ cd ..
$ cd tbj
$ ls
dir wtmcqwgp
$ cd wtmcqwgp
$ ls
dir stcgrs
$ cd stcgrs
$ ls
285843 tbj
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd tbj
$ ls
173380 mcgzmthd.mdg
$ cd ..
$ cd ..
$ cd ..
$ cd jldnlddj
$ ls
57836 brdtwc.pws
dir fqg
dir hzl
140902 lbn
dir qhrcm
dir ssrc
169907 wsbpzmbq.hws
$ cd fqg
$ ls
273621 pwjr.gwt
$ cd ..
$ cd hzl
$ ls
dir fqg
dir tbj
$ cd fqg
$ ls
290882 hcf.sqw
62759 hlntl.zqg
115593 ntgm.wjn
64481 qwtv
$ cd ..
$ cd tbj
$ ls
199421 gsvpcdm
200467 hnsrdnl.ctv
9980 lgqgdvwz.zdp
dir lqlml
19593 pgn
51598 tqqbwd
$ cd lqlml
$ ls
92416 fdwgg.rdp
279285 zzdfcs
$ cd ..
$ cd ..
$ cd ..
$ cd qhrcm
$ ls
278543 trjm.mrw
279502 zzdfcs
$ cd ..
$ cd ssrc
$ ls
238789 zfvwwnhl
$ cd ..
$ cd ..
$ cd vws
$ ls
249170 bgfrh
dir ndtnt
$ cd ndtnt
$ ls
5224 qwdnzdq.rfz
$ cd ..
$ cd ..
$ cd ..
$ cd fqg
$ ls
171994 trjm.mrw
$ cd ..
$ cd mbbtzgmf
$ ls
dir cfqzlgm
57211 ssvqllt.ccv
dir tbj
$ cd cfqzlgm
$ ls
dir tlbgq
$ cd tlbgq
$ ls
232962 ssvqllt.ccv
$ cd ..
$ cd ..
$ cd tbj
$ ls
23083 lszhdjr.lzt
$ cd ..
$ cd ..
$ cd vvmzhhtv
$ ls
150567 fcpv.vws
$ cd ..
$ cd wglhbp
$ ls
dir cjm
dir gjhzw
dir lmzzlp
123986 lszhdjr.hcj
275863 lwbz
121332 snnhqgp.tdj
dir stngv
dir wdzvcfm
dir wjqztbj
dir wzhsq
$ cd cjm
$ ls
300643 jhtjsn.hzm
$ cd ..
$ cd gjhzw
$ ls
dir hwlj
dir tbj
$ cd hwlj
$ ls
280279 ssvqllt.ccv
$ cd ..
$ cd tbj
$ ls
88746 ssvqllt.ccv
139206 tbj
$ cd ..
$ cd ..
$ cd lmzzlp
$ ls
9261 btnzjtlr
dir fqg
128118 fqg.fsf
165323 hnsrdnl.ctv
dir prvmm
$ cd fqg
$ ls
35303 dcglqd.zrj
71812 mvzh
32361 ssvqllt.ccv
69305 zzdfcs
$ cd ..
$ cd prvmm
$ ls
296946 zzdfcs
$ cd ..
$ cd ..
$ cd stngv
$ ls
dir hgj
46259 vlb.ztz
25946 zstwl.wgs
106712 zzdfcs
$ cd hgj
$ ls
289819 dhwr.mvc
85418 dvpvhhgj.fmw
108543 fqg.frj
229544 pwhwmctv
$ cd ..
$ cd ..
$ cd wdzvcfm
$ ls
dir sdphr
$ cd sdphr
$ ls
84638 hnsrdnl.ctv
$ cd ..
$ cd ..
$ cd wjqztbj
$ ls
240174 btnzjtlr.ldw
125567 lszhdjr
265718 lszhdjr.mmz
242407 wzjcc
$ cd ..
$ cd wzhsq
$ ls
dir hzl
22176 hzl.cpv
122990 ldtwhvc.vcv
$ cd hzl
$ ls
309519 plnn.pdn
$ cd ..
$ cd ..
$ cd ..
$ cd zcwmf
$ ls
dir hwq
268508 mztd
$ cd hwq
$ ls
189618 trjm.mrw
120145 wsbpzmbq.hws
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd qfrrtb
$ ls
dir dmntr
dir fqg
dir gpcvsbpl
dir hzl
dir mqbhs
dir pgvngj
dir pnrdwlqn
dir qlnwhq
$ cd dmntr
$ ls
dir btnzjtlr
141598 fqg.wcw
223036 hnsrdnl.ctv
96925 qhwmj
257697 ssvqllt.ccv
184839 vmbfhldv.zgm
$ cd btnzjtlr
$ ls
153689 jnbthqwp
dir tcp
$ cd tcp
$ ls
90378 mczzfwsz.hwf
$ cd ..
$ cd ..
$ cd ..
$ cd fqg
$ ls
dir btq
51590 fqg
176455 gnqsnpj.vsh
dir mthwtst
dir trhz
dir zbpjvb
$ cd btq
$ ls
dir bdnc
dir ttpj
dir vftshfd
$ cd bdnc
$ ls
263358 trjm.mrw
$ cd ..
$ cd ttpj
$ ls
185501 fqg.dvq
151107 ltmmsr.lqd
dir mbtqmqh
231236 sdzp.qhb
16601 vfflgw.vrr
75487 zbvllh.gqb
$ cd mbtqmqh
$ ls
dir lszhdjr
184660 pmwswf.lrm
dir tbj
dir zqbss
262042 zzdfcs
$ cd lszhdjr
$ ls
dir dmc
$ cd dmc
$ ls
173189 mzmr.nrj
$ cd ..
$ cd ..
$ cd tbj
$ ls
59531 fjqfbq
$ cd ..
$ cd zqbss
$ ls
dir btnzjtlr
dir lszhdjr
14365 sqdj
$ cd btnzjtlr
$ ls
113619 trjm.mrw
$ cd ..
$ cd lszhdjr
$ ls
87142 hnsrdnl.ctv
dir lszhdjr
$ cd lszhdjr
$ ls
dir jsdrvbhc
$ cd jsdrvbhc
$ ls
210295 hzl
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd vftshfd
$ ls
dir jjws
dir mvdcjgp
dir qflcrlrm
$ cd jjws
$ ls
82848 trjm.mrw
$ cd ..
$ cd mvdcjgp
$ ls
231865 lzzl
$ cd ..
$ cd qflcrlrm
$ ls
150667 btnzjtlr
$ cd ..
$ cd ..
$ cd ..
$ cd mthwtst
$ ls
26308 lszhdjr.dbb
$ cd ..
$ cd trhz
$ ls
16138 swtdz.hdt
$ cd ..
$ cd zbpjvb
$ ls
69598 hnsrdnl.ctv
96314 tbj.gpj
$ cd ..
$ cd ..
$ cd gpcvsbpl
$ ls
dir dbssfzqt
dir pgn
dir zfgvldv
$ cd dbssfzqt
$ ls
156599 jcv
68192 zzdfcs
$ cd ..
$ cd pgn
$ ls
124613 fqg
139219 gmnqvlbb.nnf
177527 hnsrdnl.ctv
116238 hzl.qwm
dir tbj
69576 zzdfcs
$ cd tbj
$ ls
78863 hnsrdnl.ctv
dir lszhdjr
$ cd lszhdjr
$ ls
76043 qjwjw.dbn
$ cd ..
$ cd ..
$ cd ..
$ cd zfgvldv
$ ls
dir tbj
$ cd tbj
$ ls
308796 gqcw.fsm
$ cd ..
$ cd ..
$ cd ..
$ cd hzl
$ ls
50784 btnzjtlr
19755 gjbcgphh.rbw
169847 lncnj.bct
46359 mbrtgl
dir nlnt
269695 wfg.cdn
$ cd nlnt
$ ls
dir cqfzqwr
dir dghdql
dir fnd
159573 hnsrdnl.ctv
dir lszhdjr
16814 tsm
59202 wsbpzmbq.hws
22244 zlbj
$ cd cqfzqwr
$ ls
213009 trjm.mrw
$ cd ..
$ cd dghdql
$ ls
61202 hnsrdnl.ctv
$ cd ..
$ cd fnd
$ ls
237330 hnsrdnl.ctv
$ cd ..
$ cd lszhdjr
$ ls
222813 ssvqllt.ccv
$ cd ..
$ cd ..
$ cd ..
$ cd mqbhs
$ ls
dir fqg
$ cd fqg
$ ls
121590 lcwsbvw.jlj
13769 zzdfcs
$ cd ..
$ cd ..
$ cd pgvngj
$ ls
29079 lnfsw.mvd
dir tbj
$ cd tbj
$ ls
303514 ssvqllt.ccv
81789 wsbpzmbq.hws
$ cd ..
$ cd ..
$ cd pnrdwlqn
$ ls
145498 btnzjtlr.hdq
209811 fqg
dir gscsq
39287 jbln.grc
dir lszhdjr
dir zcj
$ cd gscsq
$ ls
dir btnzjtlr
257666 cmflqncq.csp
146453 lszhdjr.jvl
21252 ssvqllt.ccv
dir vjpgs
29627 zjgswm.zmw
$ cd btnzjtlr
$ ls
52870 fqg.bcq
131279 hnsrdnl.ctv
dir hts
180154 plgqz.lfz
118677 ssvqllt.ccv
143055 zzdfcs
$ cd hts
$ ls
295829 hnsrdnl.ctv
$ cd ..
$ cd ..
$ cd vjpgs
$ ls
247444 fqg.rjw
dir hzl
113248 tbj
$ cd hzl
$ ls
91966 ppff.qhn
$ cd ..
$ cd ..
$ cd ..
$ cd lszhdjr
$ ls
290399 grzs.btl
11125 gswg
110268 mhdfszz.pdh
dir mwbjshb
dir ndtllttm
126485 wsbpzmbq.hws
152691 zzdfcs
$ cd mwbjshb
$ ls
119607 rpgml
$ cd ..
$ cd ndtllttm
$ ls
5107 qsqqfpc.mzf
$ cd ..
$ cd ..
$ cd zcj
$ ls
dir gftzs
131397 ssvqllt.ccv
dir vpqvpmv
dir wdqw
34540 wsbpzmbq.hws
$ cd gftzs
$ ls
115531 fbjj.vrn
$ cd ..
$ cd vpqvpmv
$ ls
dir bfqpwgdc
67619 ffbllv
dir tzr
$ cd bfqpwgdc
$ ls
144904 fqg.djq
dir gbn
dir jzz
dir vtp
$ cd gbn
$ ls
dir btnzjtlr
$ cd btnzjtlr
$ ls
dir dzsbcqjd
253792 fqg.fcw
209245 fqtqsdrt.pqd
303280 nqvqm
271246 vchvvq.cft
$ cd dzsbcqjd
$ ls
13953 tbj
$ cd ..
$ cd ..
$ cd ..
$ cd jzz
$ ls
234810 ssvqllt.ccv
$ cd ..
$ cd vtp
$ ls
287225 rzqfq.pvj
$ cd ..
$ cd ..
$ cd tzr
$ ls
135596 bbzlnjtc.fft
dir bqfz
dir dztgr
306047 hnsrdnl.ctv
248180 jzdzf
dir lszhdjr
dir mds
dir nmdc
dir qpmt
126445 wsbpzmbq.hws
191907 zzdfcs
$ cd bqfz
$ ls
137988 fqg
122217 lszhdjr.bwc
232293 ssvqllt.ccv
168937 twrtmwh.ddc
$ cd ..
$ cd dztgr
$ ls
23653 qhrp.ljh
$ cd ..
$ cd lszhdjr
$ ls
dir ghqlj
dir qjjvfv
dir qsjrnq
$ cd ghqlj
$ ls
184316 ghshmzt.srl
258282 nbqndwj
dir ndd
dir tqqlnw
68843 trjm.mrw
92593 wllcqzfr.mbd
$ cd ndd
$ ls
152924 gvclc
77856 llztchwp.jjd
$ cd ..
$ cd tqqlnw
$ ls
4090 flvdsc.zsv
219378 vgwfn.zjh
$ cd ..
$ cd ..
$ cd qjjvfv
$ ls
230606 trjm.mrw
$ cd ..
$ cd qsjrnq
$ ls
252853 fnnbmt.dtm
279660 lszhdjr.rjc
$ cd ..
$ cd ..
$ cd mds
$ ls
10903 jzwjv
$ cd ..
$ cd nmdc
$ ls
114234 hnsrdnl.ctv
$ cd ..
$ cd qpmt
$ ls
171542 bvrzgp
129238 hnsrdnl.ctv
137570 tbj
54929 vtcfq.npn
44117 zzdfcs
$ cd ..
$ cd ..
$ cd ..
$ cd wdqw
$ ls
dir jmvsdlv
dir mjgpdcbl
$ cd jmvsdlv
$ ls
dir flnnqz
$ cd flnnqz
$ ls
224693 flqpwqp.fwn
$ cd ..
$ cd ..
$ cd mjgpdcbl
$ ls
140928 btnzjtlr.prd
$ cd ..
$ cd ..
$ cd ..
$ cd ..
$ cd qlnwhq
$ ls
dir btnzjtlr
dir cbhr
dir cnbssw
dir dwvv
dir lszhdjr
dir rnhnbs
dir sdhqp
$ cd btnzjtlr
$ ls
225671 ssrcp.chb
268250 tbj.cfd
$ cd ..
$ cd cbhr
$ ls
68468 qdqlml.qrj
$ cd ..
$ cd cnbssw
$ ls
dir tbj
187921 zscs
$ cd tbj
$ ls
307230 hzl
dir jbcnnvq
228268 lssvr.gfn
$ cd jbcnnvq
$ ls
277047 nztsr
$ cd ..
$ cd ..
$ cd ..
$ cd dwvv
$ ls
267743 btnzjtlr
dir fqg
68364 qznpsjp
dir wdr
230595 wsbpzmbq.hws
206 wtwwd.jnb
$ cd fqg
$ ls
260003 btnzjtlr.hjn
103775 btnzjtlr.ndh
200945 trjm.mrw
dir twpplmhh
$ cd twpplmhh
$ ls
dir tvrq
$ cd tvrq
$ ls
298383 ssvqllt.ccv
$ cd ..
$ cd ..
$ cd ..
$ cd wdr
$ ls
248357 tbj
$ cd ..
$ cd ..
$ cd lszhdjr
$ ls
259605 lszhdjr.mvw
$ cd ..
$ cd rnhnbs
$ ls
297597 hnsrdnl.ctv
$ cd ..
$ cd sdhqp
$ ls
95362 wsbpzmbq.hws

Part 1:
import std/strutils
import std/sequtils
import std/re

type
  DirEntry = ref object
    parent: DirEntry
    name: string
    dirs: seq[DirEntry]
    files: seq[FileEntry]
  FileEntry = ref object
    name: string
    size: int


proc mkcd(a: DirEntry, name: string): DirEntry =
  for i in 0.. (a.dirs.len() - 1):
    if a.dirs[i].name == name:
        return a.dirs[i]
  a.dirs.add(DirEntry(parent: a, name: name, dirs: @[], files: @[]))
  return a.dirs[len(a.dirs)-1]

proc recursive_size(a: DirEntry): int =
    var sz = 0
    for d in a.dirs:
        sz += d.recursive_size()
    for f in a.files:
        sz += f.size
    return sz

proc sum_size_sub(a: DirEntry, max: int): int =
    let sz = a.recursive_size()
    var res = 0
    if sz < max:
        res += sz
    for d in a.dirs:
        res += d.sum_size_sub(max)
    return res

proc print(a: DirEntry, indent: int) =
    echo ' '.repeat(indent*2), a.name, " (sz = ", a.recursive_size(), " )"
    echo ' '.repeat(indent*2), "{"
    for f in a.files:
        echo ' '.repeat(indent*2+2), "[F] ", f.name, " (sz = ", f.size, " )"
    for d in a.dirs:
        d.print(indent+1)
    echo ' '.repeat(indent*2), "}"


proc run07_1(): string =
    const input = staticRead"../input/day07.txt"

    let lines = splitLines(input).filter(proc(p: string): bool = p != "")

    var root = DirEntry(parent: nil, name: "/", dirs: @[], files: @[])

    var curr = root

    for line in lines:
        if line == "$ cd ..":
            curr = curr.parent
        elif line.startsWith("$ cd "):
            curr = curr.mkcd(line.substr(5))
        elif line == "$ ls":
            continue
        elif line.startsWith("dir "):
            discard curr.mkcd(line.substr(4))
        elif line.match(re"^[0-9].*"):
            let split = line.split(" ")
            curr.files.add(FileEntry(name: split[1], size: parseInt(split[0])))
        else:
            echo "UNKNOWN LINE: " & line


    # echo root.recursive_size()
    # root.print(0)

    return intToStr(root.sum_size_sub(100000))


when not defined(js):
    echo run07_1()
else:
    proc js_run07_1(): cstring {.exportc.} =
        return cstring(run07_1())
Result: 1243729

Part 2:
import std/strutils
import std/sequtils
import std/algorithm
import std/re

type
  DirEntry = ref object
    parent: DirEntry
    name: string
    dirs: seq[DirEntry]
    files: seq[FileEntry]
  FileEntry = ref object
    name: string
    size: int


proc mkcd(a: DirEntry, name: string): DirEntry =
  for i in 0.. (a.dirs.len() - 1):
    if a.dirs[i].name == name:
        return a.dirs[i]
  a.dirs.add(DirEntry(parent: a, name: name, dirs: @[], files: @[]))
  return a.dirs[len(a.dirs)-1]

proc recursive_size(a: DirEntry): int =
    var sz = 0
    for d in a.dirs:
        sz += d.recursive_size()
    for f in a.files:
        sz += f.size
    return sz

proc sum_size_sub(a: DirEntry, max: int): int =
    let sz = a.recursive_size()
    var res = 0
    if sz < max:
        res += sz
    for d in a.dirs:
        res += d.sum_size_sub(max)
    return res

proc print(a: DirEntry, indent: int) =
    echo ' '.repeat(indent*2), a.name, " (sz = ", a.recursive_size(), " )"
    echo ' '.repeat(indent*2), "{"
    for f in a.files:
        echo ' '.repeat(indent*2+2), "[F] ", f.name, " (sz = ", f.size, " )"
    for d in a.dirs:
        d.print(indent+1)
    echo ' '.repeat(indent*2), "}"

proc collect_dirs(a: DirEntry, coll: var seq[DirEntry]) =
    coll.add(a)
    for d in a.dirs:
        coll.add(d)
        d.collect_dirs(coll)


proc run07_2(): string =
    const input = staticRead"../input/day07.txt"

    let lines = splitLines(input).filter(proc(p: string): bool = p != "")

    var root = DirEntry(parent: nil, name: "/", dirs: @[], files: @[])

    var curr = root

    for line in lines:
        if line == "$ cd ..":
            curr = curr.parent
        elif line.startsWith("$ cd "):
            curr = curr.mkcd(line.substr(5))
        elif line == "$ ls":
            continue
        elif line.startsWith("dir "):
            discard curr.mkcd(line.substr(4))
        elif line.match(re"^[0-9].*"):
            let split = line.split(" ")
            curr.files.add(FileEntry(name: split[1], size: parseInt(split[0])))
        else:
            echo "UNKNOWN LINE: " & line


    # echo root.recursive_size()

    # root.print(0)

    var dirs: seq[DirEntry] = @[]
    root.collect_dirs(dirs)

    proc scmp(a, b: DirEntry): int =
        if a.recursive_size() < b.recursive_size(): -1
        else: 1

    dirs.sort(scmp)

    let min_size = -(70000000 - 30000000 - root.recursive_size())

    # echo min_size

    for d in dirs:
        if d.recursive_size() > min_size:
            return intToStr(d.recursive_size())

    return "ERR"


when not defined(js):
    echo run07_2()
else:
    proc js_run07_2(): cstring {.exportc.} =
        return cstring(run07_2())
Result: 4443914


made with vanilla PHP and MySQL, no frameworks, no bootstrap, no unnecessary* javascript