mirror of
https://github.com/RussellChamp/advent-of-code-2022.git
synced 2026-10-27 21:52:30 +00:00
day07 solution
This commit is contained in:
1 parent
90aad38e16
commit
6107f01523
4 files changed
+159
-1
No files matched your search
@@ -0,0 +1,75 @@
|
||||
class PathNode:
|
||||
def __init__(self, name, size = 0):
|
||||
self.name = name
|
||||
self.size = size
|
||||
self.parent = None
|
||||
self.children = {}
|
||||
|
||||
def has_parent(self):
|
||||
# print('%s has a parent? %s' % (self.name, self.parent is not None))
|
||||
return self.parent is not None
|
||||
|
||||
def set_parent(self, parent):
|
||||
self.parent = parent
|
||||
|
||||
def has_child(self, name):
|
||||
# print('%s has child %s? %s' % (self.name, name, self.children.has_key(name)))
|
||||
return self.children.has_key(name)
|
||||
|
||||
def add_child(self, name, size = 0):
|
||||
# print('+ adding %s to %s' % (name, self.name))
|
||||
self.children[name] = PathNode(name, size)
|
||||
self.children[name].set_parent(self)
|
||||
self.size += size
|
||||
|
||||
ptr = self
|
||||
while ptr.has_parent():
|
||||
ptr = ptr.parent
|
||||
ptr.size += size
|
||||
|
||||
def is_directory(self):
|
||||
return len(self.children) > 0
|
||||
|
||||
def print_self(self, indentation = 0):
|
||||
size = '(%d)' % (self.size) + (' [%d items]' % (len(self.children)) if self.is_directory() else '')
|
||||
print('%s%s %s' % (' ' * indentation, self.name, size))
|
||||
for key in self.children:
|
||||
self.children[key].print_self(indentation+1)
|
||||
|
||||
def go_up_one_level(self):
|
||||
if self.has_parent():
|
||||
# print('-> moved up one level from %s to %s' % (self.name, self.parent.name))
|
||||
return self.parent
|
||||
return self
|
||||
|
||||
def go_to_root(self):
|
||||
if self.has_parent():
|
||||
# print('-> going to root from %s' % (self.name))
|
||||
return self.parent.go_to_root()
|
||||
return self
|
||||
|
||||
def go_to_child(self, name):
|
||||
if self.has_child(name):
|
||||
# print('-> going to %s from %s' % (name, self.name))
|
||||
return self.children[name]
|
||||
return self
|
||||
|
||||
def get_directories_le(self, size):
|
||||
dirs = []
|
||||
for key in filter(lambda c: self.children[c].is_directory(), self.children):
|
||||
if self.children[key].size <= size:
|
||||
dirs.append([self.children[key].name, self.children[key].size])
|
||||
dirs += self.children[key].get_directories_le(size)
|
||||
return dirs
|
||||
|
||||
def iterate_all_directories(self):
|
||||
dirs = [[self.name, self.size]]
|
||||
for key in self.children:
|
||||
dirs += self.children[key].iterate_all_directories()
|
||||
return dirs
|
||||
|
||||
def find_smallest_at_least(self, required_size):
|
||||
all_dirs = self.iterate_all_directories()
|
||||
adequate_size_dirst = filter(lambda item: item[1] >= required_size, all_dirs)
|
||||
smallest_dir = min(adequate_size_dirst, key=lambda item: item[1])
|
||||
return smallest_dir
|
||||
@@ -0,0 +1,68 @@
|
||||
# Day 07: No Space Left On Device
|
||||
|
||||
import os
|
||||
from PathNode import PathNode
|
||||
|
||||
def get_path():
|
||||
return os.path.join(os.path.dirname(__file__), 'data.txt')
|
||||
|
||||
def get_dir_tree():
|
||||
ptr = PathNode('/')
|
||||
|
||||
with open(get_path()) as fp:
|
||||
for cmd in fp:
|
||||
cmd = cmd.strip()
|
||||
# print(cmd)
|
||||
if cmd[0] == '$':
|
||||
# commands
|
||||
if cmd[2:4] == 'ls':
|
||||
pass # basically a noop
|
||||
elif cmd[2:4] == 'cd':
|
||||
if cmd[5:] == '/':
|
||||
ptr = ptr.go_to_root()
|
||||
elif cmd[5:] == '..':
|
||||
ptr = ptr.go_up_one_level()
|
||||
else:
|
||||
ptr = ptr.go_to_child(cmd[5:])
|
||||
pass
|
||||
elif cmd[:3] == 'dir':
|
||||
# list a directory
|
||||
ptr.add_child(cmd[4:])
|
||||
else:
|
||||
# listing a file
|
||||
[size, name] = cmd.split()
|
||||
ptr.add_child(name, int(size))
|
||||
|
||||
return ptr.go_to_root()
|
||||
|
||||
|
||||
def solve_part1():
|
||||
root = get_dir_tree()
|
||||
# ptr.print_self()
|
||||
dirs = root.get_directories_le(100000)
|
||||
total_size = sum(map(lambda item: item[1], dirs))
|
||||
|
||||
print('Day 07: Part 1')
|
||||
print('GOAL: Find all of the directories with a total size of at most 100000.')
|
||||
print('ANSWER: What is the sum of the total sizes of those directories?')
|
||||
print('Total size: %d' % (total_size))
|
||||
|
||||
def solve_part2():
|
||||
total_size = 70000000
|
||||
required_space = 30000000
|
||||
|
||||
root = get_dir_tree()
|
||||
delete_size = required_space - (total_size - root.size)
|
||||
# print('Current usage is %d / %d [additional %d needed to get to %d / %d]' % \
|
||||
# (root.size, total_size, delete_size, total_size - required_space, total_size))
|
||||
smallest = root.find_smallest_at_least(delete_size)
|
||||
|
||||
print('Day 07: Part 2')
|
||||
print('GOAL: Find the smallest directory that, if deleted, would free up enough space on the filesystem to run the update.')
|
||||
print('ANSWER: What is the total size of that directory?')
|
||||
print('Need to free up %d' % delete_size)
|
||||
print('Smallest directory: %s - %d' % (smallest[0], smallest[1]))
|
||||
|
||||
if __name__ == '__main__':
|
||||
solve_part1()
|
||||
solve_part2()
|
||||
@@ -0,0 +1,12 @@
|
||||
import unittest
|
||||
|
||||
class Day07TestMethods(unittest.TestCase):
|
||||
def setUp(self):
|
||||
pass
|
||||
|
||||
# Does a thing
|
||||
def test_true(self):
|
||||
self.assertEqual(True, False)
|
||||
|
||||
if __name__ == '__main__':
|
||||
unittest.main()
|
||||
+4
-1
@@ -12,12 +12,15 @@ def solve_part1():
|
||||
for line in fp:
|
||||
print(line)
|
||||
|
||||
print('Day #DAY#: Part 1')
|
||||
print('GOAL: #GOAL1#')
|
||||
print('ANSWER: #ANSWER1#')
|
||||
print('Total: %d' % (total))
|
||||
|
||||
def solve_part2():
|
||||
total = 0
|
||||
|
||||
|
||||
print('Day #DAY#: Part 2')
|
||||
print('GOAL: #GOAL2#')
|
||||
print('ANSWER: #ANSWER2#')
|
||||
print('Total: %d' % (total))
|
||||
|
||||
Reference in new issue
Block a user