【问题标题】:Ruby Koans Scoring ProjectRuby Koans 评分项目
【发布时间】:2012-07-22 19:49:41
【问题描述】:

我正在研究 Ruby Koans,但在弄清楚我编写的方法出了什么问题时遇到了一些麻烦。我在about_scoring_project.rb中,写了骰子游戏的得分方法:

def score(dice)
  return 0 if dice == []
  sum = 0
  rolls = dice.inject(Hash.new(0)) { |result, element| result[element] += 1; result; }
  rolls.each { |key, value| 
    # special condition for rolls of 1
    if key == 1  
      sum += 1000 | value -= 3 if value >= 3
      sum += 100*value
      next
    end
    sum += 100*key | value -= 3 if value >= 3
    sum += 50*value if key == 5 && value > 0
  }
  return sum
end

对于不熟悉练习的人:

Greed 是一款骰子游戏,您最多可以滚动五个骰子来累积 点。下面的“score”函数将用于计算 单掷骰子的分数。

贪婪滚动得分如下:

  • 一组三个1000分

  • 一组三个数字(除了一个)的价值是该数字的 100 倍。 (例如三个五是 500 分)。

  • 一个(不属于一组三个)值 100 分。

  • 五个(不属于一组三个)值 50 分。

  • 其他一切都值 0 分。

例子:

score([1,1,1,5,1]) => 1150 分 score([2,3,4,6,2]) => 0 分 score([3,4,5,3,3]) => 350 分 score([1,5,1,2,4]) => 250 分

下面的测试中给出了更多评分示例:

你的目标是编写 score 方法。

当我尝试运行文件中的最后一个测试时遇到了麻烦:assert_equal 550, score([5,5,5,5])

由于某种原因,我返回 551 而不是 550。感谢您的帮助!

【问题讨论】:

  • 我在那个测试中也遇到了麻烦。 ;)

标签: ruby


【解决方案1】:

这是我的方法:

def score(dice)
  # Count how many what
  clusters = dice.reduce(Hash.new(0)) {|hash, num| hash[num] += 1; hash }

  # Since 1's are special, handle them first
  ones = clusters.delete(1) || 0
  score = ones % 3 * 100 + ones / 3 * 1000

  # Then singular 5's
  score += clusters[5] % 3 * 50

  # Then the triples other than triple-one
  clusters.reduce(score) {|s, (num, count)| s + count / 3 * num * 100 }
end

【讨论】:

  • 虽然您的代码对 koans 成功,但它会失败(例如)[1,5,1,5,1]。通过简单地计算一个,假设任何三个都值 1000,而实际上,在这种情况下,它们每个值 100,所以答案是 400,但您的代码给出了 1100。
  • 规则没有规定一组三个必须是连续的。 :-)
【解决方案2】:

我的方法使用两个查找表 - 一个包含三人组的分数,另一个包含单人组的分数。我使用表格计算出每个数字的分数,并使用inject 累积总分:

def score(dice)
  triple_scores = [1000, 200, 300, 400, 500, 600]
  single_scores = [100, 0, 0, 0, 50, 0]
  (1..6).inject(0) do |score, number|
    count = dice.count(number)
    score += triple_scores[number - 1] * (count / 3)
    score += single_scores[number - 1] * (count % 3)
  end
end

