advent-of-code

Perserverance, or the lack thereof

git clone git://git.shimmy1996.com/advent-of-code.git

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