-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path12-2.rb
executable file
·106 lines (90 loc) · 2.3 KB
/
12-2.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
#!/usr/bin/env ruby
require 'numo/narray'
require 'algorithms'
class Map
attr_accessor :start, :end, :map, :lengths
def initialize(input)
@height = input.size
@width = input[0].size
@map = Numo::UInt8.zeros(@height, @width)
input.each_index do |row|
input[row].each_index do |col|
case input[row][col]
when 'S'
@map[row, col] = 0
when 'E'
@start = [row, col]
@map[row, col] = 'z'.ord - 'a'.ord
else
@map[row, col] = input[row][col].ord - 'a'.ord
end
end
end
@lengths = Numo::UInt32.new(@height, @width).fill Numo::UInt32::MAX
@lengths[@start[0], @start[1]] = 0
end
def solve!
queue = Containers::MinHeap.new
queue.push(0, @start)
until queue.empty?
length = queue.next_key
row, col = queue.pop
next if length > @lengths[row, col]
neighbours = [
[row + 1, col],
[row - 1, col],
[row, col + 1],
[row, col - 1]
]
neighbours.select! do |coords|
coords[0] >= 0 and
coords[0] < @height and
coords[1] >= 0 and
coords[1] < @width and
@map[row, col] <= @map[coords[0], coords[1]] + 1
end
neighbours.each do |step|
new_length = length + 1
if new_length < @lengths[step[0], step[1]]
@lengths[step[0], step[1]] = new_length
queue.push(new_length, [step[0], step[1]])
end
end
end
end
def solution
closest = Numo::UInt32::MAX
@map.each_with_index do |height, row, col|
next if height.positive?
if @lengths[row, col] < closest
closest = @lengths[row, col]
end
end
closest
end
def to_s
s = "<#{self.class}:\n"
s += "Start: #{@start}, end: #{@end}\n"
s += "\nMap:\n"
@height.times do |row|
@width.times do |col|
s += @map[row, col].to_s.rjust(2, '0') + ' '
end
s += "\n"
end
s += "\nLengths:\n"
@height.times do |row|
@width.times do |col|
s += @lengths[row, col].to_s.rjust(Math::log10(@lengths.max).ceil, '0') + ' '
end
s += "\n"
end
s += '>'
s
end
alias inspect to_s
end
input = File.read('12.input').lines.map(&:strip).map(&:chars)
map = Map.new(input)
map.solve!
print map.solution, "\n"