|
|
@@ -0,0 +1,123 @@
|
|
|
+import os, argparse, re
|
|
|
+
|
|
|
+
|
|
|
+def solve_task(lines):
|
|
|
+ e = Explorer()
|
|
|
+ for line in lines:
|
|
|
+ e.parse_output(line)
|
|
|
+
|
|
|
+ folders = e.get_all_folders()
|
|
|
+ free_space = 70000000 - e.get_size()
|
|
|
+ missing_space = 30000000 - free_space
|
|
|
+ large_enough_folder_sizes = [f.size for f in folders if f.size >= missing_space]
|
|
|
+ large_enough_folder_sizes.sort()
|
|
|
+ print(f"Free space: {free_space}")
|
|
|
+ print(f"Missing space: {missing_space}")
|
|
|
+ print(f"Smallest folder to delete: {large_enough_folder_sizes[0]}")
|
|
|
+
|
|
|
+class Explorer:
|
|
|
+ def __init__(self):
|
|
|
+ self.root_node = FolderNode()
|
|
|
+ self.current_dir = self.root_node
|
|
|
+
|
|
|
+ def parse_output(self, line):
|
|
|
+ tokens = line.split()
|
|
|
+ if tokens[0] == "$":
|
|
|
+ self.parse_cmd(tokens[1:])
|
|
|
+ elif tokens[0] == "dir":
|
|
|
+ self.current_dir.add_folder(tokens[1])
|
|
|
+ else:
|
|
|
+ self.current_dir.add_file(tokens[1], tokens[0])
|
|
|
+
|
|
|
+ def get_size(self):
|
|
|
+ return self.root_node.size
|
|
|
+
|
|
|
+ def parse_cmd(self, tokens):
|
|
|
+ cmd = tokens[0]
|
|
|
+ if cmd == "cd":
|
|
|
+ path = tokens[1]
|
|
|
+ if path == "..":
|
|
|
+ self.current_dir = self.current_dir.parent
|
|
|
+ elif path == "/":
|
|
|
+ self.current_dir = self.root_node
|
|
|
+ else:
|
|
|
+ if path in self.current_dir.children:
|
|
|
+ # Existing name
|
|
|
+ self.current_dir = self.current_dir.children[path]
|
|
|
+ else:
|
|
|
+ self.current_dir.add_folder(path)
|
|
|
+ self.current_dir = self.current_dir.children[path]
|
|
|
+
|
|
|
+ def get_all_folders(self):
|
|
|
+ all_folders_found = [self.root_node]
|
|
|
+ folders_to_traverse = [self.root_node]
|
|
|
+ while len(folders_to_traverse) > 0:
|
|
|
+ current_folder = folders_to_traverse.pop()
|
|
|
+ folders_found = [folder for folder in current_folder.children.values() if isinstance(folder, FolderNode)]
|
|
|
+ all_folders_found.extend(folders_found)
|
|
|
+ folders_to_traverse.extend(folders_found)
|
|
|
+ return all_folders_found
|
|
|
+
|
|
|
+class Node:
|
|
|
+ def __init__(self, parent):
|
|
|
+ self.size = 0
|
|
|
+ if parent:
|
|
|
+ self.parent = parent
|
|
|
+ else:
|
|
|
+ self.parent = self
|
|
|
+
|
|
|
+class FileNode(Node):
|
|
|
+ def __init__(self, parent, name, size):
|
|
|
+ super().__init__(parent)
|
|
|
+ self.parent = parent
|
|
|
+ self.name = name
|
|
|
+ self.size = int(size)
|
|
|
+
|
|
|
+class FolderNode(Node):
|
|
|
+ def __init__(self, parent = None, name = "/"):
|
|
|
+ super().__init__(parent)
|
|
|
+ self.children = {}
|
|
|
+ self.name = name
|
|
|
+
|
|
|
+ def add(self, node):
|
|
|
+ self.children[node.name] = node
|
|
|
+ self.adjust_size(node.size)
|
|
|
+
|
|
|
+ def add_file(self, name, size):
|
|
|
+ file = FileNode(self, name, size)
|
|
|
+ self.add(file)
|
|
|
+
|
|
|
+ def add_folder(self, name):
|
|
|
+ folder = FolderNode(self, name)
|
|
|
+ self.add(folder)
|
|
|
+
|
|
|
+ def adjust_size(self, increment):
|
|
|
+ self.size += increment
|
|
|
+ if not self.is_root():
|
|
|
+ self.parent.adjust_size(increment)
|
|
|
+
|
|
|
+ def is_root(self):
|
|
|
+ return self.parent == self
|
|
|
+
|
|
|
+
|
|
|
+def read_lines(filename):
|
|
|
+ lines = []
|
|
|
+ with open(filename) as infile:
|
|
|
+ for raw_line in infile:
|
|
|
+ line = raw_line.rstrip()
|
|
|
+ lines.append(line)
|
|
|
+ return lines
|
|
|
+
|
|
|
+def parse_arguments():
|
|
|
+ parser = argparse.ArgumentParser(description="Script that solves the case",epilog="Have a nice day!")
|
|
|
+ parser.add_argument('filename', nargs='?', default="example.txt", help='Input file')
|
|
|
+ args = parser.parse_args()
|
|
|
+ return args
|
|
|
+
|
|
|
+def main():
|
|
|
+ args = parse_arguments()
|
|
|
+ lines = read_lines(args.filename)
|
|
|
+ solve_task(lines)
|
|
|
+
|
|
|
+if __name__ == "__main__":
|
|
|
+ main()
|