【问题标题】:Ruby Anagram Using String#sumRuby Anagram 使用字符串#sum
【发布时间】:2012-03-20 00:55:07
【问题描述】:

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

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

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

我想尝试找出一些基于使用sum 来确定字谜的方法。例如,“cars”和“scar”是字谜,它们的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']。我认为我缺少的是将其转换为预期的输出格式。

【问题讨论】:

    标签: ruby anagram


    【解决方案1】:

    很遗憾,我认为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"]] 
    

    【讨论】:

    • 这似乎是普遍接受的解决方案,并且有充分的理由。乍一看,当我开始处理这个问题时,我认为 sum 似乎可能是攻击它的另一种方式。我最初的解决方案不像你的那样雄辩,但它使用了相同的 word.chars.sort 想法。只是想保持新鲜:)
    • 我也确实提交了我的 gisted 解决方案,它通过了他们在 autograder 中使用的规范,就像我原来的解决方案一样。我重新提交了原始解决方案,以便将正确的实现存档。尝试总是很有趣。
    【解决方案2】:
    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】:

      实际上,我认为您可以将 sum 用于字谜测试,但不能将字符的序数本身相加,而是像这样:

      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 的数字,每个数字位置代表一个不同的字符。 N 是输入集中最长单词的长度。

      【讨论】:

      • 使用下面的 zaa 和 yab 的 Andy Lindemans 示例对此进行测试会产生正确的功能,即它们没有组合在一起。我将您添加到我对 Alex D 的评论中链接的要点中。
      【解决方案4】:

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

      如果您使用不同的算法来组合字符代码,则将单词错误识别为“字谜”的可能性会大大降低,但仍不为零。基本上,您需要某种散列算法,但具有散列值的 order 属性无关紧要。也许将每个字符映射到一个不同的随机位串,然后对字符串中每个字符的位串求和?

      这样,任何两个非字谜给你误报的机会大约是2 ** bitstring_length

      【讨论】:

      猜你喜欢
      • 2017-07-18
      • 2016-03-29
      • 1970-01-01
      • 2019-08-15
      • 2018-02-16
      • 2015-02-08
      • 2016-02-20
      • 2019-05-21
      • 2016-01-05
      相关资源
      最近更新 更多