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))