ref: 3e9018eb7ab58e4e4fc66d9cfd5b455464cbd921
010/main.py
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 |
from copy import deepcopy from math import gcd, sqrt from itertools import groupby MAP = """.#..# ..... ##### ....# ...##""" MAP2 = """......#.#. #..#.#.... ..#######. .#.#.###.. .#..#..... ..#....#.# #..#....#. .##.#..### ##...#..#. .#....####""" MAP3 = """#.#...#.#. .###....#. .#....#... ##.#.#.#.# ....#.#.#. .##..###.# ..#...##.. ..##....## ......#... .####.###.""" PUZZLE = """.###..#######..####..##...# ########.#.###...###.#....# ###..#...#######...#..####. .##.#.....#....##.#.#.....# ###.#######.###..##......#. #..###..###.##.#.#####....# #.##..###....#####...##.##. ####.##..#...#####.#..###.# #..#....####.####.###.#.### #..#..#....###...#####..#.. ##...####.######....#.####. ####.##...###.####..##....# #.#..#.###.#.##.####..#...# ..##..##....#.#..##..#.#..# ##.##.#..######.#..#..####. #.....#####.##........##### ###.#.#######..#.#.##..#..# ###...#..#.#..##.##..#####. .##.#..#...#####.###.##.##. ...#.#.######.#####.#.####. #..##..###...###.#.#..#.#.# .#..#.#......#.###...###..# #.##.#.#..#.#......#..#..## .##.##.##.#...##.##.##.#..# #.###.#.#...##..#####.###.# #.####.#..#.#.##.######.#.. .#.#####.##...#...#.##...#.""" def get_distance_and_slope(ast1, ast2): x1, y1 = ast1 x2, y2 = ast2 x_, y_ = x2 - x1, y2 - y1 g = gcd(x_, y_) slope = int(x_ / g), int(y_ / g) distance = sqrt(float(x_ ** 2 + y_ ** 2)) return slope, distance def parse_map(data): result = [] for line_i, line in enumerate(data.splitlines()): for c_i, c in enumerate(line): if c == '#': result.append((c_i, line_i)) return result def get_visible_asteroid_count(ast, asteroid_map): data = [] for other_ast in asteroid_map: if ast == other_ast: continue slope, dist = get_distance_and_slope(ast, other_ast) data.append({ 'ast': ast, 'slope': slope, 'distance': dist }) data = sorted(data, key=lambda x: x['slope']) grouped = groupby(data, lambda x: x['slope']) visible = 0 for k, g in grouped: visible += 1 return visible def find_best_asteroid(asteroid_map): x = {} for ast in asteroid_map: num_visible_asts = get_visible_asteroid_count(ast, deepcopy(asteroid_map)) x[num_visible_asts] = ast keys = list(x.keys()) keys.sort() keys.reverse() return x[keys[0]], keys[0] def main(): asteroid_map = parse_map(MAP) _, num = find_best_asteroid(asteroid_map) assert num == 8, num asteroid_map = parse_map(MAP2) _, num = find_best_asteroid(asteroid_map) assert num == 33, num asteroid_map = parse_map(MAP3) _, num = find_best_asteroid(asteroid_map) assert num == 35, num asteroid_map = parse_map(PUZZLE) _, num = find_best_asteroid(asteroid_map) print(num) if __name__ == '__main__': main() |