diff --git a/data/day24.rb b/data/day24.txt similarity index 100% rename from data/day24.rb rename to data/day24.txt diff --git a/lib/day24.rb b/lib/day24.rb index cc4abd5..e765258 100644 --- a/lib/day24.rb +++ b/lib/day24.rb @@ -1,33 +1,39 @@ # frozen_string_literal: true -# -class Line - attr_reader :slope, :y_intercept - def initialize(x, y, z, cx, cy, cz) - # Calculate the slope - @slope = cy.to_f / cx if cx != 0 - @slope ||= Float::INFINITY # Vertical line +class Line + attr_reader :slope, :y_intercept, :x, :y - # Calculate the y-intercept - if @slope == Float::INFINITY + def initialize(x, y, cx, cy) + @x = x + @y = y + if cx == 0 + @slope = Float::INFINITY @x_intercept = x else + @slope = cy.to_f / cx @y_intercept = y - @slope * x end end def intersects_with?(other_line) - # If slopes are equal, lines are parallel (or identical) - return false if @slope == other_line.slope - + return false if @slope == other_line.slope && @slope != Float::INFINITY + return false if @slope == Float::INFINITY && other_line.slope == Float::INFINITY && @x_intercept != other_line.x_intercept true end def intersection_point(other_line) - return nil unless intersects_with?(other_line) + return [0, 0] unless intersects_with?(other_line) - x = (other_line.y_intercept - @y_intercept) / (@slope - other_line.slope) - y = @slope * x + @y_intercept + if @slope == Float::INFINITY + x = @x_intercept + y = other_line.slope * x + other_line.y_intercept + elsif other_line.slope == Float::INFINITY + x = other_line.x_intercept + y = @slope * x + @y_intercept + else + x = (other_line.y_intercept - @y_intercept) / (@slope - other_line.slope) + y = @slope * x + @y_intercept + end [x, y] end @@ -39,24 +45,48 @@ def to_s "y = #{@slope}x + #{@y_intercept}" end end + + protected + + def x_intercept + @x_intercept + end end # Day24 class Day24 - def load(file) + def load(file, min, max) content = File.read(file) + @min = min + @max = max @parts = [] content.split("\n").each do |line| f, e = line.split("@") fs = f.split(",").map(&:to_i) es = e.split(",").map(&:to_i) - @parts << Line.new(fs[0], fs[1], fs[2], es[0], es[1], es[2]) + @parts << Line.new(fs[0], fs[1], es[0], es[1]) end end def part1 - puts @parts[0].intersection_point(@parts[1]) - sum = 0 - sum + result = [] + @parts.each_with_index do |part, i| + for j in (i + 1)..(@parts.length - 1) + other_part = @parts[j] + + if part.intersects_with?(other_part) + x, y = part.intersection_point(other_part) + # check if the intersection point is in the test grid + if x.between?(@min, @max) && y.between?(@min, @max) + # check if the intersection point is in the future + if x > part.x + puts "Intersection point: #{x}, #{y}" + result << part.intersection_point(other_part) + end + end + end + end + end + result.length end end diff --git a/test/unit/day24_test.rb b/test/unit/day24_test.rb index 355c1ef..624c6ce 100644 --- a/test/unit/day24_test.rb +++ b/test/unit/day24_test.rb @@ -4,7 +4,13 @@ class Day24Test < Minitest::Test def test_day24a sut = Day24.new - sut.load('data/day24a.txt') + sut.load('data/day24a.txt', 7, 27) assert_equal(2, sut.part1) end + + def _test_day24 + sut = Day24.new + sut.load('data/day24.txt', 200000000000000, 400000000000000) + assert_equal(14472, sut.part1) # too low + end end