implemented day 3 part 1.

This commit is contained in:
didier amyot committed 2023-12-04 10:01:46 -05:00
1 parent 4ddb2bc807
commit 6d36e67a24
4 files changed
+384

No files matched your search

+137
View File
@@ -0,0 +1,137 @@
# frozen_string_literal: true
def group_neighbour(lst, &block)
if lst.empty?
return []
end
ret = [[lst[0]]]
lst.each_cons(2) do |first_and_second|
first, second = first_and_second
if block.call first, second
ret[-1].append second
else
ret.append [second]
end
end
ret
end
class EngineNumber
def initialize(line_index, start, end_, value)
@line_index = line_index
@start = start
@end_ = end_
@value = value
end
attr_accessor :line_index
attr_accessor :start
attr_accessor :end_
attr_accessor :value
end
class EngineLine
def initialize(idx, line)
@idx = idx
@line = line
end
def is_symbols?(letter)
unless letter
return false
end
"1234567890.".index(letter) == nil
end
def has_any_symbols_at(indexes)
indexes.any? do |idx|
is_symbols? @line[idx]
end
end
def extract_digit_indexes(word)
digit_indexes = []
word.split("").each_with_index do |letter, index|
if "0123456789".index letter
digit_indexes.append index
end
end
digit_indexes
end
def group_digit_indexes(digit_indexes)
group_neighbour(digit_indexes) {|x, y| y == x + 1}
end
def create_engine_number(digit_group)
start = digit_group.min
end_ = 1 + digit_group.max
value = @line[start...end_].to_i
EngineNumber.new @idx, start, end_, value
end
def extract_engine_numbers
digit_indexes = extract_digit_indexes @line
group_digit_indexes(digit_indexes).map &method(:create_engine_number)
end
end
class Engine
def initialize(engine_lines)
@engine_lines = engine_lines
end
def self.deserialize(ser)
els = ser.strip.split("\n").each_with_index.map { |line, idx| EngineLine.new idx, line}
return self.new els
end
def extract_engine_numbers
@engine_lines
.map {|line| line.extract_engine_numbers}
.flatten
end
def has_symbol?(line_index, indexes_in_line)
# indexes_in_line = indexes_in_line || []
# puts "> #{ indexes_in_line }"
@engine_lines[line_index]&.has_any_symbols_at indexes_in_line
end
def get_engine_number_neighbourhood(engine_number)
line_index = engine_number.line_index
[
{line_index: line_index, indexes_in_line: ((engine_number.start-1)..(engine_number.start-1))},
{line_index: line_index, indexes_in_line: ((engine_number.end_)..(engine_number.end_))},
{line_index: line_index - 1 , indexes_in_line: ((engine_number.start - 1)...(engine_number.end_+1))},
{line_index: line_index + 1 , indexes_in_line: ((engine_number.start - 1)...(engine_number.end_+1))},
]
end
def touches_symbol?(engine_number)
get_engine_number_neighbourhood(engine_number).map do |h|
has_symbol?(h[:line_index], h[:indexes_in_line])
end
.any?
end
def extract_engine_numbers_that_touches_symbols
extract_engine_numbers.filter {|engine_number| touches_symbol? engine_number}
end
attr_accessor :engine_lines
end
input_file_name = File.join(File.dirname(__FILE__), "day_3_input.txt")
input_content = File.open(input_file_name).read
engine = Engine.deserialize input_content
puts engine.extract_engine_numbers_that_touches_symbols.map {|e| e.value} .sum