diff --git a/2024/day9/main.py b/2024/day9/main.py new file mode 100644 index 0000000..c87b32b --- /dev/null +++ b/2024/day9/main.py @@ -0,0 +1,101 @@ +with open('test.text', 'r') as file: + data: str = file.read().strip() + +# If block has no ID then it is free +class FreeBlock: + size: int + + def __init__(self, s: int): + self.size = s + + def __str__(self) -> str: + return '.' * self.size + +class FileBlock: + size: int + id: int + + def __init__(self, size: int, id: int): + self.size = size + self.id = id + + def __str__(self) -> str: + return str(self.id) * self.size + +class DiskMap: + blocks: list[FreeBlock | FileBlock] + + def __init__(self, s: str): + self.blocks = [] + self.parse(s) + + def parse(self, s: str) -> None: + is_file = True + id = 0 + for char in s: + b = FreeBlock(int(char)) + if is_file: + b = FileBlock(int(char), id) + id += 1 + is_file = not is_file + + self.blocks.append(b) + + # Returns index of first free block or None + def findFreeBlock(self) -> int | None: + for i, block in enumerate(self.blocks): + if type(block) == FreeBlock: + return i + + return None + + # Returns index of last file block + def findLastFile(self) -> int | None: + for i, block in reversed(list(enumerate(self.blocks))): + if type(block) == FileBlock: + return i + + return None + + def compact(self) -> None: + while True: + free_index = self.findFreeBlock() + file_index = self.findLastFile() + + if free_index > file_index: + break + + free_size: int = self.blocks[free_index].size + file_size: int = self.blocks[file_index].size + file_id: int = self.blocks[file_index].id + + remaining_file_size = file_size - free_size + remaining_free_size = 0 + if remaining_file_size < 0: + remaining_free_size = abs(remaining_file_size) + remaining_file_size = 0 + + if remaining_free_size != 0: + self.blocks[free_index] = FileBlock(free_size - remaining_free_size, file_id) + self.blocks[file_id] = FreeBlock(free_size) + else: + self.blocks[free_index] = FileBlock(free_size, file_id) + self.blocks[file_index] = FreeBlock(free_size) + + if remaining_file_size: + self.blocks.insert(file_index, FileBlock(remaining_file_size, file_id)) + + print(free_index) + self.print() + + def print(self) -> None: + for block in self.blocks: + print(block, end='') + print() + +# Parse Data +diskmap = DiskMap(data) + +diskmap.print() +diskmap.compact() +diskmap.print() diff --git a/2024/day9/test.text b/2024/day9/test.text new file mode 100644 index 0000000..bd41cba --- /dev/null +++ b/2024/day9/test.text @@ -0,0 +1 @@ +12345 \ No newline at end of file