Mercurial > repos > other > adventofcode2023
view day24.rb @ 35:ca54f9702892
Day 24 part 2 instructions and partial solution
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Thu, 18 Apr 2024 19:54:59 +0100 |
parents | 59620bbc4084 |
children |
line wrap: on
line source
#! /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