2024-12-11 22:30:06 +00:00
|
|
|
#!/usr/bin/env python
|
|
|
|
# -*- encoding: utf-8; py-indent-offset: 4 -*-
|
|
|
|
|
|
|
|
# Author: Sebastian Mark
|
|
|
|
# CC-BY-SA (https://creativecommons.org/licenses/by-sa/4.0/deed.de)
|
|
|
|
|
|
|
|
# pylint: disable=missing-module-docstring,missing-function-docstring,consider-using-f-string
|
|
|
|
|
|
|
|
|
|
|
|
def readinput():
|
|
|
|
with open("input", "r", encoding="utf-8") as file:
|
|
|
|
lines = [list(line.strip()) for line in file]
|
|
|
|
return lines
|
|
|
|
|
|
|
|
|
|
|
|
def is_visible(trees: list, tree_y: int, tree_x: int) -> bool:
|
|
|
|
height = len(trees)
|
|
|
|
width = len(trees[0])
|
|
|
|
|
|
|
|
# edges are always visible
|
|
|
|
if not 0 < tree_y < height - 1 or not 0 < tree_x < width - 1:
|
|
|
|
return True
|
|
|
|
|
|
|
|
# check up, right, down, right
|
|
|
|
directions = [(-1, 0), (0, 1), (1, 0), (0, -1)]
|
|
|
|
for dy, dx in directions:
|
|
|
|
nxty = tree_y + dy
|
|
|
|
nxtx = tree_x + dx
|
|
|
|
# continue to check in the direction til border
|
|
|
|
is_biggest = True
|
|
|
|
while 0 <= nxty < height and 0 <= nxtx < width:
|
|
|
|
# check size, stop searching if bigger tree found
|
|
|
|
if trees[tree_y][tree_x] <= trees[nxty][nxtx]:
|
|
|
|
is_biggest = False
|
|
|
|
break
|
|
|
|
|
|
|
|
nxtx += dx
|
|
|
|
nxty += dy
|
|
|
|
|
|
|
|
if is_biggest:
|
|
|
|
return True
|
|
|
|
|
|
|
|
return False
|
|
|
|
|
|
|
|
|
2024-12-12 19:22:43 +00:00
|
|
|
def scenic_score(trees: list, tree_y: int, tree_x: int) -> int:
|
|
|
|
height = len(trees)
|
|
|
|
width = len(trees[0])
|
|
|
|
|
|
|
|
score = 1
|
|
|
|
|
|
|
|
# check up, right, down, right
|
|
|
|
directions = [(-1, 0), (0, 1), (1, 0), (0, -1)]
|
|
|
|
for dy, dx in directions:
|
|
|
|
nxty = tree_y + dy
|
|
|
|
nxtx = tree_x + dx
|
|
|
|
visual_range = 1
|
|
|
|
|
|
|
|
# continue to check in the direction til border
|
|
|
|
while 0 < nxty < height - 1 and 0 < nxtx < width - 1:
|
|
|
|
# check size, stop if bigger tree found
|
|
|
|
if trees[tree_y][tree_x] <= trees[nxty][nxtx]:
|
|
|
|
break
|
|
|
|
|
|
|
|
visual_range += 1
|
|
|
|
nxtx += dx
|
|
|
|
nxty += dy
|
|
|
|
|
|
|
|
score *= visual_range
|
|
|
|
|
|
|
|
return score
|
|
|
|
|
|
|
|
|
2024-12-11 22:30:06 +00:00
|
|
|
def main():
|
|
|
|
trees = readinput()
|
|
|
|
|
2024-12-12 19:22:43 +00:00
|
|
|
# part 1
|
2024-12-11 22:30:06 +00:00
|
|
|
visible = 0
|
|
|
|
for y in range(len(trees)):
|
|
|
|
for x in range(len(trees[0])):
|
|
|
|
if is_visible(trees, y, x):
|
|
|
|
visible += 1
|
|
|
|
print("Visible trees: %d" % visible)
|
|
|
|
|
2024-12-12 19:22:43 +00:00
|
|
|
# part 1
|
|
|
|
scenic_scores = []
|
|
|
|
for y in range(len(trees)):
|
|
|
|
for x in range(len(trees[0])):
|
|
|
|
scenic_scores.append(scenic_score(trees, y, x))
|
|
|
|
print("Highest scenic score: %d" % max(scenic_scores))
|
|
|
|
|
2024-12-11 22:30:06 +00:00
|
|
|
|
|
|
|
if __name__ == "__main__":
|
|
|
|
main()
|