advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git
commit 703e896dca75fbefc681f099c68449f0590c8681
parent bba64a36e16913403868854c5467498dc816ae49
Author: Shimmy Xu <shimmy.xu@shimmy1996.com>
Date:   Tue, 10 Dec 2019 13:12:47 -0500

Add Julia solution for day 10

Diffstat:
Aday-10/day-10.jl | 95+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 95 insertions(+), 0 deletions(-)
diff --git a/day-10/day-10.jl b/day-10/day-10.jl
@@ -0,0 +1,95 @@
+function line_of_sight(x_diff, y_diff)
+    if x_diff == 0 || y_diff == 0
+        (sign(x_diff), sign(y_diff))
+    else
+        factor = gcd(x_diff, y_diff)
+        (x_diff ÷ factor, y_diff ÷ factor)
+    end
+end
+
+function coord_to_angle(coord)
+    angle = atan(coord[2], coord[1]) + 0.5π
+    if angle < 0
+        angle += 2π
+    end
+    angle
+end
+
+function part_1(input)
+    detected = Dict();
+    for x in 1:length(input)
+        for y in 1:length(input)
+            if input[y][x]
+                # If there's an asteroid, compute line of sight with all others.
+                view_curr = Set();
+                for (coord, view) in detected
+                    push!(view,line_of_sight(
+                        x - coord[1],
+                        y - coord[2]
+                    ))
+                    push!(view_curr, line_of_sight(
+                        coord[1] - x,
+                        coord[2] - y,
+                    ))
+                end
+                detected[(x, y)] = view_curr
+            end
+        end
+    end
+    maximum(p -> (length(p[2]), p[1]), detected)
+end
+
+function part_2(input, station)
+    # Record detected asteroids sorted by line of sight angle.
+    detected = Dict();
+    for x in 1:length(input)
+        for y in 1:length(input)
+            if input[y][x] && ((x, y) != station)
+                x_diff = x - station[1]
+                y_diff = y - station[2]
+                push!(get!(detected, line_of_sight(x_diff, y_diff), []),
+                      (x_diff, y_diff))
+            end
+        end
+    end
+    # Sort line of sight by angle, which starts CW from north.
+    los_sorted = collect(keys(detected))
+    sort!(los_sorted; by = coord_to_angle)
+    los_count = Dict(map(p -> (p[1], length(p[2])), zip(keys(detected), values(detected))))
+    # Vaporize by going around sorted los until we hit 200th.
+    num_vaporized = 0
+    last_los = (0, 0)
+    while true
+        for key in los_sorted
+            if los_count[key] > 0
+                los_count[key] -= 1
+                num_vaporized += 1
+                last_los = key
+                if num_vaporized == 200
+                    break
+                end
+            end
+        end
+        if num_vaporized == 200
+            break
+        end
+    end
+    # Sort asteroids in that los and count back.
+    asteroids_in_los = copy(detected[last_los])
+    sort!(asteroids_in_los, by=coord -> coord[1]^2 + coord[2]^2)
+    reverse!(asteroids_in_los)
+    jackpot = asteroids_in_los[los_count[last_los] + 1];
+    jackpot = [jackpot[1] + station[1] - 1, jackpot[2] + station[2] - 1]
+    # Convert relative coordinates to absolute one.
+    jackpot[1] * 100 + jackpot[2]
+end
+
+input = map(readlines(open("input.txt"))) do line
+    map(ch -> ch == '#', collect(line))
+end
+
+println("Julia:")
+println("Part 1: ")
+num_obs, station = part_1(input)
+println(num_obs, " asteroids observed at ", (station[1] - 1, station[2] - 1));
+println("Part 2: ", part_2(input, station))