I will use the term enclosures to refer to parentheses ('(' and ')'), brackets ('[' and ']') and braces ('{' and '}'). A string of enclosures is balanced if:
- each left parenthesis has a matching right parenthesis, and vice-versa;
- each left bracket has a matching right bracket, and vice-versa;
- each left brace has a matching right brace, and vice-versa; and
- all matched pairs are well-nested in the sense every each matched pair must be separated by a string comprised of zero or more matched pairs.
For example, '([{}])' is well-nested whereas '([{]})' is not, as the string separating the matched pair, '[' and ]', namely '{', is not a matched pair.
If, in the code in the question, the length of the string is even stack is initialized to an empty array that is never changed, so the return value stack.empty? will always be true. For example, balanced?(')[') #=> true. You need something like the following.
RIGHT_ENCLOSURE_PAIRS = { '}'=>'{', ']'=>'[', ')'=>'(' }
RIGHT_ENCLOSURES = RIGHT_ENCLOSURE_PAIRS.keys
def balanced?(str)
stack = []
str.each_char do |c|
if RIGHT_ENCLOSURES.include?(c)
return false if stack.empty? || stack.last != RIGHT_ENCLOSURE_PAIRS[c]
stack.pop
else
stack << c
end
end
stack.empty?
end
balanced? '{}()[]' #=> true
balanced? '([{}])' #=> true
balanced? '([{}]{})' #=> true
balanced? '((([[[{{{}}}]]])))' #=> true
balanced? '{[]' #=> false
balanced? '{{(([[' #=> false
balanced? '{()[{]}(([]))' #=> false
I initially had the following guard clause as the first line of the method.
return false if str.length.odd?
After reflection, however, I removed it, as the time spent executing it unnecessarily for strings with even numbers of enclosures was probably much greater than the time saved for strings with odd numbers of enclosures.
I have not included puts statements such as puts "#{c} is an opening enclosure" as they would normally only be used for debugging, but they could of course be added if desired, in which case it might be more helpful to write
ENCLOSURE_TYPE = { '('=>'left parenthesis', ')'=>'right parenthesis',
'['=>'left bracket', ']'=>'right bracket',
'{'=>'left brace', '}'=>'right brace' }
puts "#{c} is a #{ENCLOSURE_TYPE[c]}"