You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 

101 lines
2.5 KiB

import aoclib
inp = aoclib.get_input(8, parser=aoclib.parse_lines_with_func(lambda line: [int(c) for c in line]))
class Forest:
class Directions:
UP = (-1, 0)
DOWN = (1, 0)
LEFT = (0, -1)
RIGHT = (0, 1)
ALL = (UP, DOWN, LEFT, RIGHT)
def __init__(self, grid): # assumes rect grid
self.grid = grid
self.max = (len(grid[0]), len(grid))
def is_tree_visible(self, x: int, y: int):
return any([self._tree_visible_from(direction, x, y) for direction in self.Directions.ALL])
def _tree_visible_from(self, direction, x, y):
main = self._get_tree(x, y)
others = self._get_all_trees_in_dir(direction, x, y)
return all([o < main for o in others])
def _get_all_trees_in_dir(self, direction, x, y):
trees = []
dx, dy = direction
while True:
x += dx
y += dy
tree = self._get_tree(x, y)
if tree is not None:
trees.append(tree)
else:
return trees
def scenic_score_for_pos(self, x, y):
prod = 1
for d in self.Directions.ALL:
prod *= self._get_scenic_score_in_dir(d, x, y)
if prod == 0:
break
return prod
def _get_scenic_score_in_dir(self, direction, x, y):
house = self._get_tree(x, y)
count = 0
for tree in self._get_trees_in_dir_iter(direction, x, y):
count += 1
if tree >= house:
break
return count
def _get_trees_in_dir_iter(self, direction, x, y):
dx, dy = direction
while True:
x += dx
y += dy
tree = self._get_tree(x, y)
if tree is not None:
yield tree
else:
break
def _get_tree(self, x, y):
if x < 0 or y < 0:
return None
try:
return self.grid[y][x]
except IndexError:
return None
def part1():
f = Forest(inp)
xmax, ymax = f.max
count = 0
for x in range(xmax):
for y in range(ymax):
if f.is_tree_visible(x, y):
count += 1
return count
def part2():
f = Forest(inp)
xmax, ymax = f.max
highest = 0
for x in range(xmax):
for y in range(ymax):
if (current := f.scenic_score_for_pos(x, y)) > highest:
highest = current
return highest
aoclib.main(part1, part2)