day08 finished
This commit is contained in:
parent
82c7745b47
commit
9674fc3e2b
5 changed files with 251 additions and 0 deletions
102
advent/days/day08/solution.py
Normal file
102
advent/days/day08/solution.py
Normal file
|
|
@ -0,0 +1,102 @@
|
|||
from __future__ import annotations
|
||||
from dataclasses import dataclass
|
||||
|
||||
from typing import Iterator
|
||||
|
||||
day_num = 8
|
||||
|
||||
|
||||
def part1(lines: Iterator[str]) -> int:
|
||||
return Trees.parse(lines).count_visible()
|
||||
|
||||
|
||||
def part2(lines: Iterator[str]) -> int:
|
||||
return Trees.parse(lines).max_scenic_score()
|
||||
|
||||
|
||||
@dataclass(slots=True)
|
||||
class Trees:
|
||||
trees: list[list[int]]
|
||||
width: int
|
||||
height: int
|
||||
|
||||
@staticmethod
|
||||
def parse(lines: Iterator[str]) -> Trees:
|
||||
trees = [[int(tree) for tree in line] for line in lines]
|
||||
return Trees(trees, len(trees[0]), len(trees))
|
||||
|
||||
def count_visible(self) -> int:
|
||||
visible = [[True] * self.width]
|
||||
for _ in range(self.height - 2):
|
||||
visible += [[True] + [False] * (self.width - 2) + [True]]
|
||||
visible += [[True] * self.width]
|
||||
|
||||
# From Up
|
||||
mx = self.trees[0].copy()
|
||||
for y in range(1, self.height - 1):
|
||||
for x in range(1, self.width - 1):
|
||||
if self.trees[y][x] > mx[x]:
|
||||
mx[x] = self.trees[y][x]
|
||||
visible[y][x] = True
|
||||
|
||||
# From Down
|
||||
mx = self.trees[-1].copy()
|
||||
for y in range(self.height - 2, 0, -1):
|
||||
for x in range(1, self.width - 1):
|
||||
if self.trees[y][x] > mx[x]:
|
||||
mx[x] = self.trees[y][x]
|
||||
visible[y][x] = True
|
||||
|
||||
# From Left
|
||||
mx = [self.trees[y][0] for y in range(self.height)]
|
||||
for x in range(1, self.width - 1):
|
||||
for y in range(1, self.height - 1):
|
||||
if self.trees[y][x] > mx[y]:
|
||||
mx[y] = self.trees[y][x]
|
||||
visible[y][x] = True
|
||||
|
||||
# From Right
|
||||
mx = [self.trees[y][-1] for y in range(self.height)]
|
||||
for x in range(self.width - 2, 0, -1):
|
||||
for y in range(1, self.height - 1):
|
||||
if self.trees[y][x] > mx[y]:
|
||||
mx[y] = self.trees[y][x]
|
||||
visible[y][x] = True
|
||||
|
||||
return sum(1 for y in range(self.height) for x in range(self.width) if visible[y][x])
|
||||
|
||||
def max_scenic_score(self) -> int:
|
||||
max_score = 0
|
||||
for y in range(1, self.height - 1):
|
||||
for x in range(1, self.width - 1):
|
||||
score = self.single_scenic_score(x, y)
|
||||
if score > max_score:
|
||||
max_score = score
|
||||
return max_score
|
||||
|
||||
def single_scenic_score(self, x: int, y: int) -> int:
|
||||
up = 0
|
||||
for dy in range(y - 1, -1, -1):
|
||||
up += 1
|
||||
if self.trees[dy][x] >= self.trees[y][x]:
|
||||
break
|
||||
|
||||
down = 0
|
||||
for dy in range(y + 1, self.height):
|
||||
down += 1
|
||||
if self.trees[dy][x] >= self.trees[y][x]:
|
||||
break
|
||||
|
||||
left = 0
|
||||
for dx in range(x - 1, -1, -1):
|
||||
left += 1
|
||||
if self.trees[y][dx] >= self.trees[y][x]:
|
||||
break
|
||||
|
||||
right = 0
|
||||
for dx in range(x + 1, self.width):
|
||||
right += 1
|
||||
if self.trees[y][dx] >= self.trees[y][x]:
|
||||
break
|
||||
|
||||
return up * down * left * right
|
||||
Loading…
Add table
Add a link
Reference in a new issue