|
|
@ -15,25 +15,29 @@ TURNS = {
|
|
|
|
Loop = Class.new(Exception)
|
|
|
|
Loop = Class.new(Exception)
|
|
|
|
|
|
|
|
|
|
|
|
def patrol(lab)
|
|
|
|
def patrol(lab)
|
|
|
|
|
|
|
|
return enum_for(__method__, lab) unless block_given?
|
|
|
|
|
|
|
|
|
|
|
|
start = lab.find { _2 == ?^ }.first
|
|
|
|
start = lab.find { _2 == ?^ }.first
|
|
|
|
path = [[start, [-1,0]]]
|
|
|
|
guard = [start, [-1,0]]
|
|
|
|
seen = path.to_set
|
|
|
|
seen = Set.new
|
|
|
|
|
|
|
|
|
|
|
|
loop do
|
|
|
|
loop do
|
|
|
|
pos, dir = path.last
|
|
|
|
pos, dir = guard
|
|
|
|
peek = pos.zip(dir).map {|i,di| i + di }
|
|
|
|
yield pos
|
|
|
|
|
|
|
|
|
|
|
|
return path unless lab.has_key?(peek)
|
|
|
|
peek = pos.zip(dir).map {|i,di| i + di }
|
|
|
|
|
|
|
|
return unless lab.has_key?(peek)
|
|
|
|
|
|
|
|
|
|
|
|
raise Loop if seen.include?([peek, dir])
|
|
|
|
raise Loop if seen.include?([peek, dir])
|
|
|
|
seen << [peek, dir]
|
|
|
|
seen << [peek, dir]
|
|
|
|
|
|
|
|
|
|
|
|
case lab.fetch(peek)
|
|
|
|
case lab.fetch(peek)
|
|
|
|
when ?., ?^
|
|
|
|
when ?., ?^
|
|
|
|
path << [peek, dir]
|
|
|
|
guard[0] = peek
|
|
|
|
when ?#
|
|
|
|
when ?#
|
|
|
|
path.last[1] = TURNS.fetch(dir)
|
|
|
|
guard[1] = TURNS.fetch(dir)
|
|
|
|
when nil
|
|
|
|
when nil
|
|
|
|
return path
|
|
|
|
return
|
|
|
|
else
|
|
|
|
else
|
|
|
|
fail
|
|
|
|
fail
|
|
|
|
end
|
|
|
|
end
|
|
|
@ -41,13 +45,13 @@ def patrol(lab)
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
def loop?(lab)
|
|
|
|
def loop?(lab)
|
|
|
|
patrol(lab)
|
|
|
|
patrol(lab).each {}
|
|
|
|
false
|
|
|
|
false
|
|
|
|
rescue Loop
|
|
|
|
rescue Loop
|
|
|
|
true
|
|
|
|
true
|
|
|
|
end
|
|
|
|
end
|
|
|
|
|
|
|
|
|
|
|
|
path = patrol(input).map(&:first).to_set
|
|
|
|
path = patrol(input).to_set
|
|
|
|
pp path.length
|
|
|
|
pp path.length
|
|
|
|
|
|
|
|
|
|
|
|
pp input
|
|
|
|
pp input
|
|
|
|