aoc2025/mark/day2/part2.rb

75 lines
1.8 KiB
Ruby

require 'debug'
require 'prime'
class ValidIdFilter
def initialize(file_path, debug: false)
@file_path = file_path
@debug = debug
end
def sum_invalid_ids
ranges = parse_input(File.read(@file_path))
invalid_ids = ranges.flat_map {|range| get_invalid_ids_from_range(range)}
puts invalid_ids.inspect if @debug
invalid_ids.sum
end
private
# @param [Range] e.g., 11-22
# @return [<Integer>] array of invalid ids in range
def get_invalid_ids_from_range(range)
range.select do |element|
invalid_id?(element)
end
end
def invalid_id?(integer)
# ID is invalid if it is made only of some sequence of digits repeated AT LEAST twice
string = integer.to_s
num_digits = string.length
puts "is #{string} an invalid ID?" if @debug
(1...num_digits).each do |n|
next if num_digits % n != 0
slices = string.chars.each_slice(n).map(&:join)
puts "...trying divisior #{n}: #{slices} ..." if @debug
return true if slices.uniq.length == 1 && slices.length > 1
end
false
end
# @param [String] full input e.g., "11-22,33-604,..."
# @return [<Range>] e.g., [11..22, 33..604, ...]
def parse_input(input)
input.split(',').map {|range| to_range(range)}
end
# @param [String] e.g., "11-22"
# @return [Range] e.g., 11..22 (inclusive)
def to_range(string)
boundaries = string.split('-').map(&:to_i)
raise "Invalid boundaries for #{string}, got #{boundaries.inspect}" if boundaries.length != 2
Range.new(boundaries[0], boundaries[1])
end
end
if ARGV[0].nil? || ARGV[0].empty?
puts "Usage: ruby part2.rb <file_name> [debug]"
exit 1
end
debug = (ARGV[1] == "debug")
filter = ValidIdFilter.new(ARGV[0], debug:)
puts "The answer is: #{filter.sum_invalid_ids}"
# The answer is: 41662374059
# real 0m24,122s
# user 0m24,049s
# sys 0m0,070s