-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path09b_solution.rb
67 lines (52 loc) · 1.27 KB
/
09b_solution.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
require 'set'
input = File.read("./09input.txt")
board = input.split("\n").map do |line|
line.split("").map(&:to_i)
end
def neighbours(board, ri, ci)
result = []
last_ri = board.length - 1
last_ci = board[ri].length - 1
if ri != 0
result << [ri-1, ci]
end
if ri != last_ri
result << [ri+1, ci]
end
if ci != 0
result << [ri, ci-1]
end
if ci != last_ci
result << [ri, ci+1]
end
result
end
def is_low_point(board, ri, ci)
element = board[ri][ci]
neighbours(board, ri, ci).all? do |nri, nci|
element < board[nri][nci]
end
end
def basin_size(board, ri, ci, visited = Set.new)
return 0 if visited.include? [ri,ci]
visited.add [ri, ci]
basin_neighbours = neighbours(board, ri, ci).lazy.select do |nri, nci|
n = board[nri][nci]
n != 9 && board[ri][ci] < n
end
1 + basin_neighbours.inject(0) do |a, (nri, nci)|
a + basin_size(board, nri, nci, visited)
end
end
basin_sizes = []
board.each_with_index do |row, ri|
row.each_with_index do |entry, ci|
if is_low_point(board, ri, ci)
basin_sizes << basin_size(board, ri, ci)
end
end
end
# definitely not the most efficient solution, but I'm lazy
largest_sizes = basin_sizes.sort.reverse.take(3)
result = largest_sizes.inject(1) { |a, e| a * e }
puts result