-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathday12part2.rb
140 lines (128 loc) · 3.03 KB
/
day12part2.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
file = File.open "day12in.txt"
grid = []
cost = []
starts = []
dest = nil
row = 0
col = 0
file.each_line do |l|
grid << []
cost << []
l.chomp.each_char do |c|
if c == "S"
starts << [row, col]
grid[row] << 0
cost[row] << 0
elsif c == "E"
dest = [row, col]
grid[row] << 25
cost[row] << 1e15
else
grid[row] << c.ord - 97
cost[row] << 1e15
if grid[row][-1] == 0
starts << [row, col]
end
end
col += 1
end
row += 1
col = 0
end
def min_hash(hash)
min_key = nil
min_val = 1e16
hash.each do |k, v|
if min_val > v
min_key = k
min_val = v
end
end
min_key
end
def neighbours(grid, row, col)
res = [nil, nil, nil, nil] # N, W, S, E
if col > 0
unless grid[row][col - 1] - 1 > grid[row][col]
res[1] = 1
end
end
if col < grid[0].length - 1 # s
unless grid[row][col + 1] - 1 > grid[row][col]
res[3] = 1
end
end
if row > 0
unless grid[row - 1][col] - 1 > grid[row][col]
res[0] = 1
end
end
if row < grid.length - 1 # e
unless grid[row + 1][col] - 1 > grid[row][col]
res[2] = 1
end
end
res
end
minimum_dist = 1e15
starts.each do |start|
row = start[0]
col = start[1]
cost[row][col] = 1
unvisited = {}
unvisited[row.to_s + "_" + col.to_s] = 0
visited = []
until dest == [row, col] or unvisited.size == 0
neigh = neighbours grid, row, col # N, W, S, E
neigh.each_with_index do |elem, i|
unless elem.nil?
dest_row = row
dest_col = col
dest_row = row - 1 if i == 0
dest_col = col - 1 if i == 1
dest_row = row + 1 if i == 2
dest_col = col + 1 if i == 3
unless visited.include? [dest_row, dest_col]
unvisited[dest_row.to_s + "_" + dest_col.to_s] = 1e15 if unvisited[dest_row.to_s + "_" + dest_col.to_s].nil?
previous_cost = unvisited[dest_row.to_s + "_" + dest_col.to_s]
current_cost = unvisited[row.to_s + "_" + col.to_s]
unvisited[dest_row.to_s + "_" + dest_col.to_s] = current_cost + 1 if current_cost < previous_cost
if dest == [dest_row, dest_col]
puts "path to dest with cost #{unvisited[dest_row.to_s + "_" + dest_col.to_s]}"
end
end
end
end
visited << [row, col]
unvisited.reject! do |k, v|
if k == (row.to_s + "_" + col.to_s)
cost[row][col] = v
true
else
false
end
end
next_ = min_hash(unvisited)
if next_ # will be nil if we start in an inescapable lake
res = next_.split "_"
new_row = res[0].to_i
new_col = res[1].to_i
if dest == [new_row, new_col]
cost[dest[0]][dest[1]] = unvisited[new_row.to_s + "_" + new_col.to_s]
end
row = new_row
col = new_col
else
cost[dest[0]][dest[1]] = 1e15
end
end
if cost[dest[0]][dest[1]] < minimum_dist
minimum_dist = cost[dest[0]][dest[1]]
end
cost.each do |row|
row.each_with_index do |elem, col|
row[col] = 1e15
end
end
end
puts minimum_dist