111 lines
2.6 KiB
Nim
111 lines
2.6 KiB
Nim
|
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())
|