Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-core/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ruby 用于匹配两个字符串的模加扰优化代码_Ruby - Fatal编程技术网

Ruby 用于匹配两个字符串的模加扰优化代码

Ruby 用于匹配两个字符串的模加扰优化代码,ruby,Ruby,我正在尝试编写一个函数scramble(str1,str2),如果str1字符的一部分可以重新排列以匹配str2,则返回false。仅使用小写字母(a-z)。不包括标点符号或数字。例如: str1='rkqodlw';str2='world'应返回true str1='cedewaraaossoqyt';str2='codewars'应返回true str1='katas';str2='steak'应返回false 这是我的代码: def scramble(s1, s2) #sorts

我正在尝试编写一个函数
scramble(str1,str2)
,如果
str1
字符的一部分可以重新排列以匹配
str2
,则返回
false
。仅使用小写字母(a-z)。不包括标点符号或数字。例如:

  • str1='rkqodlw';str2='world'
    应返回
    true
  • str1='cedewaraaossoqyt';str2='codewars'
    应返回
    true
  • str1='katas';str2='steak'
    应返回
    false
这是我的代码:

def scramble(s1, s2)
  #sorts strings into arrays
  first = s1.split("").sort
  second = s2.split("").sort
  correctLetters = 0
  for i in 0...first.length
    #check for occurrences of first letter
    occurrencesFirst = first.count(s1[i])
    for j in 0...second.length
      #scan through second string
      occurrencesSecond = second.count(s2[j])
      #if letter to be tested is correct and occurrences of first less than occurrences of second
      #meaning word cannot be formed
      if (s2[j] == s1[i]) && occurrencesFirst < occurrencesSecond
        return false
      elsif s2[j] == s1[i]
        correctLetters += 1
      elsif first.count(s1[s2[j]]) == 0
        return false
      end
    end
  end
  if correctLetters == 0
    return false
  end
  return true
end
def加扰(s1、s2)
#将字符串排序为数组
first=s1.split(“”)。sort
秒=s2.split(“”)排序
更正字母=0
对于0中的i…第一个长度
#检查是否出现第一个字母
发生率first=first.count(s1[i])
对于0…秒长度的j
#扫描第二个字符串
发生率秒=秒计数(s2[j])
#如果待测字母正确且第一个字母的出现次数少于第二个字母的出现次数
#这个词的意思是不能形成的
如果(s2[j]==s1[i])&&occurrencesFirst

我需要帮助优化此代码。请给我一些建议。

这里有一种高效的、类似Ruby的方法

代码

def scramble(str1, str2)
  h1 = char_counts(str1)
  h2 = char_counts(str2)
  h2.all? { |ch, nbr| nbr <= h1[ch] }
end

def char_counts(str)
  str.each_char.with_object(Hash.new(0)) { |ch, h| h[ch] += 1 }
end
def scramble(str1, str2)
  str2.chars.difference(str1.chars).empty?
end

class Array
  def difference(other)
    h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
    reject { |e| h[e] > 0 && h[e] -= 1 }
  end
end
解释

这三个步骤如下

str1 = 'abecacdeba'
str2 = 'abceae'

h1 = char_counts(str1)
  #=> {"a"=>3, "b"=>2, "e"=>2, "c"=>2, "d"=>1}
h2 = char_counts(str2)
  #=> {"a"=>2, "b"=>1, "c"=>1, "e"=>2}
h2.all? { |ch, nbr| nbr <= h1[ch] }
  #=> true
def char_counts(str)
  h = {}
  str.each_char do |ch|
    h[ch] = 0 unless h.key?(ch) # instead of Hash.new(0)
    h[ch] = h[c] + 1            # instead of h[c][ += 1
  end
  h                             # no need for this if use `each_with_object`
end
然后我们会发现
1true
但是
2false
,因此该方法将返回
false
。第二个比较是
2单向比较:

def scramble(s1,s2)
  s2.chars.uniq.all? { |c| s1.count(c) >= s2.count(c) }
end
另一种方式:

def scramble(s1,s2)
  pool = s1.chars.group_by(&:itself)
  s2.chars.all? { |c| pool[c]&.pop }
end
还有一个:

def scramble(s1,s2)
  ('a'..'z').all? { |c| s1.count(c) >= s2.count(c) }
end
由于这似乎是,我提交了我的前两个那里。两个都被接受了,第一个稍微快一点。然后我看到了其他人的解决方案,看到有人在使用
('a'..'z')
,而且速度很快,所以我把它包括在这里

