34
|
1 #! /usr/bin/env ruby
|
|
2
|
|
3 if ARGV.length != 1
|
|
4 abort("Incorrect arguments - needs input file")
|
|
5 elsif not File.exist? (ARGV[0])
|
|
6 abort("File #{ARGV[0]} did not exist")
|
|
7 end
|
|
8
|
|
9 file = ARGV[0]
|
|
10
|
|
11 MovingObject = Struct.new(:x, :y, :z, :dx, :dy, :dz)
|
|
12 Position = Struct.new(:x, :y, :z)
|
|
13
|
|
14 box_range = 7..27
|
|
15 box_range = 200000000000000..400000000000000
|
|
16
|
|
17 objects = File.open(file, "r").each_line(chomp: true).map do |line|
|
|
18 pos, vel = line.split(" @ ")
|
|
19 position = pos.split(", ").map(&:to_f)
|
|
20 velocity = vel.split(",").map(&:to_f)
|
|
21 MovingObject.new(position[0], position[1], position[2], velocity[0], velocity[1], velocity[2])
|
|
22 end
|
|
23
|
|
24 # Reset our origin coordinates so that the bounding box starts at 0,0
|
|
25 # This prevents overflow with large numbers in the later calculation
|
|
26 offset = box_range.begin
|
|
27 box_range = 0..(box_range.size-1)
|
|
28 objects.each {|obj| obj.x -= offset; obj.y -= offset; obj.z -= offset}
|
|
29
|
|
30
|
|
31 def is_parallel?(a, b)
|
|
32 (a.dx / b.dx) == (a.dy / b.dy)
|
|
33 end
|
|
34
|
|
35 def is_in_past?(obj, point)
|
|
36 (obj.dx > 0 ? obj.x > point.x : obj.x < point.x) || (obj.dy > 0 ? obj.y > point.y : obj.y < point.y)
|
|
37 end
|
|
38
|
|
39 intersects = objects.combination(2).filter {|a, b| !is_parallel?(a, b) }.map do |a,b|
|
|
40 # https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
|
|
41 x_1 = a.x
|
|
42 x_2 = a.x + a.dx
|
|
43 x_3 = b.x
|
|
44 x_4 = b.x + b.dx
|
|
45 y_1 = a.y
|
|
46 y_2 = a.y + a.dy
|
|
47 y_3 = b.y
|
|
48 y_4 = b.y + b.dy
|
|
49
|
|
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)))
|
|
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)))
|
|
52 [a, b, Position.new(px, py, 0)]
|
|
53 end.filter do |a,b,intersect|
|
|
54 box_range.include?(intersect.x) && box_range.include?(intersect.y) && !is_in_past?(a, intersect) && !is_in_past?(b, intersect)
|
|
55 end
|
|
56
|
|
57 puts intersects.length |