parent
220c8853de
commit
c3c34b998c
@ -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…
Reference in new issue