Mercurial > repos > other > adventofcode2023
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