【讨论】:

    【解决方案3】:

    这是因为您实际上是将| 运算符(按位或)的结果添加到总分中:

    sum += 100*key | value -= 3 if value >= 3 # This is 501 in your case
    

    证明:

    irb(main):004:0> value = 4
    => 4
    irb(main):005:0> 100 * 5 | value -= 3 # This should be read as (500) | 1 which is 501
    => 501
    

    所以改写成这样:

    if value >= 3
      sum += 100 * key
      value -= 3
    end
    

    【讨论】:

      【解决方案4】:

      我去了

      def score(dice)
        dice.uniq.map do |die|
          count = dice.count die
          if count > 2
            count -= 3
            die == 1 ? 1000 : 100 * die
          else 0
          end + case die
                when 1 then count * 100
                when 5 then count * 50
                else 0
                end
        end.inject(:+) || 0
      end
      

      【讨论】:

        【解决方案5】:

        我的做法是:

        def score(dice)
          calculator = ->(no, group_multipler, individual_multipler) { (no / 3 * group_multipler) + (no % 3 * individual_multipler) }
          dice.group_by {|i| i % 7 }.inject(0) do |total, (value, scores)|
            group_multipler, individual_multipler = case value
            when 1
              [1000, 100]
            when 5
              [500, 50]
            else 
              [value * 100, 0]
            end
            total += calculator.call(scores.size, group_multipler, individual_multipler)
          end
        end
        

        【讨论】:

          【解决方案6】:

          我的做法:

               def score(dice)
                  score = 0
                  score += dice.count(1) >= 3? (1000+ (dice.count(1) -3)*100): dice.count(1) * 100
                  score += dice.count(5) >= 3 ? (500 + (dice.count(5) -3)*50): dice.count(5) * 50
                 [2,3,4,6].each {|x| dice.count(x) >=3? score+= x*100:0}
                 return score
              end
          

          【讨论】:

            【解决方案7】:

            这是我的答案:

            def score(dice)
              frequency = dice.inject(Hash.new(0)) do |h, el|
                h[el] += 1
                h
              end
            
              score_triples = { 1 => 1000 }
              score_singles = { 1 => 100, 5 => 50 }
            
              score = 0
              frequency.each do |k, v|
                score += v / 3 * score_triples.fetch(k, 100 * k)
                score += v % 3 * score_singles.fetch(k, 0)
              end
              score
            end
            

            【讨论】:

              【解决方案8】:

              我的方法使用了整数除法和模除法:

              def score(dice)
                  points = 1000 * (dice.count(1) / 3)
                  points += 100 * (dice.count(1) % 3)
                  points += 50 * (dice.count(5) % 3)
                  (2..6).each do |i|
                      points += (100 * i) * (dice.count(i) / 3)
                  end
                  points
              end
              

              【讨论】:

              • 我认为这段代码会失败:[1, 2, 1, 2, 1, 2],分数应该是 1100,而实际上应该是 300。所有的计数都是计算某物出现的次数:# 如果一个块是给定,计算块 # 返回真值的元素数。 # # ary = [1, 2, 4, 2] # ary.count #=> 4 # ary.count(2) #=> 2 # ary.count { |x| x%2 == 0 } #=> 3
              【解决方案9】:

              这是我自己编写的第一段代码(当然,在 stackoverflow 的大量帮助下。)看了所有其他答案后,我意识到这特别过分,因为它适用于 9 数字骰子(确实存在吗?)

                def score(dice)
                  
                if dice.empty?
                  return 0
                end
              
                var_score = 0
              
                conteo = (0..9).to_a.each.map { |x| dice.count(x)} 
                
                #Evaluating 1
                if ( conteo[1] / 3 ) >= 0
                  multiplier1 = conteo[1]/3
                  var_score += multiplier1 * 1000
                end
              
                if ( conteo[1] % 3 ) != 0
                  var_score += (conteo[1] % 3)*100
                end
                
                #Evaluating 5
                if ( conteo[5] % 3 ) != 0
                  var_score += (conteo[5] % 3)* 50
                end
              
                #Evaluating numbers x 3    
                if (conteo[2..9].count { |x| x >= 3 }) > 0
                  triplets = conteo[2..9].map {|x| x / 3}
                  array_multiplicator = triplets.each_with_index.select {|num,index| (num > 0)}.map {|x| x[0]}
                  product_triplets = triplets.each_with_index.select {|num,index| (num > 0)}.map {|x| x[1]}.map {|x| (x+2)*100}
                  var_score += array_multiplicator.zip(product_triplets).map{|x| x.inject(&:*)}.sum
                end
              
                var_score
              end
              

              【讨论】:

                【解决方案10】:

                花了 29 行,但这是我的第一个 Ruby

                    def score(dice)
                      return 0 if dice == [] 
                      sums = Array.new  # To hold number of occurrences 1 - 6
                      for i in 0..6     # Initialize to 0... note [0] is not used 
                        sums[i] = 0
                      end
                      total = 0   # To hold total
                      dice.each do |dots|   # Number of dots showing on dice
                        sums[dots] += 1     # Increment the array members 1 - 6
                      end 
                        if sums[1] > 2 then # If 3 1's
                          total += 1000 
                          sums[1] -= 3   # Remove the 3 you took, in case there's more
                        end
                        if sums[2] > 2  then total += 200  # If 3 2's
                        end
                        if sums[3] > 2  then total += 300   #If 3 3's
                        end
                        if sums[4] > 2  then total += 400    #If 3 4's
                        end
                        if sums[5] > 2  then total += 500     #If 3 5's
                          sums[5] -= 3                        #Remove the 5's you took
                        end
                        if sums[6] > 2  then total += 600  #If 3 6's
                        end
                     total += (sums[1] * 100)   # If any ones are left
                     total += (sums[5] * 50)    # Same for fives
                     return total
                end
                

                【讨论】:

                  【解决方案11】:

                  这是我的解决方案。

                  def score(dice)
                      score = 0
                      # grab all the numbers and their amounts
                      number_amounts = dice.reduce(Hash.new(0)) { |hash, numb| hash[numb] += 1; hash }
                  
                      # iterate through each pair
                      number_amounts.each do |key, value|
                        # case with number 1
                        score += (value % 3) * 100 + value / 3 * 1000 if (key == 1)
                        # case with number 5
                        score += (value % 3) * 50 + value / 3 * key * 100 if (key == 5)
                        # all numbers except 1 and 5
                        score += (value / 3) * key * 100 if (key != 1 && key != 5)
                      end
                      score
                  end
                  

                  【讨论】:

                  • 请不要仅发布代码答案。请解释你的代码是做什么的。
                  • 知道了 Dan-Dev。添加了 cmets。我觉得现在看起来好多了。
                  【解决方案12】:
                      def score(dice)
                    # Set up rules Hash
                    rules = { 1 => {:triples => 1000, :singles => 100}, 5 => {:triples => 100, :singles => 50} }
                    [2,3,4,6].each {|i| rules[i] = {:triples => 100, :singles => 0} }
                    # Count all ocourencies
                    counts = dice.each_with_object(Hash.new(0)) {|e, h| h[e] += 1}
                  
                    #calculate total
                    total = 0
                    counts.each_pair{ | key, value | 
                      total += value >= 3? (rules[key][:triples]*key + (value -3)*rules[key][:singles]): value * rules[key][:singles]
                    }
                    return total
                  end
                  

                  【讨论】:

                    【解决方案13】:
                    def score(dice)
                        score = 0
                        dice.uniq.each do |number|
                            count = dice.count number
                            weight = if number == 1 then 10 else number end
                            if count >= 3
                                score += weight * 100
                                count -= 3
                            end
                            if count > 0 and number == 1 or number == 5
                                score += count * weight * 10
                            end
                        end
                        score
                    end
                    

                    【讨论】:

                      【解决方案14】:
                      def score(dice)
                          ones = fives = rest = 0
                      
                          one_count = dice.count(1)
                          if one_count > 2
                              ones = 1000
                              one_count -= 3
                          end
                          ones += one_count * 100
                      
                          five_count = dice.count(5)
                          if five_count > 2
                              fives = 500
                              five_count -= 3
                          end
                          fives += five_count * 50
                      
                          [2,3,4,6].each do |num|
                              if dice.count(num) > 2
                                  rest += num * 100
                              end
                          end
                      
                          return ones + fives + rest
                      end
                      

                      【讨论】:

                        猜你喜欢
                        • 1970-01-01
                        • 2011-01-22
                        • 1970-01-01
                        • 1970-01-01
                        • 2015-03-15
                        • 2012-06-13
                        • 1970-01-01
                        • 2012-10-29
                        • 2015-02-18
                        相关资源
                        最近更新 更多