簡體   English   中英

在 Ruby 中編寫“匹配平衡括號”程序的更好方法

[英]Better way to write “matching balanced parenthesis” program in Ruby

此方法應該采用一個字符串並檢測字符串中的括號 '(' '{' '[' 是否與相應的(相反的)括號正確關閉。

首先,是否有一種更優雅、更緊湊的方式來編寫這個位而不使用所有的“或”(||):

            split_array.each do |i| 
              if (i == "{" || i == "(" || i == "[")
                  left.push(i)
                else (i == "}" || i == ")" || i == "]")
                  right.push(i)
                end
             end

我的第二個問題是,這段代碼可怕嗎(見下文)? 似乎我應該能夠以更少的行數來編寫它,但從邏輯上講,我還沒有想出另一個解決方案(還)。該代碼適用於大多數測試,但此測試返回 false(請參閱所有驅動程序測試)底部): p valid_string?("[ ( text ) {} ]") == true

任何批評將不勝感激! (另外,如果有更好的部分可以發布此內容,請告訴我)謝謝!

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

-------更新:嘗試了一些不同的方法后,我的重構是這樣的: -----------

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 

我的方法如下:

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

算法 :

  1. 聲明一個字符堆棧S
  2. 現在遍歷表達式字符串 exp。
    • 如果當前字符是起始括號( '(''{''[' ),則將其壓入堆棧。
    • 如果當前字符是右括號( ')''}'']' ),則從堆棧中彈出,如果彈出的字符是匹配的起始括號,則很好,否則括號不平衡。
  3. 完全遍歷后,如果堆棧中還剩下一些起始括號,則“不平衡”

最短的正則表達式解決方案可能是:

def valid_string? orig
  str = orig.dup
  re = /\([^\[\](){}]*\)|\[[^\[\](){}]*\]|\{[^\[\](){}]*\}/
  str[re] = '' while str[re]
  !str[/[\[\](){}]/]
end

怎么樣:

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

這應該提供相同的功能

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

你也可以用注入來做到這一點,但它會有點不透明。

其它的辦法:

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

這是模擬面試編碼挑戰的一部分。 在我的例子中,還有一個括號映射傳入{ "(" => ")", "[" => "]" } ,這意味着括號的類型可能會有所不同。

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

你可以試試這個方法:

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

如果您想了解偽代碼,請嘗試來自coursera 的此鏈接(從 0:56 開始)。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM