98 lines
3.0 KiB
Python
98 lines
3.0 KiB
Python
![]() |
# SPDX-License-Identifier: MIT
|
||
|
# Copyright (c) 2021 Akumatic
|
||
|
#
|
||
|
# https://adventofcode.com/2021/day/11
|
||
|
|
||
|
class Octopus:
|
||
|
def __init__(self, idx, energy):
|
||
|
self.idx = idx
|
||
|
self._get_neighbor_idx()
|
||
|
self.energy = energy
|
||
|
self.flashed = False
|
||
|
self.neighbors = list()
|
||
|
|
||
|
def _get_neighbor_idx(self):
|
||
|
if self.idx == 0: # top left corner
|
||
|
self.neighbor_idx = [self.idx + i for i in (1, 10, 11)]
|
||
|
elif self.idx == 9: # top right corner
|
||
|
self.neighbor_idx = [self.idx + i for i in (-1, 9, 10)]
|
||
|
elif self.idx == 90: # bottom left corner
|
||
|
self.neighbor_idx = [self.idx + i for i in (-10, -9, 1)]
|
||
|
elif self.idx == 99: # bottom right corner
|
||
|
self.neighbor_idx = [self.idx + i for i in (-11, -10, -1)]
|
||
|
elif self.idx < 10: # top edge
|
||
|
self.neighbor_idx = [self.idx + i for i in (-1, 1, 9, 10, 11)]
|
||
|
elif self.idx > 90: # bottom edge
|
||
|
self.neighbor_idx = [self.idx + i for i in (-11, -10, -9, -1, 1)]
|
||
|
elif self.idx % 10 == 0: # left edge
|
||
|
self.neighbor_idx = [self.idx + i for i in (-10, -9, 1, 10, 11)]
|
||
|
elif self.idx % 10 == 9: # right edge
|
||
|
self.neighbor_idx = [self.idx + i for i in (-11, -10, -1, 9, 10)]
|
||
|
else:
|
||
|
self.neighbor_idx = [self.idx + i for i in (-11, -10, -9, -1, 1, 9, 10, 11)]
|
||
|
|
||
|
def add_neighbor(self, neighbor):
|
||
|
self.neighbors.append(neighbor)
|
||
|
|
||
|
def flash(self):
|
||
|
self.flashed = True
|
||
|
for neighbor in self.neighbors:
|
||
|
neighbor.energy += 1
|
||
|
|
||
|
def read_file(filename: str = "input.txt") -> list:
|
||
|
with open(f"{__file__.rstrip('code.py')}{filename}", "r") as f:
|
||
|
lines = [line for line in f.read().strip().split("\n")]
|
||
|
values = list()
|
||
|
for line in lines:
|
||
|
values += [int(x) for x in list(line)]
|
||
|
return values
|
||
|
|
||
|
def create_octopuses(vals: int) -> list:
|
||
|
octopuses = [Octopus(i, vals[i]) for i in range(len(vals))]
|
||
|
for octopus in octopuses:
|
||
|
for i in octopus.neighbor_idx:
|
||
|
octopus.add_neighbor(octopuses[i])
|
||
|
return octopuses
|
||
|
|
||
|
def step(octopuses: list) -> int:
|
||
|
flashes = 0
|
||
|
for octopus in octopuses:
|
||
|
octopus.energy += 1
|
||
|
|
||
|
repeat = True
|
||
|
while repeat:
|
||
|
repeat = False
|
||
|
for octopus in octopuses:
|
||
|
if octopus.energy > 9 and octopus.flashed == False:
|
||
|
octopus.flash()
|
||
|
flashes += 1
|
||
|
repeat = True
|
||
|
|
||
|
for octopus in octopuses:
|
||
|
if octopus.flashed:
|
||
|
octopus.flashed = False
|
||
|
octopus.energy = 0
|
||
|
|
||
|
return flashes
|
||
|
|
||
|
def part1(vals: list) -> int:
|
||
|
flashes = 0
|
||
|
octopuses = create_octopuses(vals)
|
||
|
for _ in range(100):
|
||
|
flashes += step(octopuses)
|
||
|
return flashes
|
||
|
|
||
|
def part2(vals: list) -> int:
|
||
|
octopuses = create_octopuses(vals)
|
||
|
count = 0
|
||
|
flashes = 0
|
||
|
while flashes != 100:
|
||
|
flashes = step(octopuses)
|
||
|
count += 1
|
||
|
return count
|
||
|
|
||
|
if __name__ == "__main__":
|
||
|
vals = read_file()
|
||
|
print(f"Part 1: {part1(vals)}")
|
||
|
print(f"Part 2: {part2(vals)}")
|