codewars的“性能测试”没有明确显示,但它们都有大约45000个字母长。因此,我对这些解决方案以及Cary(您的解决方案太慢,无法包含在内)的字母表进行了基准测试,重复的字母表长度大约为100次:

这个故事的寓意是什么<代码>字符串#计数
在这里很快。就像,快得离谱。几乎难以置信的快(实际上我不得不运行额外的测试来相信它)。它以每秒19亿个字母的速度计算(100乘以26个字母乘以2个约45000个字母的字符串,全部在0.12秒内)。请注意,与我自己的第一个解决方案的不同之处在于,我使用了
s2.chars.uniq
,这将时间从0.12秒增加到了0.81秒。也就是说,通过一个字符串进行两次计数所需的时间大约是52次计数所需时间的六倍。计数速度大约快150倍。我确实希望它会非常快,因为它可能只是使用C代码(edit:)搜索字节数组中的一个字节,但这种速度仍然让我感到惊讶

代码:

需要“基准测试”
def加扰stefan1(s1、s2)
s2.chars.uniq.all?{| c | s1.count(c)>=s2.count(c)}
结束
def加扰stefan2(s1、s2)
pool=s1.chars.group_by(&:自身)
s2.chars.all?{| c | pool[c]&.pop}
结束
def加扰_其他(s1、s2)
('a'…'z')。好吗?{| c | s1.count(c)>=s2.count(c)}
结束
def扰码卡1(str1、str2)
h1=字符计数(str1)
h2=字符计数(str2)
好吗?{| ch,nbr | nbr 0&&h[e]=1}
结束
结束
Benchmark.bm do|x|
n=100
s1=('a'..'z')。to_a*(45000/26))。shuffle.join
s2=s1.chars.shuffle.join
x、 报告('stefan1'){n.times{scramble_stefan1(s1,s2)}
x、 报告('stefan2'){n.times{scramble_stefan2(s1,s2)}
x、 报告('Other'){n.times{scramble_Other(s1,s2)}
x、 报告('Cary 1'){n.times{scramble_cary1(s1,s2)}
x、 报告('Cary 2'){n.times{scramble_cary2(s1,s2)}
结束

非常感谢您!
def scramble(s1,s2)
  s2.chars.uniq.all? { |c| s1.count(c) >= s2.count(c) }
end
def scramble(s1,s2)
  pool = s1.chars.group_by(&:itself)
  s2.chars.all? { |c| pool[c]&.pop }
end
def scramble(s1,s2)
  ('a'..'z').all? { |c| s1.count(c) >= s2.count(c) }
end
               user     system      total        real
Stefan 1   0.812000   0.000000   0.812000 (  0.811765)
Stefan 2   2.141000   0.000000   2.141000 (  2.127585)
Other      0.125000   0.000000   0.125000 (  0.122248)
Cary 1     2.562000   0.000000   2.562000 (  2.575366)
Cary 2     3.094000   0.000000   3.094000 (  3.106834)
require 'benchmark'

def scramble_stefan1(s1,s2)
  s2.chars.uniq.all? { |c| s1.count(c) >= s2.count(c) }
end

def scramble_stefan2(s1,s2)
  pool = s1.chars.group_by(&:itself)
  s2.chars.all? { |c| pool[c]&.pop }
end

def scramble_other(s1,s2)
  ('a'..'z').all? { |c| s1.count(c) >= s2.count(c) }
end

def scramble_cary1(str1, str2)
  h1 = char_counts(str1)
  h2 = char_counts(str2)
  h2.all? { |ch, nbr| nbr <= h1[ch] }
end
def char_counts(str)
  str.each_char.with_object(Hash.new(0)) { |ch, h| h[ch] += 1 }
end

def scramble_cary2(str1, str2)
  str2.chars.difference(str1.chars).empty?
end
class Array
  def difference(other)
    h = other.each_with_object(Hash.new(0)) { |e,h| h[e] += 1 }
    reject { |e| h[e] > 0 && h[e] -= 1 }
  end
end

Benchmark.bmbm do |x|
  n = 100
  s1 = (('a'..'z').to_a * (45000 / 26)).shuffle.join
  s2 = s1.chars.shuffle.join
  x.report('Stefan 1') { n.times { scramble_stefan1(s1, s2) } }
  x.report('Stefan 2') { n.times { scramble_stefan2(s1, s2) } }
  x.report('Other') { n.times { scramble_other(s1, s2) } }
  x.report('Cary 1') { n.times { scramble_cary1(s1, s2) } }
  x.report('Cary 2') { n.times { scramble_cary2(s1, s2) } }
end