summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--solutions/py/d10.py214
-rw-r--r--solutions/py/main.py3
2 files changed, 131 insertions, 86 deletions
diff --git a/solutions/py/d10.py b/solutions/py/d10.py
index 1360490..b7ff5db 100644
--- a/solutions/py/d10.py
+++ b/solutions/py/d10.py
@@ -11,57 +11,7 @@ def red(dcoord):
gcd = math.gcd(dx, dy)
return (dx // gcd, dy // gcd)
-input = open("../input/10","r")
-t1 = open("../input/10-test1","r")
-
-input = input.readlines()
-
-asteroids = set()
-res = {}
-
-max_x = len(input[0].rstrip())
-max_y = len(input)
-
-for y in range(max_y):
- for x in range(max_x):
- if input[y][x] == "#":
- asteroids.add((x,y))
-
-for a in asteroids: # for each asteroid ...
- candidates = set(asteroids.copy())
- candidates.remove(a)
- seen = set()
- while len(candidates) > 0:
- c = candidates.pop()
- seen.add(c)
- dx = c[0] - a[0]
- dy = c[1] - a[1]
- x = a[0]
- y = a[1]
- x += dx
- y += dy
- dx, dy = red((dx, dy))
- x += dx
- y += dy
- while x < max_x and y < max_y and x >= 0 and y >= 0:
- if (x, y) in candidates:
- candidates.remove((x, y))
- if (x, y) in seen:
- seen.remove((x, y))
- x += dx
- y += dy
- res[a] = seen
-
-best = [0, 0, 0]
-for coord in res:
- if (amount := len(res[coord])) > best[0]:
- best = [amount, coord, res[coord]]
-print(best[0], best[1], best[2])
-asteroids.remove(best[1])
-x0 = best[1][0]
-y0 = best[1][1]
-
-def angle(x, y):
+def angle(x, y): # from y-axis, clockwise
if x >= 0 and y > 0:
return math.atan(abs(x/y))
if x > 0 and y <= 0:
@@ -71,39 +21,133 @@ def angle(x, y):
else:
return math.atan(abs(y/x)) + 3*math.pi / 2
-angles = {}
-q = queue.Queue()
-for a in asteroids:
- angles[a] = angle(a[0] - x0, y0 - a[1])
-
-print("sorting")
-for k, v in sorted(angles.items(), key=lambda item: item[1]):
- print(k, v)
- if k in best[2]:
- q.put(k)
-
-print("q", list(q.queue))
-
-destroyed = 1
-while not q.empty():
- asteroid = q.get()
- print(destroyed, asteroid)
- asteroids.remove(asteroid)
- destroyed += 1
-
- # add next asteroid behind to queue
- dx = asteroid[0] - x0
- dy = asteroid[1] - y0
- x = x0
- y = y0
- x += dx
- y += dy
- dx, dy = red((dx, dy))
- x += dx
- y += dy
- while x < max_x and y < max_y and x >= 0 and y >= 0:
- if (x, y) in asteroids:
- q.put((x, y))
- break
+def pt1(input):
+ asteroids = set()
+ res = {}
+
+ max_x = len(input[0].rstrip())
+ max_y = len(input)
+
+ for y in range(max_y):
+ for x in range(max_x):
+ if input[y][x] == "#":
+ asteroids.add((x,y))
+
+ for a in asteroids:
+ candidates = set(asteroids.copy())
+ candidates.remove(a)
+ seen = set()
+ while len(candidates) > 0:
+ c = candidates.pop()
+ seen.add(c)
+ dx = c[0] - a[0]
+ dy = c[1] - a[1]
+ x = a[0]
+ y = a[1]
+ x += dx
+ y += dy
+ dx, dy = red((dx, dy))
+ x += dx
+ y += dy
+ while x < max_x and y < max_y and x >= 0 and y >= 0:
+ if (x, y) in candidates:
+ candidates.remove((x, y))
+ if (x, y) in seen:
+ seen.remove((x, y))
+ x += dx
+ y += dy
+ res[a] = seen
+
+ best = [0, 0, 0]
+ for coord in res:
+ if (amount := len(res[coord])) > best[0]:
+ best = [amount, coord, res[coord]]
+ return (best[1], best[0])
+
+def pt2(input):
+ asteroids = set()
+ res = {}
+
+ max_x = len(input[0].rstrip())
+ max_y = len(input)
+
+ for y in range(max_y):
+ for x in range(max_x):
+ if input[y][x] == "#":
+ asteroids.add((x,y))
+
+ for a in asteroids:
+ candidates = set(asteroids.copy())
+ candidates.remove(a)
+ seen = set()
+ while len(candidates) > 0:
+ c = candidates.pop()
+ seen.add(c)
+ dx = c[0] - a[0]
+ dy = c[1] - a[1]
+ x = a[0]
+ y = a[1]
+ x += dx
+ y += dy
+ dx, dy = red((dx, dy))
+ x += dx
+ y += dy
+ while x < max_x and y < max_y and x >= 0 and y >= 0:
+ if (x, y) in candidates:
+ candidates.remove((x, y))
+ if (x, y) in seen:
+ seen.remove((x, y))
+ x += dx
+ y += dy
+ res[a] = seen
+
+ best = [0, 0, 0]
+ for coord in res:
+ if (amount := len(res[coord])) > best[0]:
+ best = [amount, coord, res[coord]]
+ asteroids.remove(best[1])
+ x0 = best[1][0]
+ y0 = best[1][1]
+
+ angles = {}
+ q = queue.Queue()
+ for a in asteroids:
+ angles[a] = angle(a[0] - x0, y0 - a[1])
+
+ for k, v in sorted(angles.items(), key=lambda item: item[1]):
+ if k in best[2]:
+ q.put(k)
+
+ destroyed = 1
+ while not q.empty():
+ asteroid = q.get()
+ if destroyed == 200:
+ return (asteroid, asteroid[0]*100 + asteroid[1])
+ asteroids.remove(asteroid)
+ destroyed += 1
+
+ # add next asteroid behind to queue
+ dx = asteroid[0] - x0
+ dy = asteroid[1] - y0
+ x = x0
+ y = y0
x += dx
y += dy
+ dx, dy = red((dx, dy))
+ x += dx
+ y += dy
+ while x < max_x and y < max_y and x >= 0 and y >= 0:
+ if (x, y) in asteroids:
+ q.put((x, y))
+ break
+ x += dx
+ y += dy
+
+if __name__ == "__main__":
+ import cProfile
+
+ input = open("../input/10","r").readlines()
+ cProfile.run("pt1(input)")
+ cProfile.run("pt2(input)")
+ print(pt1(input))
+ print(pt2(input))
diff --git a/solutions/py/main.py b/solutions/py/main.py
index 8887664..f3c5b78 100644
--- a/solutions/py/main.py
+++ b/solutions/py/main.py
@@ -9,8 +9,9 @@ import d06
import d07
import d08
import d09
+import d10
-mods = [d01, d02, d03, d04, d05, d06, d07, d08, d09]
+mods = [d01, d02, d03, d04, d05, d06, d07, d08, d09, d10]
timings = [[0 for _ in range(2)] for _ in range(len(mods))]
clock_type = time.CLOCK_MONOTONIC