[2022][ruby][12.x] refactored
diff --git a/2022/ruby/day_12.rb b/2022/ruby/day_12.rb
index 201c798..3cda8a8 100644
--- a/2022/ruby/day_12.rb
+++ b/2022/ruby/day_12.rb
@@ -1,69 +1,50 @@
-height_map = ARGF.read.lines(chomp: true).map(&:chars)
+heights = ARGF.read.lines(chomp: true).map(&:chars)
.each.with_index.with_object({}) do |(row,y),map|
row.each.with_index do |height,x|
map[[y,x]] = height
end
end
-s, e = height_map.invert.values_at(?S, ?E)
-height_map[s] = ?a
-height_map[e] = ?z
-
-# part one
-# queue = [s]
-# visited = { s => 0 }
-
-# until visited.has_key?(e)
-# current = queue.shift
-# moves = visited.fetch(current)
-
-# neighbors = [
-# [-1, 0],
-# [ 1, 0],
-# [ 0, -1],
-# [ 0, 1],
-# ].map { current.zip(_1).map {|a,b| a + b } }
-# .select { height_map.has_key?(_1) }
-# .reject { visited.has_key?(_1) }
-# .select { height_map.fetch(_1).ord - 1 <= height_map.fetch(current).ord }
-
-# neighbors.each do |y,x|
-# visited[[y,x]] = moves + 1
-# queue << [y,x]
-# end
-
-# queue.sort_by { visited.fetch(_1) }
-# end
-
-# p visited.fetch(e)
-
-# part two
-queue = [e]
-visited = { e => 0 }
-
-loop do
- current = queue.shift
- moves = visited.fetch(current)
+class HeightMap
+ def initialize(heights)
+ @heights = heights
+ end
- neighbors = [
- [-1, 0],
- [ 1, 0],
- [ 0, -1],
- [ 0, 1],
- ].map { current.zip(_1).map {|a,b| a + b } }
- .select { height_map.has_key?(_1) }
- .reject { visited.has_key?(_1) }
- .select { height_map.fetch(current).ord <= height_map.fetch(_1).ord + 1 }
+ def shortest(from:, to:)
+ queue = [from]
+ visited = { from => 0 }
+
+ until queue.empty? || visited.has_key?(to)
+ current = queue.shift
+ moves = visited.fetch(current)
+
+ neighbors = [
+ [-1, 0],
+ [ 1, 0],
+ [ 0, -1],
+ [ 0, 1],
+ ].map { current.zip(_1).map {|a,b| a + b } }
+ .select { @heights.has_key?(_1) }
+ .reject { visited.has_key?(_1) }
+ .select { @heights.fetch(_1).ord - 1 <= @heights.fetch(current).ord }
+
+ neighbors.each do |y,x|
+ visited[[y,x]] = moves + 1
+ queue << [y,x]
+ end
+
+ queue.sort_by { visited.fetch(_1) }
+ end
- if a = neighbors.find { height_map.fetch(_1) == ?a }
- p moves + 1
- break
+ visited.fetch(to, nil)
end
+end
- neighbors.each do |y,x|
- visited[[y,x]] = moves + 1
- queue << [y,x]
- end
+s, e = heights.invert.values_at(?S, ?E)
+heights[s] = ?a
+heights[e] = ?z
- queue.sort_by { visited.fetch(_1) }
-end
+hm = HeightMap.new(heights)
+p hm.shortest(from: s, to: e)
+
+p heights.select { _2 == ?a }.map(&:first).map { hm.shortest(from: _1, to: e) }.compact.min