106 lines
2.0 KiB
Ruby
106 lines
2.0 KiB
Ruby
#prepare the input which is a string containing new lines
|
|
def parse(input)
|
|
data = []
|
|
row = 0
|
|
symbols = []
|
|
numbers = []
|
|
input.each_line do |line|
|
|
start_num = false
|
|
num = ""
|
|
num_cols = []
|
|
|
|
line.chomp.chars.each_with_index do |c,col|
|
|
if c == "."
|
|
if start_num
|
|
# finish a number
|
|
numbers << [num.to_i, row, num_cols]
|
|
start_num = false
|
|
num = ""
|
|
num_cols = []
|
|
end
|
|
elsif /\d/.match?(c)
|
|
# a digit
|
|
start_num = true
|
|
num += c
|
|
num_cols << col
|
|
elsif c == "*"
|
|
# symbol
|
|
if start_num
|
|
# finish a number
|
|
numbers << [num.to_i, row, num_cols]
|
|
start_num = false
|
|
num = ""
|
|
num_cols = []
|
|
end
|
|
# fill adjacents
|
|
|
|
symbols << [row,col]
|
|
else
|
|
# other symbol
|
|
if start_num
|
|
# finish a number
|
|
numbers << [num.to_i, row, num_cols]
|
|
start_num = false
|
|
num = ""
|
|
num_cols = []
|
|
end
|
|
end
|
|
end
|
|
|
|
if start_num
|
|
# finish a number
|
|
numbers << [num.to_i, row, num_cols]
|
|
start_num = false
|
|
num = ""
|
|
num_cols = []
|
|
end
|
|
row += 1
|
|
end
|
|
data = [symbols,numbers]
|
|
data
|
|
end
|
|
|
|
def find_adjacent_numbers(row,col,numbers)
|
|
adjacents = []
|
|
matches = [
|
|
[row-1,col-1],
|
|
[row-1,col,],
|
|
[row-1,col+1],
|
|
[row,col-1],
|
|
[row,col+1],
|
|
[row+1,col-1],
|
|
[row+1,col],
|
|
[row+1,col+1]
|
|
]
|
|
numbers.each do |number|
|
|
num, row, cols = number
|
|
cols.each do |col|
|
|
if matches.include? [row,col]
|
|
adjacents << num
|
|
break
|
|
end
|
|
end
|
|
|
|
end
|
|
|
|
adjacents
|
|
end
|
|
|
|
# result should a single string or integer
|
|
def calculate(data)
|
|
result = ""
|
|
symbols, numbers = data
|
|
selected_numbers = []
|
|
symbols.each do |symbol|
|
|
row,col = symbol
|
|
adj = find_adjacent_numbers(row,col,numbers)
|
|
if adj.length == 2
|
|
selected_numbers << adj.first * adj.last
|
|
end
|
|
end
|
|
|
|
result = selected_numbers.reduce(&:+)
|
|
|
|
result
|
|
end
|