【问题标题】:How to create a method that checks if string1 can be rearranged to equal string2?如何创建一个方法来检查 string1 是否可以重新排列为等于 string2?
【发布时间】:2015-02-25 14:50:45
【问题描述】:

我尝试编写一个方法,但是当我的代码没有运行并且我不确定为什么时。

str1 = "cored"
str2 = "coder"

def StringScramble(str1,str2)

  numCombos = str1.length.downto(1).inject(:*)
  arr = []

  until arr.length == numCombos
    shuffled = str1.split('').join
    unless arr.include?(shuffled) 
      arr << shuffled 
    end
  end

  if arr.include?(str1)
    return true
  else 
    return false
  end

end

【问题讨论】:

    标签: ruby


    【解决方案1】:

    更新:正如@eugen 在评论中指出的那样,有一种更有效的方法:

    str1.chars.sort == str2.chars.sort # => true
    

    原答案:

    str1.chars.permutation.include?(str2.chars) # => true
    

    【讨论】:

    • 哇,简单多了。凡事都有方法。谢谢!
    • 生成所有排列是多余的。 str1.chars.sort == str2.chars.sort 应该更快。
    • 对于像“isitananagram”这样的较长字符串,排列需要太多时间
    • @eugen 真的!根据您的评论更新了我的答案,这要好得多。
    • 我喜欢两件事:解决方案的简单性和解决问题的简单方法。
    【解决方案2】:

    最有效的方法?

    比较排序的字符串当然是最简单的方法,但如果效率是最重要的,你能做得更好吗?上个月@raph 发布了一个comment,它提出了一种对我来说听起来不错的方法。我打算将它与标准测试进行基准测试,但一直没有解决。我回答的目的是将建议的方法与标准方法进行基准测试。

    挑战者

    这个想法是为其中一个字符串中的字符创建一个计数哈希h,以便h['c'] 等于'c' 在字符串中出现的次数。然后一个遍历第二个字符串的字符。假设'c' 是这些字符之一。然后false方法返回h.key?('c') =&gt; false或h['c'] == 0(也可以写成h['c'].to_i == 0,如nil.to_i =&gt; 0);否则,将根据散列检查第二个字符串的下一个字符。假设字符串长度相等,当且仅当在检查完第二个字符串的所有字符后没有返回 false 时,它们才是彼此的字谜。为两个字符串中较短的一个创建哈希可能会提供进一步的改进。这是我的方法代码:

    def hcompare(s1,s2)
      return false unless s1.size == s2.size
      # set `ss` to the shorter string, `sl` to the other.
      ss, sl = (s1.size < s2.size) ? [s1, s2] : [s2, s1]    
      # create hash `h` with letter counts for the shorter string:
      h = ss.chars.each_with_object(Hash.new(0)) { |c,h| h[c] += 1}    
      #decrement counts in `h` for characters in `sl`
      sl.each_char { |c| return false if h[c].to_i == 0; h[c] -= 1 }    
      true
    end
    

    现任

    def scompare(s1,s2)
      s1.chars.sort == s2.chars.sort
    end
    

    帮助者

    methods = [:scompare, :hcompare]
    
    def compute(m,s1,s2)
      send(m,s1,s2)
    end
    
    def shuffle_chars(s)
      s.chars.shuffle.join
    end
    

    测试数据

    reps = 20
    ch = [*'b'..'z']
    

    基准

    require 'benchmark'
    
    [50000, 100000, 500000].each do |n|
      t1 = Array.new(reps) { (Array.new(n) {ch.sample(1) }).join}
      test_strings = { true=>t1.zip(t1.map {|s| shuffle_chars(s)})}
      test_strings[false]  = t1.zip(t1.map {|t| shuffle_chars((t[1..-1] << 'a'))})
      puts "\nString length #{n}, #{reps} repetitions"
      [true, false].each do |same|
        puts "\nReturn #{same} "
        Benchmark.bm(10) do |bm|
          methods.each do |m|
            bm.report m.to_s do
              test_strings[same].each { |s1,s2| compute(m,s1,s2) }
            end
          end
        end  
      end
    end
    

    进行的比较

    我比较了scompare(使用sort)和hcompare(使用hash)这两种方法,针对三个字符串长度执行基准测试:50,000、100,000 和 500,000 个字符。对于每个字符串长度,我通过从[*('b'..'z')] 中随机选择每个字符来创建两个字符串中的第一个。然后我创建了两个字符串与第一个进行比较。一个只是对第一个字符串的字符进行混洗,因此当比较这两个字符串时,这些方法将返回true。在第二种情况下,我做了同样的事情,只是我用'a' 替换了一个随机选择的字符,所以这些方法将返回false。这两种情况在下面标记为true 和false。

    结果

    String length 50000, 20 repetitions
    
    Return true 
                     user     system      total        real
    scompare     0.620000   0.010000   0.630000 (  0.625711)
    hcompare     0.840000   0.010000   0.850000 (  0.845548)
    
    Return false 
                     user     system      total        real
    scompare     0.530000   0.000000   0.530000 (  0.532666)
    hcompare     1.370000   0.000000   1.370000 (  1.366293)
    
    String length 100000, 20 repetitions
    
    Return true 
                     user     system      total        real
    scompare     1.420000   0.100000   1.520000 (  1.516580)
    hcompare     2.280000   0.010000   2.290000 (  2.284189)
    
    Return false 
                     user     system      total        real
    scompare     1.020000   0.010000   1.030000 (  1.034887)
    hcompare     1.960000   0.000000   1.960000 (  1.962655)
    
    String length 500000, 20 repetitions
    
    Return true 
                     user     system      total        real
    scompare    10.310000   0.540000  10.850000 ( 10.850988)
    hcompare     9.960000   0.180000  10.140000 ( 10.153366)
    
    Return false 
                     user     system      total        real
    scompare     8.120000   0.570000   8.690000 (  8.687847)
    hcompare     9.160000   0.030000   9.190000 (  9.189997)
    

    结论

    如您所见,使用计数哈希的方法仅在一种true 情况下(n =&gt; 500,000)优于使用sort。即使在那里,胜利的幅度也很小,比大多数其他基准比较中的相对差异要小得多,标准方法在这些比较中获胜。虽然哈希计数方法可能在不同的测试中表现更好,但似乎传统的排序方法很难被击败。

    这个答案有趣吗?我不确定,但由于在看到结果之前我已经完成了大部分工作(我预计这将有利于计数哈希),所以我决定继续进行。

    【讨论】:

    • 加一以保证完整性。
    猜你喜欢
    • 1970-01-01
    • 2021-08-22
    • 2018-05-19
    • 2018-08-09
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-08-23
    相关资源
    最近更新 更多