Mercurial > repos > other > adventofcode2023
view day3b.rb @ 8:51e5f26dc81e
Add a template file for reuse
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Thu, 07 Dec 2023 19:41:46 +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(:+)