CLOSE_TO_OPEN = { ']'=>'[', '}'=>'{', ')'=>'(' }
def valid?(str)
str.each_char.with_object([]) do |c,stack|
case c
when '[', '{', '('
stack << c
when ']', '}', ')'
return false unless stack.pop == CLOSE_TO_OPEN[c]
end
end.empty?
end
valid? "[a]{b[c{d}e]fg}" #=> true
valid? "[a]{b[c{d]e}fg}" #=> false
Поведение метода можно увидеть, добавив несколько puts
операторов.
def valid?(str)
str.each_char.with_object([]) do |c,stack|
puts "c=#{c}, stack=#{stack}"
case c
when '[', '{', '('
stack << c
puts " stack after 'stack << #{c}' = #{stack}"
when ']', '}', ')'
print " stack.pop (#{stack.last||'nil'})==CLOSE_TO_OPEN[#{c}] " +
"(#{CLOSE_TO_OPEN[c]})=>"
puts stack.last == CLOSE_TO_OPEN[c] ? "true, so continue" :
"false, so return false"
return false unless stack.pop == CLOSE_TO_OPEN[c]
end
end.tap { |stack| puts "At end, '#{stack}.empty?` (#{stack.empty?})" }.empty?
end
valid? "[a]{b[c{d}e]fg}"
c=[, stack=[]
stack after 'stack << [' = ["["]
c=a, stack=["["]
c=], stack=["["]
stack.pop ([)==CLOSE_TO_OPEN[]] ([)=>true, so continue
c={, stack=[]
stack after 'stack << {' = ["{"]
c=b, stack=["{"]
c=[, stack=["{"]
stack after 'stack << [' = ["{", "["]
c=c, stack=["{", "["]
c={, stack=["{", "["]
stack after 'stack << {' = ["{", "[", "{"]
c=d, stack=["{", "[", "{"]
c=}, stack=["{", "[", "{"]
stack.pop ({)==CLOSE_TO_OPEN[}] ({)=>true, so continue
c=e, stack=["{", "["]
c=], stack=["{", "["]
stack.pop ([)==CLOSE_TO_OPEN[]] ([)=>true, so continue
c=f, stack=["{"]
c=g, stack=["{"]
c=}, stack=["{"]
stack.pop ({)==CLOSE_TO_OPEN[}] ({)=>true, so continue
At end, '[].empty?` (true)
#=> true
valid? "[a]{b[c{d]e}fg}"
c=[, stack=[]
stack after 'stack << [' = ["["]
c=a, stack=["["]
c=], stack=["["]
stack.pop ([)==CLOSE_TO_OPEN[]] ([)=>true, so continue
c={, stack=[]
stack after 'stack << {' = ["{"]
c=b, stack=["{"]
c=[, stack=["{"]
stack after 'stack << [' = ["{", "["]
c=c, stack=["{", "["]
c={, stack=["{", "["]
stack after 'stack << {' = ["{", "[", "{"]
c=d, stack=["{", "[", "{"]
c=], stack=["{", "[", "{"]
stack.pop ({)==CLOSE_TO_OPEN[]] ([)=>false, so return false
#=> false