# -*- coding: utf-8 -*- from abc import ABC from typing import Iterator, Any, List from aoc import BaseAssignment class Assignment(BaseAssignment): trees: List[str] def row_at(self, y: int) -> List[int]: return [int(i) for i in self.trees[y]] def col_at(self, x: int) -> List[int]: return [int(i[x]) for i in self.trees] class AssignmentOne(Assignment): example_result = 21 def is_visible(self, trees: List[int], index: int) -> bool: highest_first_half = max(trees[:index]) highest_second_half = max(trees[index + 1 :]) value = trees[index] return highest_first_half < value or highest_second_half < value def tree_visible(self, x: int, y: int) -> bool: col = self.col_at(x) row = self.row_at(y) return self.is_visible(col, y) or self.is_visible(row, x) def run(self, input: Iterator) -> Any: self.trees = list(input) width = len(self.trees[0]) height = len(self.trees) visible_inside = 0 self.is_visible(self.col_at(1), 2) for x in range(1, width - 1): for y in range(1, height - 1): if self.tree_visible(x, y): visible_inside += 1 return visible_inside + ((width - 1) * 2) + ((height - 1) * 2) class AssignmentTwo(Assignment): example_result = 8 @staticmethod def calculate_1d_scenic_score(trees: List[int], index: int) -> int: first_half = list(reversed(trees[:index])) second_half = trees[index + 1 :] value = trees[index] score_first_half = 0 for score_first_half, tree in enumerate(first_half): if tree >= value: break score_second_half = 0 for score_second_half, tree in enumerate(second_half): if tree >= value: break return (score_first_half + 1) * (score_second_half + 1) def calculate_scenic_score(self, x: int, y: int) -> int: col = self.col_at(x) row = self.row_at(y) return self.calculate_1d_scenic_score(col, y) * self.calculate_1d_scenic_score( row, x ) def run(self, input: Iterator) -> Any: self.trees = list(input) width = len(self.trees[0]) height = len(self.trees) scenic_scores: List[int] = [] for x in range(1, width - 1): for y in range(1, height - 1): scenic_score = self.calculate_scenic_score(x, y) scenic_scores.append(scenic_score) return max(scenic_scores)