mirror of
https://github.com/cupcakearmy/advent-of-code.git
synced 2024-12-21 23:56:30 +00:00
07
This commit is contained in:
parent
bf613c4583
commit
720c9924da
11
2022/07/README.md
Normal file
11
2022/07/README.md
Normal file
@ -0,0 +1,11 @@
|
|||||||
|
# 07
|
||||||
|
|
||||||
|
Loved this one too!! Writing a littler shell "emulator" was def. fun! Also caching directory sizes for performance :)
|
||||||
|
|
||||||
|
<details>
|
||||||
|
<summary>Solutions</summary>
|
||||||
|
<ol>
|
||||||
|
<li>1306611</li>
|
||||||
|
<li>13210366</li>
|
||||||
|
</ol>
|
||||||
|
</details>
|
115
2022/07/python/main.py
Normal file
115
2022/07/python/main.py
Normal file
@ -0,0 +1,115 @@
|
|||||||
|
#!/usr/bin/env python
|
||||||
|
|
||||||
|
from dataclasses import dataclass
|
||||||
|
from os.path import dirname, join
|
||||||
|
from typing import Callable, ClassVar, Literal, Union
|
||||||
|
|
||||||
|
# Day 07
|
||||||
|
|
||||||
|
# Common
|
||||||
|
|
||||||
|
|
||||||
|
def read_input(filename):
|
||||||
|
data = join(dirname(__file__), '..', filename)
|
||||||
|
with open(data) as f:
|
||||||
|
return f.read().strip()
|
||||||
|
|
||||||
|
|
||||||
|
test = read_input('test.txt')
|
||||||
|
data = read_input('input.txt')
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class File:
|
||||||
|
size: int
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Directory:
|
||||||
|
name: str
|
||||||
|
contents: dict[str, Union['Directory', File]]
|
||||||
|
parent: Union[None, 'Directory'] = None
|
||||||
|
_size: int | None = None
|
||||||
|
|
||||||
|
def size(self) -> int:
|
||||||
|
if self._size is None:
|
||||||
|
self._size = sum([
|
||||||
|
entry.size if isinstance(entry, File) else entry.size()
|
||||||
|
for entry in self.contents.values()
|
||||||
|
])
|
||||||
|
return self._size
|
||||||
|
|
||||||
|
def walk(self, fn: Callable[[Union[File, 'Directory']], None]):
|
||||||
|
for entry in self.contents.values():
|
||||||
|
fn(entry)
|
||||||
|
if isinstance(entry, Directory):
|
||||||
|
entry.walk(fn)
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Command:
|
||||||
|
command: str
|
||||||
|
output: list[str]
|
||||||
|
|
||||||
|
|
||||||
|
@dataclass
|
||||||
|
class Shell:
|
||||||
|
commands: list[Command]
|
||||||
|
root: Directory
|
||||||
|
cwd: Directory
|
||||||
|
|
||||||
|
def execute(self):
|
||||||
|
for command in self.commands:
|
||||||
|
cmd, *args = command.command.split()
|
||||||
|
match cmd:
|
||||||
|
case 'ls':
|
||||||
|
for entry in command.output:
|
||||||
|
size, name = entry.split()
|
||||||
|
self.cwd.contents[name] = Directory(name, {}, self.cwd) if size == 'dir' else File(int(size))
|
||||||
|
case 'cd':
|
||||||
|
match args[0]:
|
||||||
|
case '/':
|
||||||
|
self.cwd = self.root
|
||||||
|
case '..':
|
||||||
|
self.cwd = self.cwd.parent
|
||||||
|
case _:
|
||||||
|
self.cwd = self.cwd.contents[args[0]]
|
||||||
|
|
||||||
|
def get_all_sizes(self) -> list[int]:
|
||||||
|
sizes: list[int] = []
|
||||||
|
|
||||||
|
def fn(entry: Directory | File):
|
||||||
|
if isinstance(entry, Directory):
|
||||||
|
sizes.append(entry.size())
|
||||||
|
self.root.walk(fn)
|
||||||
|
return sizes
|
||||||
|
|
||||||
|
def flag_1(self):
|
||||||
|
directories = self.get_all_sizes()
|
||||||
|
return sum([size for size in directories if size <= 100_000])
|
||||||
|
|
||||||
|
def flag_2(self, total=70_000_000, needed=30_000_000):
|
||||||
|
to_remove = needed - total + self.root.size()
|
||||||
|
big_enough = sorted([
|
||||||
|
size
|
||||||
|
for size in self.get_all_sizes()
|
||||||
|
if size > to_remove
|
||||||
|
])
|
||||||
|
return big_enough[0]
|
||||||
|
|
||||||
|
@staticmethod
|
||||||
|
def parse(data: str):
|
||||||
|
commands = [command.strip().split('\n') for command in data.split('$ ')[1:]]
|
||||||
|
root = Directory('/', {})
|
||||||
|
return Shell([Command(command[0], command[1:]) for command in commands], root, root)
|
||||||
|
|
||||||
|
|
||||||
|
shell = Shell.parse(test)
|
||||||
|
shell.execute()
|
||||||
|
print(shell.flag_1())
|
||||||
|
print(shell.flag_2())
|
||||||
|
|
||||||
|
shell = Shell.parse(data)
|
||||||
|
shell.execute()
|
||||||
|
print(shell.flag_1())
|
||||||
|
print(shell.flag_2())
|
Loading…
Reference in New Issue
Block a user