/ 8.py
8.py
1 #!/usr/bin/python3 2 3 # run it as 4 # ./8.py [ --one | --two ] < inputs/8 5 6 import sys 7 import math 8 9 def ingest(): 10 # don't you love python sometimes? 11 return [[int(char) for char in line.strip()] for line in sys.stdin.readlines()] 12 13 def check_visible(direction_dict, mm): 14 if direction_dict.get(mm, 0) == 9: 15 return 16 if direction_dict.get(mm) is None or direction_dict.get(mm, 0) < data[line][char]: 17 visble.add((line, char)) 18 direction_dict[mm] = max(data[line][char], direction_dict.get(mm, 0)) 19 20 21 if __name__ == '__main__': 22 23 def display(): 24 winners = [sorted(rating.items(), key=lambda x: x[1])[-1][0]] 25 for line in range(length): 26 for char in range(length): 27 if (line, char) in winners: 28 print('▇', end='') 29 elif (line, char) in visble: 30 print('X', end='') 31 else: 32 print(data[line][char], end='') 33 print() 34 35 data = ingest() 36 assert len(data[0]) == len(data) 37 length = len(data) 38 visble = set() 39 rating = {} 40 41 if '--one' in sys.argv: 42 # ok, will try to be smart here 43 # check view from all 4 sides, this way I don't need to check some trees at all 44 north, south, west, east = {}, {}, {}, {} 45 for line in range(length): 46 for char in range(length): 47 check_visible(north, char) 48 for line in reversed(range(length)): 49 for char in range(length): 50 check_visible(south, char) 51 for char in range(length): 52 for line in range(length): 53 check_visible(west, line) 54 for char in reversed(range(length)): 55 for line in range(length): 56 check_visible(east, line) 57 print('visible:', len(visble)) 58 59 if '--two' in sys.argv: 60 def calc(me, neighbors): 61 value = 0 62 if not neighbors: 63 return value 64 for n in neighbors: 65 if n < me: 66 value += 1 67 elif n == me: 68 value += 1 69 break 70 else: 71 break 72 return value 73 74 # could be optimized by not copying every tree in each direction 75 # but that's not fun anyway. It would be fun to avoid some groups of trees somehow entirely 76 for line in range(length): 77 for char in range(length): 78 me = data[line][char] 79 up = [data[_][char] for _ in reversed(range(0, line))] 80 left = [data[line][_] for _ in reversed(range(0, char))] 81 down = [data[_][char] for _ in range(line+1, length)] 82 right = [data[line][_] for _ in range(char+1, length)] 83 rating[(line, char)] = math.prod([calc(me, _) for _ in (up, left, down, right)]) 84 # display() 85 winner_v = sorted(rating.items(), key=lambda x: x[1])[-1][1] 86 print(winner_v)