From 2fbe2677b9aec5b5b978919c4135debfc0e60dcf Mon Sep 17 00:00:00 2001 From: Bruno BELANYI Date: Mon, 9 Dec 2024 08:48:17 -0500 Subject: [PATCH] 2024: d09: ex1: add solution --- 2024/d09/ex1/ex1.py | 62 +++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100755 2024/d09/ex1/ex1.py diff --git a/2024/d09/ex1/ex1.py b/2024/d09/ex1/ex1.py new file mode 100755 index 0000000..93a1aaf --- /dev/null +++ b/2024/d09/ex1/ex1.py @@ -0,0 +1,62 @@ +#!/usr/bin/env python + +import sys + + +def solve(input: str) -> int: + def parse(input: str) -> tuple[list[int], list[int]]: + files: list[int] = [] + free: list[int] = [] + + for i, c in enumerate(input): + if c == "\n": + continue + (files if i % 2 == 0 else free).append(int(c)) + + # Make `to_disk` slightly simpler + if len(files) > len(free): + free.append(0) + + return files, free + + def to_disk(files: list[int], free: list[int]) -> list[int | None]: + assert len(files) == len(free) # Sanity check + + disk: list[int | None] = [] + + for i in range(len(files)): + disk.extend([i for _ in range(files[i])]) + disk.extend([None for _ in range(free[i])]) + + return disk + + def compact(disk: list[int | None]) -> list[int]: + last = len(disk) - 1 + for i in range(len(disk)): + # Are we finished compacting? + if i >= last: + break + # Is this a free space? + if disk[i] is not None: + continue + assert disk[last] is not None # Sanity check + disk[i], disk[last] = disk[last], disk[i] + # Find next block to compact + while disk[last] is None: + last -= 1 + # At this point, `None` are at the end + # Naive list comprehension to appease the type checker + return [n for n in disk if n is not None] + + files, free = parse(input) + disk = to_disk(files, free) + return sum(i * n for i, n in enumerate(compact(disk))) + + +def main() -> None: + input = sys.stdin.read() + print(solve(input)) + + +if __name__ == "__main__": + main()