[2022][ruby][12.x] refactoring

pull/1/head
Alpha Chen 2 years ago
parent 220c8853de
commit c3c34b998c
Signed by: alpha
SSH Key Fingerprint: SHA256:3fOT8fiYQG/aK9ntivV3Bqtg8AYQ7q4nV6ZgihOA20g

@ -1,51 +1,49 @@
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
class HeightMap class HeightMap
NEIGHBORS = [[0, -1], [-1, 0], [0, 1], [1, 0]]
def initialize(heights) def initialize(heights)
@heights = heights @heights = heights
end end
def shortest(from:, to:, &cond) def shortest(from:, to:, &cond)
queue = [from] frontier = [from]
visited = { from => 0 } visited = { from => 0 }
until queue.empty? || to.any? { visited.has_key?(_1) } until frontier.empty? || to.any? { visited.has_key?(_1) }
current = queue.shift current = frontier.shift
moves = visited.fetch(current)
NEIGHBORS.each do |delta|
neighbors = [ candidate = current.zip(delta).map { _1 + _2 }
[-1, 0],
[ 1, 0], next if visited.has_key?(candidate)
[ 0, -1], next unless cand_height = @heights[candidate]
[ 0, 1], next unless cond.(@heights.fetch(current), cand_height)
].map { current.zip(_1).map {|a,b| a + b } }
.select { @heights.has_key?(_1) } visited[candidate] = visited.fetch(current) + 1
.reject { visited.has_key?(_1) } frontier << candidate
.select { cond.([@heights.fetch(current), @heights.fetch(_1)]) }
neighbors.each do |y,x|
visited[[y,x]] = moves + 1
queue << [y,x]
end end
queue.sort_by { visited.fetch(_1) } frontier.sort_by { visited.fetch(_1) }
end end
visited.find {|k,v| to.include?(k) }.last visited.find {|k,v| to.include?(k) }.last
end end
end end
heights = ARGF.read.lines(chomp: true).map(&:chars)
.flat_map.with_index {|row,y|
row.map.with_index {|height,x| [[y, x], height] }
}.to_h
s, e = heights.invert.values_at(?S, ?E) s, e = heights.invert.values_at(?S, ?E)
heights[s] = ?a heights[s] = ?a
heights[e] = ?z heights[e] = ?z
hm = HeightMap.new(heights) hm = HeightMap.new(heights)
# part one
p hm.shortest(from: s, to: [e]) { _1.ord + 1 >= _2.ord } p hm.shortest(from: s, to: [e]) { _1.ord + 1 >= _2.ord }
# part two
as = heights.select { _2 == ?a }.map(&:first) as = heights.select { _2 == ?a }.map(&:first)
p hm.shortest(from: e, to: as) { _1.ord - 1 <= _2.ord } p hm.shortest(from: e, to: as) { _1.ord - 1 <= _2.ord }

Loading…
Cancel
Save