Mercurial > repos > other > adventofcode2023
view day3b.rb @ 33:676461cc3a70
Day 23 - track segments, not each space
This allows us to explore the branches once then do quicker calculations
for valid route lengths. But still requires exploring 1,262,816 routes
to find the longest!
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Thu, 04 Jan 2024 14:52:24 +0000 |
parents | 0f4991eca11a |
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] number_chars = *('0'..'9') skip_chars = ['.'] numbers = Hash.new symbols = Array.new Position = Struct.new(:x, :y) NumberValue = Struct.new(:value, :positions) SymbolValue = Struct.new(:value, :position) def create_number_position(vals) number = vals.reduce("") {|m, v| m + v[0]}.to_i positions = vals.map {|v| Position.new(v[1], v[2])} NumberValue.new(number, positions) end def adjacent(a, b) (a.x - b.x).abs <= 1 and (a.y - b.y).abs <= 1 end sum = 0 positions = File.open(file, "r").each_line(chomp: true).with_index.map do |line, index| numbers = line.each_char.with_index.map {|c, i| if number_chars.include? c or !skip_chars.include? c then [c, index, i] end }\ .filter {|v| v != nil }\ .reduce([[], []]) do |memo, val| if number_chars.include? val[0] then if memo[1].last and memo[1].last[2] + 1 != val[2] then memo[0] << create_number_position(memo[1]) memo[1] = [] end memo[1] << val else if memo[1] != [] then memo[0] << create_number_position(memo[1]) memo[1] = [] end memo[0] << SymbolValue.new(val[0], Position.new(val[1], val[2])) end memo end if numbers[1] != [] then numbers[0] << create_number_position(numbers[1]) end numbers[0] end.flatten.group_by {|elem| elem.class} symbol_pos = positions[SymbolValue] number_pos = positions[NumberValue] puts symbol_pos.filter {|sym| sym.value == "*"}.map {|sym| number_pos.filter {|num| num.positions.any? {|num_pos| adjacent(num_pos, sym.position)}}}.filter {|nums| nums.length == 2}.map {|val| val.reduce(1) {|v, k| v * k.value}}.reduce(:+)