view day3b.rb @ 30:6de4f4d5404d

Implement Day 21 "possible spaces in a maze" Part 2 needs something like "find the repeats and lowest common multiple" that I'm not bothering with
author IBBoard <dev@ibboard.co.uk>
date Wed, 03 Jan 2024 12:01:18 +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(:+)