Author: Honza Pokorny <me@honza.ca>
10p2
010/main.py | 116 ++++++++++++++++++++++++++++++++----------------------
diff --git a/010/main.py b/010/main.py index cc16ddf2af995134baf77595e4648008737bf5c7..084bc2a1fbf1eb02c56dafd24fc78bd3705e6eec 100644 --- a/010/main.py +++ b/010/main.py @@ -1,36 +1,8 @@ from copy import deepcopy -from math import gcd, sqrt +from math import gcd, atan2, pi from itertools import groupby -MAP = """.#..# -..... -##### -....# -...##""" - -MAP2 = """......#.#. -#..#.#.... -..#######. -.#.#.###.. -.#..#..... -..#....#.# -#..#....#. -.##.#..### -##...#..#. -.#....####""" - -MAP3 = """#.#...#.#. -.###....#. -.#....#... -##.#.#.#.# -....#.#.#. -.##..###.# -..#...##.. -..##....## -......#... -.####.###.""" - PUZZLE = """.###..#######..####..##...# ########.#.###...###.#....# ###..#...#######...#..####. @@ -65,12 +37,13 @@ x1, y1 = ast1 x2, y2 = ast2 x_, y_ = x2 - x1, y2 - y1 + x_, y_ = x1 - x2, y1 - y2 g = gcd(x_, y_) slope = int(x_ / g), int(y_ / g) - distance = sqrt(float(x_ ** 2 + y_ ** 2)) - return slope, distance + distance = float(x_ ** 2 + y_ ** 2) + return None, distance def parse_map(data): @@ -94,7 +67,6 @@ slope, dist = get_distance_and_slope(ast, other_ast) data.append({ 'ast': ast, - 'slope': slope, 'distance': dist }) @@ -108,6 +80,68 @@ return visible +def rem(self, rhs): + if rhs == 0: + raise Exception('zerooo') + + r = self % rhs + + if r < 0: + if rhs < 0: + return r - rhs + else: + return r + rhs + else: + return r + + +def get_angle(a, b): + y = b[0] - a[0] + x = a[1] - b[1] + angle = atan2(y, x) + + a = rem(angle, pi * 2.0) + prec = 100000 + + return int(a * prec) + + +def get_visible_asteroids_by_angle(ast, asteroid_map): + asteroids = [] + + for other_ast in asteroid_map: + if ast == other_ast: + continue + + _, dist = get_distance_and_slope(ast, other_ast) + asteroids.append({ + 'ast': other_ast, + # 'angle': get_angle(ast, other_ast), + 'distance': dist + }) + + asteroids = sorted(asteroids, key=lambda x: x['distance']) + sort_keys = {} + things = [] + + for i, asteroid in enumerate(asteroids): + angle = get_angle(ast, asteroid['ast']) + previous_asteroids = filter( + lambda x: angle == get_angle(ast, x['ast']), + asteroids[:i] + ) + rank = len(list(previous_asteroids)) + + s = "%s-%s" % asteroid['ast'] + sort_keys[s] = (rank, angle, asteroid['ast']) + things.append(s) + + things = sorted(things, key=lambda x: sort_keys[x]) + two_hundredth = things[199] + _, _, ast = sort_keys[two_hundredth] + print(ast[0] * 100 + ast[1]) + + def find_best_asteroid(asteroid_map): x = {} for ast in asteroid_map: @@ -121,23 +155,11 @@ 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) + # station, visible = find_best_asteroid(asteroid_map) + station = (17, 23) - + get_visible_asteroids_by_angle(station, asteroid_map) if __name__ == '__main__':