From cdeb7e21a5843164cbf56431fc96a6ffd987e233 Mon Sep 17 00:00:00 2001 From: Ryan Reed Date: Sun, 12 Dec 2021 17:49:32 -0500 Subject: [PATCH] Adding Day 11 Part 2 --- puzzles/day11.py | 75 +++++++++++++++++++++++++++++++-------------- tests/test_day11.py | 6 ++-- 2 files changed, 54 insertions(+), 27 deletions(-) diff --git a/puzzles/day11.py b/puzzles/day11.py index c673666..10f5424 100644 --- a/puzzles/day11.py +++ b/puzzles/day11.py @@ -12,33 +12,45 @@ from typing import List, Tuple from dataclasses import dataclass +@dataclass +class Octopus: + energy_level: int = 0 + flash_count: int = 0 + location: Tuple[int, int] = (0, 0) + last_flash: int = 0 + class School: octopi = None step = 1 - def __init__(self, data): + def __init__(self, data: List[str]) -> None: self.parse(data) + self.synchronized_steps = [] - def flash(self, octopus): + def flash(self, octopus: Octopus) -> None: octopus.energy_level = 0 octopus.flash_count += 1 octopus.last_flash = self.step self.update_neighbors(octopus.location) - def update(self, octopus): + def update(self, octopus: Octopus) -> None: if octopus.last_flash == self.step: - return False + return None octopus.energy_level += 1 if octopus.energy_level == 10: self.flash(octopus) - def update_neighbors(self, location): + def update_neighbors(self, location: Tuple[int, int]) -> None: min_row = 0 if location[0] == 0 else location[0] - 1 min_col = 0 if location[1] == 0 else location[1] - 1 - max_row = location[0] if location[0] == self.size["rows"] - 1 else location[0] + 1 - max_col = location[1] if location[1] == self.size["cols"] - 1 else location[1] + 1 + max_row = ( + location[0] if location[0] == self.size["rows"] - 1 else location[0] + 1 + ) + max_col = ( + location[1] if location[1] == self.size["cols"] - 1 else location[1] + 1 + ) for row in range(min_row, max_row + 1): for col in range(min_col, max_col + 1): @@ -49,15 +61,39 @@ class School: self.update(self.octopi[row][col]) - def simulate(self, steps=100): - for step in range(1, steps+1): + def simulate(self, steps: int = 100) -> None: + for step in range(1, steps + 1): self.step = step for row in self.octopi: for octopus in row: self.update(octopus) + def is_synchronized(self) -> bool: + """This is inefficient and needs to be reworked""" + for row in self.octopi: + for octopi in row: + if octopi.energy_level > 0: + return False + + return True + @property - def total_flashes(self): + def first_synchronized(self) -> int: + step = 0 + while True: + step += 1 + self.step = step + for row in self.octopi: + for octopus in row: + self.update(octopus) + + if self.is_synchronized(): + break + + return step + + @property + def total_flashes(self) -> int: total = 0 for row in self.octopi: for octopus in row: @@ -65,14 +101,14 @@ class School: return total - def parse(self, data): + def parse(self, data: List[str]) -> None: self.octopi = [] for row_index, row in enumerate(data): self.octopi.append( [ Octopus( energy_level=int(value), - location=(int(row_index), int(column_index)), # row, col + location=(int(row_index), int(column_index)), # row, col ) for column_index, value in enumerate(row) ] @@ -80,25 +116,18 @@ class School: self.size = {"rows": len(self.octopi), "cols": len(self.octopi[0])} -@dataclass -class Octopus: - energy_level: int = 0 - flash_count: int = 0 - location: Tuple[int, int] = (0, 0) - last_flash: int = 0 - - def part1(inputs: List[int]) -> int: s = School(inputs) s.simulate() return s.total_flashes -def part2(inpus: List[int]) -> int: - return False +def part2(inputs: List[int]) -> int: + s = School(inputs) + return s.first_synchronized -def parse(inputs: str) -> List[int]: +def parse(inputs: str) -> List[str]: """Parse the input string""" return [line for line in inputs.split()] diff --git a/tests/test_day11.py b/tests/test_day11.py index 8268544..35dc8d0 100644 --- a/tests/test_day11.py +++ b/tests/test_day11.py @@ -24,15 +24,13 @@ def test_example1(example_data): assert aoc.part1(example_data) == 1656 -@pytest.mark.skip(reason="Not implemented") def test_example2(example_data): - assert aoc.part2(example_data) == ... + assert aoc.part2(example_data) == 195 def test_part1(day11_data): assert aoc.part1(day11_data) == 1608 -@pytest.mark.skip(reason="Not implemented") def test_part2(day11_data): - assert aoc.part2(day11_data) == ... + assert aoc.part2(day11_data) == 214