-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy path15b_solution.rb
109 lines (91 loc) · 1.88 KB
/
15b_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
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
require 'set'
require 'lazy_priority_queue'
input = File.read("15input.txt").split("\n").map do |line|
line.split("").map(&:to_i)
end
class Paths
def initialize(max_x, max_y)
@queue = MinPriorityQueue.new
(0..max_x).each do |x|
(0..max_y).each do |y|
if x == 0 && y == 0
@queue.push [0, 0], 0
else
@queue.push [x, y], Float::INFINITY
end
end
end
@lengths = Hash.new { Float::INFINITY }
@lengths[[0, 0]] = 0
@visited = Set.new
end
# can only decrease
def set(x, y, length)
@queue.decrease_key [x, y], length
@lengths[[x, y]] = length
end
def visit_next
x, y = @queue.pop
@visited.add [x, y]
[x, y, length(x, y)]
end
def length(x, y)
@lengths[[x, y]]
end
def visited?(x, y)
@visited.include? [x, y]
end
end
class Board
def initialize(input)
@board = input
@max_x = 5*@board.length-1
@max_y = 5*@board[0].length-1
end
attr_reader :board, :max_x, :max_y
def end?(x, y)
x == max_x && y == max_y
end
def neighbours(x, y)
ns = []
if x != 0
ns << [x-1, y]
end
if y != 0
ns << [x, y-1]
end
if x != max_x
ns << [x+1, y]
end
if y != max_y
ns << [x, y+1]
end
ns
end
def get(x, y)
unwrapped = board[x % board.length][y % board[0].length] + (x/board.length) + (y/board[0].length)
if unwrapped > 9
unwrapped % 9
else
unwrapped
end
end
end
board = Board.new input
paths = Paths.new(board.max_x, board.max_y)
result = nil
while result.nil?
x, y, length = paths.visit_next
if board.end?(x, y)
result = length
else
board.neighbours(x, y).each do |nx, ny|
next if paths.visited?(nx, ny)
new_length = length + board.get(nx, ny)
if new_length < paths.length(nx, ny)
paths.set(nx, ny, new_length)
end
end
end
end
puts result