annotate day24.rb @ 39:0e17e4bd97a9 default tip

Rewrite as four-dimensional route finding The grid isn't just a 2D grid. The constraints make it 4D: * X * Y * Last direction * Number of steps in that direction By tracking all four dimensions, we can find the shortest route for _all_ combinations of the constraint. Previously, we were dropping routes that were currently longer but ended up shorter because they could take subsequent steps that other routes couldn't.
author IBBoard <dev@ibboard.co.uk>
date Sun, 22 Sep 2024 11:30:53 +0100
parents 59620bbc4084
children
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
34
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
1 #! /usr/bin/env ruby
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
2
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
3 if ARGV.length != 1
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
4 abort("Incorrect arguments - needs input file")
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
5 elsif not File.exist? (ARGV[0])
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
6 abort("File #{ARGV[0]} did not exist")
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
7 end
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
8
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
9 file = ARGV[0]
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
10
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
11 MovingObject = Struct.new(:x, :y, :z, :dx, :dy, :dz)
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
12 Position = Struct.new(:x, :y, :z)
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
13
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
14 box_range = 7..27
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
15 box_range = 200000000000000..400000000000000
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
16
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
17 objects = File.open(file, "r").each_line(chomp: true).map do |line|
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
18 pos, vel = line.split(" @ ")
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
19 position = pos.split(", ").map(&:to_f)
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
20 velocity = vel.split(",").map(&:to_f)
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
21 MovingObject.new(position[0], position[1], position[2], velocity[0], velocity[1], velocity[2])
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
22 end
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
23
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
24 # Reset our origin coordinates so that the bounding box starts at 0,0
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
25 # This prevents overflow with large numbers in the later calculation
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
26 offset = box_range.begin
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
27 box_range = 0..(box_range.size-1)
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
28 objects.each {|obj| obj.x -= offset; obj.y -= offset; obj.z -= offset}
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
29
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
30
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
31 def is_parallel?(a, b)
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
32 (a.dx / b.dx) == (a.dy / b.dy)
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
33 end
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
34
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
35 def is_in_past?(obj, point)
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
36 (obj.dx > 0 ? obj.x > point.x : obj.x < point.x) || (obj.dy > 0 ? obj.y > point.y : obj.y < point.y)
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
37 end
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
38
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
39 intersects = objects.combination(2).filter {|a, b| !is_parallel?(a, b) }.map do |a,b|
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
40 # https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
41 x_1 = a.x
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
42 x_2 = a.x + a.dx
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
43 x_3 = b.x
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
44 x_4 = b.x + b.dx
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
45 y_1 = a.y
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
46 y_2 = a.y + a.dy
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
47 y_3 = b.y
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
48 y_4 = b.y + b.dy
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
49
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
50 px = ((((x_1 * y_2) - (y_1 * x_2)) * (x_3 - x_4)) - ((x_1 - x_2) * ((x_3 * y_4) - (y_3 * x_4)))) / (((x_1 - x_2) * (y_3 - y_4)) - ((y_1 - y_2) * (x_3 - x_4)))
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
51 py = ((((x_1 * y_2) - (y_1 * x_2)) * (y_3 - y_4)) - ((y_1 - y_2) * ((x_3 * y_4) - (y_3 * x_4)))) / (((x_1 - x_2) * (y_3 - y_4)) - ((y_1 - y_2) * (x_3 - x_4)))
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
52 [a, b, Position.new(px, py, 0)]
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
53 end.filter do |a,b,intersect|
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
54 box_range.include?(intersect.x) && box_range.include?(intersect.y) && !is_in_past?(a, intersect) && !is_in_past?(b, intersect)
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
55 end
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
56
59620bbc4084 Implement day 24 - 2D intersection
IBBoard <dev@ibboard.co.uk>
parents:
diff changeset
57 puts intersects.length