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
+158
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()
|
||||||
@@ -12,12 +12,15 @@ def solve_part1():
|
|||||||
for line in fp:
|
for line in fp:
|
||||||
print(line)
|
print(line)
|
||||||
|
|
||||||
|
print('Day #DAY#: Part 1')
|
||||||
print('GOAL: #GOAL1#')
|
print('GOAL: #GOAL1#')
|
||||||
print('ANSWER: #ANSWER1#')
|
print('ANSWER: #ANSWER1#')
|
||||||
print('Total: %d' % (total))
|
print('Total: %d' % (total))
|
||||||
|
|
||||||
def solve_part2():
|
def solve_part2():
|
||||||
total = 0
|
total = 0
|
||||||
|
|
||||||
|
print('Day #DAY#: Part 2')
|
||||||
print('GOAL: #GOAL2#')
|
print('GOAL: #GOAL2#')
|
||||||
print('ANSWER: #ANSWER2#')
|
print('ANSWER: #ANSWER2#')
|
||||||
print('Total: %d' % (total))
|
print('Total: %d' % (total))
|
||||||
|
|||||||
Reference in new issue
Block a user