From e12d4d7c63d913f73fdd33394ca998637e028e0e Mon Sep 17 00:00:00 2001 From: Alpha Chen Date: Sun, 11 Dec 2022 21:35:03 -0800 Subject: [PATCH] [2022][ruby][12.x] refactored --- 2022/ruby/day_12.rb | 97 ++++++++++++++++++--------------------------- 1 file changed, 39 insertions(+), 58 deletions(-) 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