我已经解决了一个问题,要求你编写一个方法来确定所提供的数组中的单词是字谜,并将字谜分组到输出中的子数组中。
我已经使用了一种典型的方式解决了这个问题,即通过对单词进行排序并根据排序的字符将它们分组为哈希值。
当我最初开始寻找一种方法时,我注意到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']。我认为我缺少的是将其转换为预期的输出格式。
答案 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
是输入集中最长单词的长度。