This method is supposed to take a string and detect if the brackets '(' '{' '[' in the string are closing properly with the corresponding (opposite) brackets.
First, is there a more elegant, compact way to write this bit without using all the "or"s (||):
split_array.each do |i|
if (i == "{" || i == "(" || i == "[")
left.push(i)
else (i == "}" || i == ")" || i == "]")
right.push(i)
end
end
My second question is, is this code terrible (see below)? It seems I should be able to write this in way fewer lines, but logically, I haven't come up with another solution (yet.) The code works for most tests, but it returns false for this test (see all driver tests at bottom): p valid_string?("[ ( text ) {} ]") == true
Any critique would be greatly appreciated! (also, if there is a better section to post this, please let me know) Thanks!
def valid_string?(string)
opposites = { "[" => "]", "{" => "}", "(" => ")", "]" => "[", "}" => "{", ")" => "(" }
left = Array.new
right = Array.new
return_val = true
split_array = string.split(//)
split_array.delete_if { |e| e.match(/\s/) }
split_array.each do |i|
if (i == "{" || i == "(" || i == "[")
left.push(i)
else (i == "}" || i == ")" || i == "]")
right.push(i)
end
end
# p left
# p right
left.each_index do |i|
if left[i] != opposites[right[i]]
return_val = false
end
end
return_val
end
p valid_string?("[ ] } ]") == false
p valid_string?("[ ]") == true
p valid_string?("[ ") == false
p valid_string?("[ ( text ) {} ]") == true
p valid_string?("[ ( text { ) } ]") == false
p valid_string?("[ (] {}") == false
p valid_string?("[ ( ) ") == false
------- Updated: After trying some different approaches, my refactor is this: -----------
def valid_string?(str)
mirrored = { "[" => "]", "{" => "}", "(" => ")" }
open_brackets = Array.new
split_str_array = str.split("")
split_str_array.each do |bracket|
if bracket.match(/[\[|\{|\(]/) then open_brackets.push(bracket)
elsif bracket.match(/[\]|\}|\)]/)
return false if mirrored[open_brackets.pop] != bracket
end
end
open_brackets.empty?
end
My approach is as below :
def valid_string?(string)
open_paren = ['[','{','(']
close_paren = [']','}',')']
open_close_hash = {"]"=>"[", "}"=>"{", ")"=>"("}
stack = []
regex = Regexp.union(close_paren+open_paren)
string.scan(regex).each do |char|
if open_paren.include? char
stack.push(char)
elsif close_paren.include? char
pop_val = stack.pop
return false if pop_val != open_close_hash[char]
end
end
open_paren.none? { |paren| stack.include? paren }
end
valid_string?("[ ] } ]") # => false
valid_string?("[ ]") # => true
valid_string?("[ ") # => false
valid_string?("[ (] {}") # => false
valid_string?("[ ( ) ") # => false
valid_string?("[ ( text { ) } ]") # => false
valid_string?("[ ( text ) {} ]") # => true
S
.'('
or '{'
or '['
) then push it to stack.')'
or '}'
or ']'
) then pop from stack and if the popped character is the matching starting bracket then fine else parenthesis are not balanced.The shortest regex solution is probably:
def valid_string? orig
str = orig.dup
re = /\([^\[\](){}]*\)|\[[^\[\](){}]*\]|\{[^\[\](){}]*\}/
str[re] = '' while str[re]
!str[/[\[\](){}]/]
end
How about:
class Brackets
def self.paired?(s)
stack = []
brackets = { '{' => '}', '[' => ']', '(' => ')' }
s.each_char do |char|
if brackets.key?(char)
stack.push(char)
elsif brackets.values.include?(char)
return false if brackets.key(char) != stack.pop
end
end
stack.empty?
end
end
Brackets.paired?("[ ] } ]") # => false
Brackets.paired?("[ ]") # => true
Brackets.paired?("[ ") # => false
Brackets.paired?("[ (] {}") # => false
Brackets.paired?("[ ( ) ") # => false
Brackets.paired?("[ ( text { ) } ]") # => false
Brackets.paired?("[ ( text ) {} ]") # => true
This should provide the same functionality
def valid_string?(string)
#assume validity
@valid = true
#empty array will be populated inside the loop
@open_characters = []
#set up a hash to translate the open character to a closing character
translate_open_closed = {"{" => "}","["=>"]","("=>")"}
#create an array from the string loop through each item
string.split('').each do |e|
#adding it to the open_characters array if it is an opening character
@open_characters << e if e=~ /[\[\{\(]/
#if it is a closing character then translate the last open_character to
#a closing character and compare them to make sure characters are closed in order
#the result of this comparison is applied to the valid variable
@valid &= e == translate_open_closed[@open_characters.pop] if e=~ /[\]\}\)]/
end
#return validity and make sure all open characters have been matched
@valid &= @open_characters.empty?
end
You could also do this with inject but it would be a bit less transparent.
Another way:
s = str.gsub(/[^\{\}\[\]\(\)]/, '')
while s.gsub!(/\{\}|\[\]|\(\)/, ''); end
s.empty?
Ex 1
str = "(a ()bb [cc{cb (vv) x} c ]ss) "
s = str.gsub(/[^\{\}\[\]\(\)]/, '') #=> "(()[{()}])"
while s.gsub!(/\{\}|\[\]|\(\)/, '') do; end
s => "([{}])" => "([])" => "()" => "" gsub!() => nil
s.empty? #=> true
Ex 2
str = "(a ()bb [cc{cb (vv) x] c }ss) "
s = str.gsub(/[^\{\}\[\]\(\)]/, '') #=> "(()[{()]})"
while s.gsub!(/\{\}|\[\]|\(\)/, '') do; end
s => "([{]})" gsub!() => nil
s.empty? #=> false
I was given this as part of a simulated interview coding challenge. In my case, there was also a parens map passed in { "(" => ")", "[" => "]" }
, meaning types of parentheses could vary.
def balanced_parens(string, parens_map)
# where we throw opening parens
opening_parens = []
i = 0
while i < string.length
# if current index is opening paren add to array
if parens_map.keys.include? string[i]
opening_parens << string[i]
# if current index is closing paren, remove last item from opening_array
elsif parens_map.values.include? string[i]
popped_paren = opening_parens.pop
# checking that closing parens at current index is a match for last open parens in opening_array
return false if string[i] != parens_map[popped_paren]
end
i += 1
end
# if opening_parens array is empty, all parens have been matched (&& value = true)
opening_parens.empty?
end
def valid_string?(exp)
return false if exp.size % 2 != 0
curly = "{}"
square = "[]"
parenthesis = "()"
emptystr = ""
loop do
old_exp = exp
exp = exp.sub(curly, emptystr)
break if exp == emptystr
exp = exp.sub(square, emptystr)
break if exp == emptystr
exp = exp.sub(parenthesis, emptystr)
break if exp == emptystr || exp == old_exp
end
exp == emptystr
end
You can try this approach:
def balanced_brackets?(string)
# your code here
stack = []
opening_bracket = ['{','[', '(']
closing_bracket = ['}', ']', ')']
string.chars.each do |char|
if opening_bracket.include?(char)
stack << char
elsif closing_bracket.include?(char)
value = stack.pop
return false if opening_bracket.index(value) != closing_bracket.index(char)
end
end
stack.empty?
end
if you want to understand pseudo code try this link from coursera (starts at 0:56).
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.