day-10.jl (2970B)
1 function line_of_sight(x_diff, y_diff)
2 if x_diff == 0 || y_diff == 0
3 (sign(x_diff), sign(y_diff))
4 else
5 factor = gcd(x_diff, y_diff)
6 (x_diff ÷ factor, y_diff ÷ factor)
7 end
8 end
9
10 function coord_to_angle(coord)
11 angle = atan(coord[2], coord[1]) + 0.5π
12 if angle < 0
13 angle += 2π
14 end
15 angle
16 end
17
18 function part_1(input)
19 detected = Dict();
20 for x in 1:length(input)
21 for y in 1:length(input)
22 if input[y][x]
23 # If there's an asteroid, compute line of sight with all others.
24 view_curr = Set();
25 for (coord, view) in detected
26 push!(view,line_of_sight(
27 x - coord[1],
28 y - coord[2]
29 ))
30 push!(view_curr, line_of_sight(
31 coord[1] - x,
32 coord[2] - y,
33 ))
34 end
35 detected[(x, y)] = view_curr
36 end
37 end
38 end
39 maximum(p -> (length(p[2]), p[1]), detected)
40 end
41
42 function part_2(input, station)
43 # Record detected asteroids sorted by line of sight angle.
44 detected = Dict();
45 for x in 1:length(input)
46 for y in 1:length(input)
47 if input[y][x] && ((x, y) != station)
48 x_diff = x - station[1]
49 y_diff = y - station[2]
50 push!(get!(detected, line_of_sight(x_diff, y_diff), []),
51 (x_diff, y_diff))
52 end
53 end
54 end
55 # Sort line of sight by angle, which starts CW from north.
56 los_sorted = collect(keys(detected))
57 sort!(los_sorted; by = coord_to_angle)
58 los_count = Dict(map(p -> (p[1], length(p[2])), zip(keys(detected), values(detected))))
59 # Vaporize by going around sorted los until we hit 200th.
60 num_vaporized = 0
61 last_los = (0, 0)
62 while true
63 for key in los_sorted
64 if los_count[key] > 0
65 los_count[key] -= 1
66 num_vaporized += 1
67 last_los = key
68 if num_vaporized == 200
69 break
70 end
71 end
72 end
73 if num_vaporized == 200
74 break
75 end
76 end
77 # Sort asteroids in that los and count back.
78 asteroids_in_los = copy(detected[last_los])
79 sort!(asteroids_in_los, by=coord -> coord[1]^2 + coord[2]^2)
80 reverse!(asteroids_in_los)
81 jackpot = asteroids_in_los[los_count[last_los] + 1];
82 jackpot = [jackpot[1] + station[1] - 1, jackpot[2] + station[2] - 1]
83 # Convert relative coordinates to absolute one.
84 jackpot[1] * 100 + jackpot[2]
85 end
86
87 input = map(readlines(open("input.txt"))) do line
88 map(ch -> ch == '#', collect(line))
89 end
90
91 println("Julia:")
92 println("Part 1: ")
93 num_obs, station = part_1(input)
94 println(num_obs, " asteroids observed at ", (station[1] - 1, station[2] - 1));
95 println("Part 2: ", part_2(input, station))