Ruby Anagram使用String#sum

时间:2012-03-01 14:16:19

标签: ruby anagram

我已经解决了一个问题,要求你编写一个方法来确定所提供的数组中的单词是字谜,并将字谜分组到输出中的子数组中。

我已经使用了一种典型的方式解决了这个问题,即通过对单词进行排序并根据排序的字符将它们分组为哈希值。

当我最初开始寻找一种方法时,我注意到String#sum存在,它将每个字符的序数加在一起。

我想尝试以某种方式确定基于使用sum的字谜。例如,“汽车”和“疤痕”是字谜,他们的sum是425。

如果输入%w[cars scar for four creams scream racs]预期输出(我已经使用哈希解决方案获得)是:[[cars, scar, racs],[for],[four],[creams,scream]]

似乎做了类似的事情:

input.each_with_object(Hash.new []) do |word, hash|
  hash[word.sum] += [word]
end

是要走的路,它会给你一个散列,其中键“425”的值是['cars','racs','scar']。我认为我缺少的是将其转换为预期的输出格式。

4 个答案:

答案 0 :(得分:17)

不幸的是,我认为String#sum不是解决此问题的有效方法。

考虑:

"zaa".sum # => 316
"yab".sum # => 316

相同的总和,但不是字谜。

相反,如何按字符的排序顺序对它们进行分组?

words = %w[cars scar for four creams scream racs]

anagrams = words.group_by { |word| word.chars.sort }.values
# => [["cars", "scar", "racs"], ["for"], ["four"], ["creams", "scream"]] 

答案 1 :(得分:1)

要获得所需的输出格式,您只需要hash.values。但请注意,仅使用单词中字符代码的总和可能会在某些输入上失败。当它们不是字谜时,两个字中的字符代码的总和可能是偶然的。

如果您使用不同的算法来组合字符代码,则错误地将单词识别为“字谜”的可能性可以低得多,但仍然不为零。基本上你需要某种哈希算法,但是具有被散列的值的 order 并不重要的属性。也许将每个字符映射到不同的随机位串,并获取字符串中每个字符的位串总和?

这样,任何两个非字母组合给你假阳性的几率约为2 ** bitstring_length

答案 2 :(得分:1)

words = %w[cars scar for four creams scream racs]
res={}

words.each do |word|
  key=word.split('').sort.join
  res[key] ||= []
  res[key] << word
end

p res.values


[["cars", "scar", "racs"], ["for"], ["four"],["creams", "scream"]]

答案 3 :(得分:1)

实际上,我认为你可以使用总和进行字谜测试,但不能自己总结字符的序数,而是这样的事情:

words = %w[cars scar for four creams scream racs]
# get the length of the longest word:
maxlen = words.map(&:length).max
# => 6 
words.group_by{|word|
  word.bytes.map{|b|
    maxlen ** (b-'a'.ord)
  }.inject(:+)
}
# => {118486616113189=>["cars", "scar", "racs"], 17005023616608=>["for"], 3673163463679584=>["four"], 118488792896821=>["creams", "scream"]} 

不确定这是否100%正确,但我认为逻辑是正确的。

这个想法是将每个单词映射到一个基于N的数字,每个数字位置代表一个不同的char。 N是输入集中最长单词的长度。