Mercurial > repos > other > adventofcode2023
comparison day3b.rb @ 2:0f4991eca11a
Implement day 3
author | IBBoard <dev@ibboard.co.uk> |
---|---|
date | Sun, 03 Dec 2023 16:07:25 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
1:49dd1ae93696 | 2:0f4991eca11a |
---|---|
1 #! /usr/bin/env ruby | |
2 | |
3 if ARGV.length != 1 | |
4 abort("Incorrect arguments - needs input file") | |
5 elsif not File.exist? (ARGV[0]) | |
6 abort("File #{ARGV[0]} did not exist") | |
7 end | |
8 | |
9 file = ARGV[0] | |
10 | |
11 number_chars = *('0'..'9') | |
12 skip_chars = ['.'] | |
13 | |
14 numbers = Hash.new | |
15 symbols = Array.new | |
16 Position = Struct.new(:x, :y) | |
17 NumberValue = Struct.new(:value, :positions) | |
18 SymbolValue = Struct.new(:value, :position) | |
19 | |
20 def create_number_position(vals) | |
21 number = vals.reduce("") {|m, v| m + v[0]}.to_i | |
22 positions = vals.map {|v| Position.new(v[1], v[2])} | |
23 NumberValue.new(number, positions) | |
24 end | |
25 | |
26 def adjacent(a, b) | |
27 (a.x - b.x).abs <= 1 and (a.y - b.y).abs <= 1 | |
28 end | |
29 | |
30 sum = 0 | |
31 positions = File.open(file, "r").each_line(chomp: true).with_index.map do |line, index| | |
32 numbers = line.each_char.with_index.map {|c, i| if number_chars.include? c or !skip_chars.include? c then [c, index, i] end }\ | |
33 .filter {|v| v != nil }\ | |
34 .reduce([[], []]) do |memo, val| | |
35 if number_chars.include? val[0] then | |
36 if memo[1].last and memo[1].last[2] + 1 != val[2] then | |
37 memo[0] << create_number_position(memo[1]) | |
38 memo[1] = [] | |
39 end | |
40 memo[1] << val | |
41 else | |
42 if memo[1] != [] then | |
43 memo[0] << create_number_position(memo[1]) | |
44 memo[1] = [] | |
45 end | |
46 memo[0] << SymbolValue.new(val[0], Position.new(val[1], val[2])) | |
47 end | |
48 memo | |
49 end | |
50 if numbers[1] != [] then | |
51 numbers[0] << create_number_position(numbers[1]) | |
52 end | |
53 numbers[0] | |
54 end.flatten.group_by {|elem| elem.class} | |
55 | |
56 symbol_pos = positions[SymbolValue] | |
57 number_pos = positions[NumberValue] | |
58 | |
59 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(:+) |