119 lines
2.6 KiB
Python
119 lines
2.6 KiB
Python
"""
|
|
parse commandline output, reconstruct a filesystem and determine the sum of all folders < 100kB
|
|
"""
|
|
|
|
TESTRUN = True
|
|
|
|
test_text = """$ 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
|
|
"""
|
|
|
|
with open('2022/7/stdout.txt') as filein:
|
|
input_text = filein.read()
|
|
|
|
text = test_text if TESTRUN else input_text
|
|
|
|
|
|
def parse_stdin(stdin: str):
|
|
outputs = stdin.split('$')
|
|
outputs = [[line.strip() for line in output.splitlines()] for output in outputs if output]
|
|
return recursive_parse(outputs)
|
|
|
|
|
|
def recursive_parse(outputs: list):
|
|
structure = {}
|
|
while True:
|
|
try:
|
|
current = outputs.pop(0)
|
|
except IndexError:
|
|
return structure
|
|
command = current.pop(0)
|
|
|
|
if command.startswith('ls'):
|
|
content = [c.split() for c in current]
|
|
for value, name in content:
|
|
structure[name] = int(value) if value.isnumeric() else value
|
|
|
|
elif command.startswith('cd'):
|
|
destination = command.split()[1]
|
|
if destination == '..':
|
|
return structure
|
|
else:
|
|
structure[destination] = recursive_parse(outputs)
|
|
|
|
|
|
def recursive_sum(d: dict, folders: list = None, initial=True):
|
|
s = 0
|
|
folders = [] if folders is None else folders
|
|
|
|
for name, value in d.items():
|
|
if isinstance(value, dict):
|
|
zs = recursive_sum(value, folders, False)
|
|
folders.append((name, zs))
|
|
else:
|
|
zs = value
|
|
s += zs
|
|
|
|
if initial:
|
|
return folders
|
|
else:
|
|
return s
|
|
|
|
|
|
def folders_up_to_size(folders: list, size: int):
|
|
return [(k, v) for k, v in folders if v <= size]
|
|
|
|
|
|
def recursive_print(d: dict, indent=0, increment=2):
|
|
for k, v in d.items():
|
|
if isinstance(v, dict):
|
|
print(' '*indent, 'dir', k)
|
|
recursive_print(v, indent+increment)
|
|
else:
|
|
print(' '*indent, k, v)
|
|
|
|
|
|
system = parse_stdin(text)
|
|
# recursive_print(system)
|
|
sums = recursive_sum(system)
|
|
summed_folders = folders_up_to_size(sums, 100000)
|
|
print(summed_folders)
|
|
print(sum([v for _, v in summed_folders]))
|
|
|
|
"""
|
|
now find the smallest folder that can be deleted to free up the space needed to keep the total size under 40MB
|
|
"""
|
|
|
|
|
|
def folders_over_size(folders: list, size: int):
|
|
return [(k, v) for k, v in folders if v > size]
|
|
|
|
|
|
total = sums[-1][1]
|
|
over = total-40000000
|
|
print('filesystem overfull by:', over)
|
|
|
|
summed_folders = folders_over_size(sums, over)
|
|
summed_folders.sort(key=lambda x: x[1])
|
|
print(summed_folders[0])
|