-
Notifications
You must be signed in to change notification settings - Fork 0
/
day3_part2.rb
142 lines (125 loc) · 4 KB
/
day3_part2.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
def get_number_and_index(str)
num_arr = []
ind_arr = []
num = ''
tmp_arr = []
str.chars.each_with_index do |char, index|
if char =~ /[0-9]/
num += char
tmp_arr << index
if index == str.size - 1
num_arr << num
ind_arr << tmp_arr[0]
end
else
if !num.empty?
num_arr << num
ind_arr << tmp_arr[0]
num = ''
tmp_arr = []
end
end
end
return num_arr, ind_arr
end
def numbers_adj_to_symbols(str, arr)
num_arr, ind_arr = get_number_and_index(str)
return [], [] if num_arr.empty?
out_arr = []
selected_ind_arr = []
num_arr.each_with_index do |num, i|
ind = ind_arr[i]
ind_current = [ind-1, ind + num.size]
if ind_current.any? { |index| str[index] =~ /[^0-9.]/ }
out_arr << num.to_i
selected_ind_arr << ind
else
ind_prev_next = (ind-1 < 0) ? ind .. ind + num.size : ind-1 .. ind + num.size
if arr.any? { |line| line[ind_prev_next].match?(/[^0-9.]/) }
out_arr << num.to_i
selected_ind_arr << ind
end
end
end
return out_arr, selected_ind_arr
end
# Algo:
# 1. Get the part numbers and their row + col index as a hash
# - key (int): row_index
# - value (nested arr): [[part, col], [part, col]]
# 0: [[467, 0], [114, 5]]
def get_part_numbers(filename)
lines_arr = File.read(filename).split("\n")
parts_number = []
lines_arr.each_index do |index|
this_line = lines_arr[index]
if index == 0
arr = [lines_arr[index+1]]
elsif index == lines_arr.size - 1
arr = [lines_arr[index-1]]
else
arr = [lines_arr[index-1], lines_arr[index+1]]
end
num_arr, ind_arr = numbers_adj_to_symbols(this_line, arr)
if !num_arr.empty?
num_arr.each_with_index do |num, ind|
parts_number << [num, index, ind_arr[ind]]
end
end
end
parts_number
end
=begin
Algo:
2. Get the row AND column index where a char is equal is "*"
3. Define the index of the boundary around the gear
- [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]
4. For each row index, get the value of the hash
- loop each subarr
- check if the col index of the part number overlaps with any of [col-1, col, col+1]
- if yes, select the the part number and store in output array
2. If the array has 2 elems, multiple the 2 numbers together
3. Store the product in `sum_arr`
4. Return the sum of all numbers in `sum_arr`
=end
def find_adjacent_part_numbers(boundary, parts_number)
out_arr = []
boundary.each do |one_side|
row, col = one_side
parts_number.each do |subarr|
pn, val = subarr[0], subarr[1..-1]
col_ind = Array(val[1]..val[1] + pn.digits.size - 1)
out_arr << pn if row == val[0] && col_ind.include?(col) && !out_arr.include?(pn)
end
end
out_arr
end
def gear_ratio(filename)
lines_arr = File.read(filename).split("\n")
parts_number = get_part_numbers(filename)
sum_arr = []
lines_arr.each_with_index do |line, row_index|
line.chars.each_with_index do |char, col_index|
if char == '*'
boundary = [[row_index, col_index - 1], [row_index, col_index + 1]]
if row_index == 0
boundary << [row_index + 1, col_index - 1] << [row_index + 1, col_index] << [row_index + 1, col_index + 1]
elsif row_index == lines_arr.size - 1
boundary << [row_index - 1, col_index - 1] << [row_index - 1, col_index] << [row_index - 1, col_index + 1]
else
boundary << [row_index + 1, col_index - 1] << [row_index + 1, col_index] << [row_index + 1, col_index + 1]
boundary << [row_index - 1, col_index - 1] << [row_index - 1, col_index] << [row_index - 1, col_index + 1]
end
found_parts_number = find_adjacent_part_numbers(boundary, parts_number)
if found_parts_number.size == 2
sum_arr << found_parts_number[0] * found_parts_number[1]
end
end
end
end
sum_arr.sum
end
p gear_ratio('test_input_day3.txt')
p gear_ratio('input_day3.txt')