changeset 34:59620bbc4084

Implement day 24 - 2D intersection Needs an offset because the numbers are big enough to overflow
author IBBoard <dev@ibboard.co.uk>
date Fri, 05 Jan 2024 11:42:13 +0000
parents 676461cc3a70
children ca54f9702892
files day24.rb day24.txt
diffstat 2 files changed, 116 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/day24.rb	Fri Jan 05 11:42:13 2024 +0000
@@ -0,0 +1,57 @@
+#! /usr/bin/env ruby
+
+if ARGV.length != 1
+    abort("Incorrect arguments - needs input file")
+elsif not File.exist? (ARGV[0])
+abort("File #{ARGV[0]} did not exist")
+end
+
+file = ARGV[0]
+
+MovingObject = Struct.new(:x, :y, :z, :dx, :dy, :dz)
+Position = Struct.new(:x, :y, :z)
+
+box_range = 7..27
+box_range = 200000000000000..400000000000000
+
+objects = File.open(file, "r").each_line(chomp: true).map do |line|
+    pos, vel = line.split(" @ ")
+    position = pos.split(", ").map(&:to_f)
+    velocity = vel.split(",").map(&:to_f)
+    MovingObject.new(position[0], position[1], position[2], velocity[0], velocity[1], velocity[2])
+end
+
+# Reset our origin coordinates so that the bounding box starts at 0,0
+# This prevents overflow with large numbers in the later calculation
+offset = box_range.begin
+box_range = 0..(box_range.size-1)
+objects.each {|obj| obj.x -= offset; obj.y -= offset; obj.z -= offset}
+
+
+def is_parallel?(a, b)
+    (a.dx / b.dx) == (a.dy / b.dy)
+end
+
+def is_in_past?(obj, point)
+    (obj.dx > 0 ? obj.x > point.x : obj.x < point.x) || (obj.dy > 0 ? obj.y > point.y : obj.y < point.y)
+end
+
+intersects = objects.combination(2).filter {|a, b| !is_parallel?(a, b) }.map do |a,b|
+    # https://en.wikipedia.org/wiki/Line%E2%80%93line_intersection#Given_two_points_on_each_line
+    x_1 = a.x
+    x_2 = a.x + a.dx
+    x_3 = b.x
+    x_4 = b.x + b.dx
+    y_1 = a.y
+    y_2 = a.y + a.dy
+    y_3 = b.y
+    y_4 = b.y + b.dy
+
+    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)))
+    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)))
+    [a, b, Position.new(px, py, 0)]
+end.filter do |a,b,intersect|
+    box_range.include?(intersect.x) && box_range.include?(intersect.y) && !is_in_past?(a, intersect) && !is_in_past?(b, intersect)
+end
+
+puts intersects.length
\ No newline at end of file
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/day24.txt	Fri Jan 05 11:42:13 2024 +0000
@@ -0,0 +1,59 @@
+--- Day 24: Never Tell Me The Odds ---
+
+A set of objects have positions and velocities in 3D space, noted as `x, y, z @ Δx, Δy, Δz`, e.g.
+
+19, 13, 30 @ -2,  1, -2
+18, 19, 22 @ -1, -1, -2
+20, 25, 34 @ -2, -2, -4
+12, 31, 28 @ -1, -2, -1
+20, 19, 15 @  1, -5, -3
+
+Ignoring the Z axis, which objects will intersect _in future_ within a given bounding box.
+
+For example, with the box 7,7 to 27,27 and the objects above:
+
+Object A: 19, 13, 30 @ -2, 1, -2
+Object B: 18, 19, 22 @ -1, -1, -2
+Objects' paths will cross inside the test area (at x=14.333, y=15.333).
+
+Object A: 19, 13, 30 @ -2, 1, -2
+Object B: 20, 25, 34 @ -2, -2, -4
+Objects' paths will cross inside the test area (at x=11.667, y=16.667).
+
+Object A: 19, 13, 30 @ -2, 1, -2
+Object B: 12, 31, 28 @ -1, -2, -1
+Objects' paths will cross outside the test area (at x=6.2, y=19.4).
+
+Object A: 19, 13, 30 @ -2, 1, -2
+Object B: 20, 19, 15 @ 1, -5, -3
+Objects' paths crossed in the past for Object A.
+
+Object A: 18, 19, 22 @ -1, -1, -2
+Object B: 20, 25, 34 @ -2, -2, -4
+Objects' paths are parallel; they never intersect.
+
+Object A: 18, 19, 22 @ -1, -1, -2
+Object B: 12, 31, 28 @ -1, -2, -1
+Objects' paths will cross outside the test area (at x=-6, y=-5).
+
+Object A: 18, 19, 22 @ -1, -1, -2
+Object B: 20, 19, 15 @ 1, -5, -3
+Objects' paths crossed in the past for both Objects.
+
+Object A: 20, 25, 34 @ -2, -2, -4
+Object B: 12, 31, 28 @ -1, -2, -1
+Objects' paths will cross outside the test area (at x=-2, y=3).
+
+Object A: 20, 25, 34 @ -2, -2, -4
+Object B: 20, 19, 15 @ 1, -5, -3
+Objects' paths crossed in the past for Object B.
+
+Object A: 12, 31, 28 @ -1, -2, -1
+Object B: 20, 19, 15 @ 1, -5, -3
+Objects' paths crossed in the past for both Objects.
+
+
+
+Look for future intersections that happen with an X and Y position each at least 200000000000000 and at most 400000000000000. Disregard the Z axis entirely.
+
+Note: Some objects are moving upwards.
\ No newline at end of file