Ruby Greed Koan - 我怎样才能改善我的if / then汤?

时间:2011-01-20 16:46:19

标签: ruby

我正在研究Ruby Koans,以便尝试学习Ruby,到目前为止,这非常好。我已经得到了贪婪的koan,在写这篇文章的时候是183.我有一个有效的解决方案,但我觉得我只拼凑了一堆if / then逻辑而且我不是拥抱Ruby模式。

在下面的代码中,您有没有办法指出我更全面地接受Ruby模式? (我的代码包含在“MY CODE [BEGINS | ENDS] HERE”评论中。

# Greed is a dice game where you roll up to five dice to accumulate
# points.  The following "score" function will be used calculate the
# score of a single roll of the dice.
#
# A greed roll is scored as follows:
#
# * A set of three ones is 1000 points
#
# * A set of three numbers (other than ones) is worth 100 times the
#   number. (e.g. three fives is 500 points).
#
# * A one (that is not part of a set of three) is worth 100 points.
#
# * A five (that is not part of a set of three) is worth 50 points.
#
# * Everything else is worth 0 points.
#
#
# Examples:
#
# score([1,1,1,5,1]) => 1150 points
# score([2,3,4,6,2]) => 0 points
# score([3,4,5,3,3]) => 350 points
# score([1,5,1,2,4]) => 250 points
#
# More scoring examples are given in the tests below:
#
# Your goal is to write the score method.

# MY CODE BEGINS HERE

def score(dice)

  # set up basic vars to handle total points and count of each number
  total = 0
  count = [0, 0, 0, 0, 0, 0]

  # for each die, make sure we've counted how many occurrencess there are
  dice.each do |die|
    count[ die - 1 ] += 1
  end

  # iterate over each, and handle points for singles and triples
  count.each_with_index do |count, index|
    if count == 3
      total = doTriples( index + 1, total )
    elsif count < 3
      total = doSingles( index + 1, count, total )
    elsif count > 3
      total = doTriples( index + 1, total )
      total = doSingles( index + 1, count % 3, total )
    end
  end

  # return the new point total
  total

end

def doTriples( number, total )
  if number == 1
    total += 1000
  else
    total += ( number ) * 100
  end
  total
end

def doSingles( number, count, total )
  if number == 1
    total += ( 100 * count )
  elsif number == 5
    total += ( 50 * count )
  end
  total
end

# MY CODE ENDS HERE

class AboutScoringProject < EdgeCase::Koan
  def test_score_of_an_empty_list_is_zero
    assert_equal 0, score([])
  end

  def test_score_of_a_single_roll_of_5_is_50
    assert_equal 50, score([5])
  end

  def test_score_of_a_single_roll_of_1_is_100
    assert_equal 100, score([1])
  end

  def test_score_of_multiple_1s_and_5s_is_the_sum_of_individual_scores
    assert_equal 300, score([1,5,5,1])
  end

  def test_score_of_single_2s_3s_4s_and_6s_are_zero
    assert_equal 0, score([2,3,4,6])
  end

  def test_score_of_a_triple_1_is_1000
    assert_equal 1000, score([1,1,1])
  end

  def test_score_of_other_triples_is_100x
    assert_equal 200, score([2,2,2])
    assert_equal 300, score([3,3,3])
    assert_equal 400, score([4,4,4])
    assert_equal 500, score([5,5,5])
    assert_equal 600, score([6,6,6])
  end

  def test_score_of_mixed_is_sum
    assert_equal 250, score([2,5,2,2,3])
    assert_equal 550, score([5,5,5,5])
  end

end

非常感谢你在我试图了解Ruby时给予的任何帮助。

37 个答案:

答案 0 :(得分:41)

哇!这里有很多非常酷的方法。我喜欢每个人的创造力。但是,我有一个教学问题,这里提供了所有答案。 (“教育学是对......教学过程的研究。” - 维基百科)

从前几个koans(在about_asserts.rb中)很明显,启蒙之路不需要任何Ruby的先验/外部知识。似乎相当清楚,Path甚至不需要先前的编程经验。因此,从教育的角度来看,这个公案必须只使用早期公案中教授的方法,语言结构和编程技术才能回答。这意味着:

  • Enumerable#each_with_index
  • Enumerable#count
  • Enumerable#sort
  • 没有Hash.new(0)指定默认值
  • Numeric#abs
  • Numeric#divmod
  • 没有递归
  • case when

现在,我并不是说你不允许在你的实现中使用这些东西,但是koan一定不能要求使用它们。 必须是仅使用先前公案引入的构造的解决方案。

此外,由于模板只是

def score(dice)
  # You need to write this method
end

似乎暗示解决方案不应该定义其他方法或类。也就是说,您应该只替换# You need to write this method行。

这是一个符合我的哲学要求的解决方案:

def score (dice)
    sum = 0
    (1..6).each do |i|
        idice = dice.select { |d| d == i }
        count = idice.size

        if count >= 3
            sum += (i==1 ? 1000 : i*100)
        end
        sum += (count % 3) * 100   if i == 1
        sum += (count % 3) *  50   if i == 5
    end
    sum
end

此处的方法/构造在以下koan文件中引入:

Enumerable#each    about_iteration.rb
Enumerable#select  about_iteration.rb
Array#size         about_arrays.rb
a ? b : c          about_control_statements.rb
%                  about_control_statements.rb

相关StackOverflow问题:

答案 1 :(得分:22)

一名学生问Joshu,“我如何编写算法来计算骰子游戏的分数?”

乔斯用棍子击打了学生并说道:“使用计算器。”

def score(dice)
  score = [0, 100, 200, 1000, 1100, 1200][dice.count(1)]
  score += [0, 50, 100, 500, 550, 600][dice.count(5)]
  [2,3,4,6].each do |num|
      if dice.count(num) >= 3 then score += num * 100 end
  end
  score
end

答案 2 :(得分:6)

我经历了一次一个测试。不确定这是一个非常“红宝石”的解决方案,但我确实很清楚每个部分正在做什么以及没有多余的值声明

def score(dice)
  ## score is set to 0 to start off so if no dice, no score
  score = 0
  ## setting the 1000 1,1,1 rule
  score += 1000 if (dice.count(1) / 3) == 1
  ## taking care of the single 5s and 1s here
  score += (dice.count(5) % 3) * 50
  score += (dice.count(1) % 3) * 100
  ## set the other triples here
  [2, 3, 4, 5, 6].each do |num|
    score += num * 100 if (dice.count(num) / 3 ) == 1
  end
  score
end

答案 3 :(得分:4)

这就是我的所作所为。看起来非常类似于一些较旧的回复。我很想找到一些巧妙的注入用法(mikeonbike的一个是niiiice)。

def score(dice)
  total = 0

  # handle triples scores for all but '1'
  (2..6).each do |num|
    total += dice.count(num) / 3 * num * 100
  end

  # non-triple score for '5'
  total += dice.count(5) % 3 * 50

  # all scores for '1'
  total += dice.count(1) / 3 * 1000 + dice.count(1) % 3 * 100

  total
end

答案 4 :(得分:4)

看起来不错。我可能会稍微改写一些东西,比如说:

def do_triples number, total
  total + (number == 1 ? 1000 : number * 100)
end

如果你想做一些除Ruby之外的其他语言可以做的事情,我认为以下可能在DIE和DRY下是合理的,在备用星期二,但我不认为那些Ruby格言真正意图适用于常见的子表达式消除。无论如何:

def do_triples number, total
  total +
  if number == 1
    1000
  else
    number * 100
  end
end

def do_triples number, total
  if number == 1
    1000
  else
    number * 100
  end + total
end

答案 5 :(得分:3)

你可以将它压缩到更少的行,但算法的可读性会丢失,所以我最终得到了这个:

def score(dice)
  result = 0;

  (1..6).each do |die|
    multiplier = die == 1 ? 1000 : 100
    number_of_triples = dice.count(die) / 3
    result += die * multiplier * number_of_triples
  end

  result += 100 * (dice.count(1) % 3)

  result += 50 * (dice.count(5) % 3)
end

如果您使用的是1.8.6,则必须使用backports或自己将计数方法添加到数组中:

class Array
  def count(item)
    self.select { |x| x == item }.size
  end
end

答案 6 :(得分:3)

这是我在大约四次迭代后尝试利用我正在学习的koans的Ruby构造的答案:

def score(dice)
  total = 0
  (1..6).each { |roll| total += apply_bonus(dice, roll)}
  return total
end

def apply_bonus(dice, roll, bonus_count = 3)
  bonus = 0
  bonus = ((roll == 1 ? 1000 : 100) * roll) if (dice.count(roll) >= bonus_count)
  bonus += 50 * (dice.count(5) % bonus_count) if (roll == 5)
  bonus += 100 * (dice.count(1) % bonus_count)  if (roll == 1)
  return bonus
end

答案 7 :(得分:2)

这是我最初在第一次尝试时遇到类似的if / then / else混乱的最终解决方案。

def score(dice)
  score = 0
  dice.uniq.each do |roll| 
    score += dice.count(roll) / 3 * (roll == 1 ? 1000 : 100*roll)
    score += dice.count(roll) % 3 * (roll == 1 ? 100 : (roll == 5 ? 50 : 0))
  end
  score
end

答案 8 :(得分:2)

这是我提出的最简单,最易读的解决方案。这也是一些不在测试中的情况,例如一卷六个5或六个1。

def score(dice)
  score = 0
  (1..6).each { |d|
    count = dice.find_all { |a| a == d }
    score = ( d == 1 ? 1000 : 100 ) * d if count.size >= 3
    score += (count.size - 3) * 50 if (count.size >= 4) && d == 5
    score += (count.size - 3) * 100 if (count.size >= 4) && d == 1  
    score += count.size * 50 if (count.size < 3) && d == 5
    score += count.size * 100 if (count.size < 3) && d == 1
  }
  score
end

我选择使用size方法而不是count方法,因为所有版本的Ruby都不支持count,并且koans没有测试计数到此测试。

答案 9 :(得分:2)

又一个答案:)

def score(dice)
  score = 0
  for num in 1..6
    occurrences = dice.count {|dice_num| dice_num == num}
    score += 1000 if num == 1 and occurrences >= 3
    score += 100 * (occurrences % 3) if num == 1
    score += 100 * num if num != 1 and occurrences >= 3
    score += 50 * (occurrences % 3) if num == 5
  end
  score
end

答案 10 :(得分:2)

def score(dice)
  total = 0
  sets = dice.group_by{|num| num }

  sets.each_pair do |num, values|
    number_of_sets, number_of_singles = values.length.divmod(3)
    number_of_sets.times { total += score_set(num) }
    number_of_singles.times { total += score_single(num) }
  end

  total
end

def score_set(num)
  return 1000 if num == 1
  num * 100
end

def score_single(num)
  return 100 if num == 1
  return 50 if num == 5
  0
end

答案 11 :(得分:1)

我和我的女朋友本周末正在经历这些红宝石,我在这方面打了很多乐趣并尝试了许多不同的解决方案。这是一个相当短的数据驱动解决方案:

SCORES = [[1000, 100], [200, 0], [300, 0], [400, 0], [500, 50], [600, 0]]

def score(dice)
  counts = dice.group_by(&:to_i).map { |i, j| [i-1, j.length] }
  counts.inject(0) do |score, (i, count)|
    sets, singles = count.divmod 3

    score + sets * SCORES[i][0] + singles * SCORES[i][1]
  end
end

这是我的必修单行(也许是FP版):

SCORES = [[1000, 100], [200, 0], [300, 0], [400, 0], [500, 50], [600, 0]]

def score(dice)
  dice.group_by(&:to_i).inject(0) {|s,(i,j)| s + j.size / 3 * SCORES[i-1][0] + j.size % 3 * SCORES[i-1][1]}
end

我也走了一些奇怪的路线:

SCORES = [[1000, 100], [200, 0], [300, 0], [400, 0], [500, 50], [600, 0]]
def score(dice)
  dice.group_by(&:to_i).inject(0) do |s, (i,j)| 
    s + j.size.divmod(3).zip(SCORES[i-1]).map {|a,b| a*b }.reduce(:+)
  end
end

所有程序员都应该解决这样的小问题...这就像在早上进行一样:)

答案 12 :(得分:1)

我和其他几个人在这里发布过相似。

score = 0
[1,2,3,4,5,6].each {|d| 
  rolls = dice.count(d)
  score = (d==1 ? 1000 : 100)*d if rolls >= 3
  score += 100*(rolls % 3) if d == 1 
  score += 50*(rolls % 3) if d == 5 
}
score

答案 13 :(得分:1)

我的回答使用了“查找表”方法......

def score(dice)
  tally = (1..6).inject(Array.new(7,0)){|a,i| a[i] = dice.count(i); a}
  rubric = {1 => [0,100,200,1000,1100,1200], 5 => [0,50,100,500,550,600]}
  score = rubric[1][tally[1]] + rubric[5][tally[5]]
  [2,3,4,6].each do |i| score += 100 * i if dice.count(i) >= 3 end
  score
end

答案 14 :(得分:1)

def score(dice)
    result = 0
    result += 1000 * (dice.find_all{|e| e == 1}).length.divmod(3)[0]
    result += 100 * (dice.find_all{|e| e == 1}).length.divmod(3)[1]
    result += 50 * (dice.find_all{|e| e == 5}).length.divmod(3)[1]
    (2..6).each {|value| result += value*100 * (dice.find_all{|e| e == value}).length.divmod(3)[0]}
    return result
end

答案 15 :(得分:1)

你可以将[0, 0, 0, 0, 0, 0]缩短为[0] * 6但是除了camelCase @injekt之外,它对我来说很好看。我很乐意在代码审查中看到这一点。

另外我想你的doTriples和doSingles并不需要他们的临时变量。

def doTriples( number, total )
  if number == 1
    total + 1000
  else
    total + ( number ) * 100 # be careful with precedence here
  end
end

答案 16 :(得分:1)

我的解决方案不是类似红宝石的风格。只是为了有趣和最短的代码。我们可以通过hash p。

设置规则
def score(dice)
  p = Hash.new([100,0]).merge({1 => [1000,100], 5 => [100,50]})
  dice.uniq.inject(0) { |sum, n| sum + dice.count(n) / 3 * n * p[n][0] + dice.count(n) % 3 * p[n][1] }
end

答案 17 :(得分:1)

我会说你看起来已经非常像Ruby了。对我来说唯一看起来不那么Rubyish的东西就是使用camelCase方法名而不是snake_case,但当然这是个人惯例,我自己也没有读过这些koans。

除此之外,通过使用case / when或任何其他解决方案,您的示例不会有太大改进。瞄准任何少于3个其他操作的东西,除此之外的任何东西,你可能想要寻找更好的解决方案。

答案 18 :(得分:1)

您可能想要更改

  # for each die, make sure we've counted how many occurrencess there are
  dice.each do |die|
    count[ die - 1 ] += 1
  end

进入哈希,例如

count = Hash.new(0)
dice.each do |die|
  count[die] += 1
end

甚至

count = {} # Or Hash.new(0)
grouped_by_dots = dice.group_by {|die| die}
1.upto(6) do |dots| # Or grouped_by_dots.each do |dots, dice_with_those_dots|
  dice_with_those_dots = grouped_by_dots.fetch(dots) {[]}
  count_of_that_dots = dice_with_those_dots.length
  count[dots] = count_of_that_dots
end

这样您就不必在代码中散布index + 1

如果Ruby内置了count_by方法,那就太好了。

答案 19 :(得分:1)

我的2美分。拥有单打/双打的新方法似乎是一种非常简单的迂回方式。

def score(dice)

  #fill initial throws
  thrown = Hash.new(0)
  dice.each do |die|
    thrown[die]+=1
  end

  #calculate score
  score = 0
  faces.each do |face,amount|
    if amount >= 3
      amount -= 3
      score += (face == 1 ? 1000 : face * 100)
    end
    score += (100 * amount) if (face == 1)
    score += (50 * amount) if (face == 5)
  end

  score
end

答案 20 :(得分:1)

这是我的答案。我不知道它是否好,但至少看起来很清楚:)

RULEHASH = { 
    1 => [1000, 100],
    2 => [100,0],
    3 => [100,0],
    4 => [100,0],
    5 => [100,50],
    6 => [100,0] 
}

def score(dice)
    score = 0
    RULEHASH.each_pair do |i, rule|
        mod = dice.count(i).divmod(3)
        score += mod[0] * rule[0] * i + mod[1] * rule[1]
    end
    score
end

答案 21 :(得分:1)

好吧,

这是我的解决方案:

def score(dice)
    total = 0

    #Iterate through 1-6, and add triples to total if found 
    (1..6).each { |roll| total += (roll == 1 ? 1000 : 100 * roll) if dice.count(roll) > 2 }

    #Handle Excess 1's and 5's
    total += (dice.count(1) % 3) * 100 
    total += (dice.count(5) % 3) * 50
end

一旦我找到了数组的“计数”方法,这个练习就很容易了。

答案 22 :(得分:0)

这里有一些不错的答案,还有一个时间吗?

我采用了使用查找来最小化条件语句的方法 - 所以只有一个if。 [而且我认为我只使用了已经在公案中引入的内容。]

def score(dice)

count = [0]*7
score = [0, 100, 0, 0, 0, 50, 0]
bonus = [0, 700, 200, 300, 400, 350, 600]

total = 0

dice.each do |roll|

    total += score[roll]

    count[roll] += 1    
    total += bonus[roll] if count[roll]==3

end 

total

end

(我知道我可以使查找数组有六个元素,但我认为更好的可读性值得几个字节。)

答案 23 :(得分:-1)

我按照脸部对骰子进行分组,然后对这些组进行循环,首先得分三分,然后是个人骰子。这就是我在玩IRL时的得分方式

def score(dice)
    points = 0
    dice.group_by {|face| face}.each do |face,group|
        while group.size >= 3
            if face == 1
                # A set of three ones is 1000 points
                points += 1000
            else
                # A set of three numbers (other than ones) is worth 100 times the number.
                points += 100 * face
            end
            group.pop(3)
        end
        group.each do |x|
             # A one (that is not part of a set of three) is worth 100 points.
            points += 100 if x==1
            # A five (that is not part of a set of three) is worth 50 points.
            points += 50 if x==5 
        end
    end
    return points
end

这就是我滚动的方式

答案 24 :(得分:-1)

我在这里使用了与其他人稍微不同的方法,并且(自然地)我认为这是更好的方法。它非常干,并且使用ruby方法相当广泛,以尽可能避免手动循环和分支。应该是相对明显的,但基本上发生的事情是我们遍历每个唯一的骰子卷,并使用该卷的出现次数的迭代侵蚀来将合适的点添加到总的总分。 / p>

def score(dice)
  score = 0 # An initial score of 0.

  throw_scores = { 1 => 10, 2 => 2, 3 => 3, 4 => 4, 5 => 5, 6 => 6 }
    # A hash to store the scores for each dice throw

  dice.uniq.each { |throw| # for each unique dice value present in the "hand"

    throw_count = (dice.select { |item| item == throw }).count
      # use select to store the number of times this throw occurs

    while throw_count > 0 
      # iteratively erode the throw count, accumulating 
      # points as appropriate along the way.

      if throw_count >= 3
        score += throw_scores[throw] * 100
        throw_count -= 3
      elsif throw == 1 || throw == 5
        score += throw_scores[throw] * 10
        throw_count -= 1
      else
        throw_count -= 1
      end
    end
  }
  return score
end

答案 25 :(得分:-1)

另一个,只是为了它的乐趣:

def score(dice)
  result = 0
  dice.uniq.each { |k|
    result += ((dice.count(k) / 3) * 1000 + (dice.count(k) % 3) * 100) if k == 1
    result += ((dice.count(k) / 3) * 100 * k + (dice.count(k) % 3) * ( k == 5 ? 50 : 0 )) if k != 1
  }
  result
end

答案 26 :(得分:-1)

那么这个解决方案呢? 感谢您的反馈!

def score(dice)
  count = Hash.new(0)
  dice.each do |die|
    count[die] += 1
  end
  total = 0
  count.each_pair { |die, set| total += set < 3 ? single_value(die,set) : triple_value(die,set)}
  total
end

def single_value(die,set)
  value = 0
  value += (set * 100) if die == 1
  value += (set * 50) if die == 5
  value
end

def triple_value(die,set)
  value = 0
  diff = set - 3
  value += single_value(die,diff)
  value += die == 1 ? 1000 : die * 100
  value
end

答案 27 :(得分:-1)

这是我的意见。这里的所有其他解决方案都试图变得聪明。有一个学习巧妙技巧的地方,但学习编写清晰可维护的代码更为重要。我在所有这些解决方案中看到的主要问题是很难从代码中辨别评分规则。你能阅读你的解决方案并确保它正确在你的头脑中吗?然后想象某人要求您添加新的评分规则,或删除一个。您能快速指向必须添加或删除规则的地方吗?

这是我的解决方案。我确信它可以改进,但看看“得分”功能的形状。这是我不介意维护的那种代码。

class Array
  def occurrences_of(match)
    self.select{ |number| match == number }.size
  end

  def delete_one(match)
    for i in (0..size)
      if match == self[i]
        self.delete_at(i)
        return
      end
    end
  end
end

def single_die_rule(match, score, dice)
  dice.occurrences_of(match) * score
end

def triple_rule(match, score, dice)
  return 0 if dice.occurrences_of(match) < 3
  3.times { dice.delete_one match }
  score
end

def score(dice)
  triple_rule(1, 1000, dice) +
  triple_rule(2, 200, dice) +
  triple_rule(3, 300, dice) +
  triple_rule(4, 400, dice) +
  triple_rule(5, 500, dice) +
  triple_rule(6, 600, dice) +
  single_die_rule(1, 100, dice) +
  single_die_rule(5, 50, dice)
end

答案 28 :(得分:-1)

我将不得不去:

def score(dice)
    # some checks
    raise ArgumentError, "input not array" unless dice.is_a?(Array)
    raise ArgumentError, "invalid array size" unless dice.size <= 5
    raise ArgumentError, "invalid dice result" if dice.any? { |x| x<1 || x>6 }

    # setup (output var, throws as hash)
    out = 0
    freqs = dice.inject(Hash.new(0)) { |m,x| m[x] += 1; m }

    # 3-sets
    1.upto(6) { |i| out += freqs[i]/3 * (i == 1 ? 10 : i) * 100 }

    # one not part of 3-set
    out += (freqs[1] % 3) * 100

    # five not part of 3-set
    out += (freqs[5] % 3) * 50

    out
end

因为到目前为止提供的大多数解决方案缺乏基本检查。其中一些是相当难以理解的(在我的书中)而不是非常惯用。

当然,通过分成两个子句,可以使3集条件更具可读性:

    # 3-sets of ones
    out += freqs[1]/3 * 1_000
    # 3-sets of others
    2.upto(6) { |i| out += freqs[i]/3 * i * 100 }

但这是IMO主要是关于个人偏好。

答案 29 :(得分:-1)

参加晚会,但想要仅仅使用迄今为止在Koans中介绍的知识来回答。具体来说,我不像大多数人那样使用Enumerable#count

这对我来说似乎非常简单,但如果有人发生,我会很高兴听到你可能有的优化。

我能说什么?我喜欢利用数组索引。

def score(dice)
  return 0 if dice.empty? # Immediately recognize an empty roll

  # Create an array to hold the scores for each die face
  totals = []
  7.times { totals << 0 }

  # Handle each roll and calculate new score
  dice.each do |roll|
    if roll == 5
      # If we have seen two 5s thus far, make the score 500 for 5s, otherwise add 50
      totals[roll] == 100 ? totals[roll] = 500 : totals[roll] += 50
    elsif roll == 1
      # If we have seen two 1s thus far, make the score 1000 for 5s, otherwise add 100
      totals[roll] == 200 ? totals[roll] = 1000 : totals[roll] += 100
    else
      # If we see any other number three times, score is the number times 100
      totals[roll] == 2 ? totals[roll] = roll * 100 : totals[roll] += 1
    end
  end

  # Count up the scores for each die face; if score is less than 50, then it's just zero
  return totals.inject(0) { |sum, points| points >= 50 ? sum += points : sum }
end

答案 30 :(得分:-1)

我更喜欢一种解决方案,它使文件开头的文档变得多余 - 也就是说,使代码自我记录。请注意该方法的最后4行如何匹配注释中描述的前4条规则。

def score(dice)
  counts = Hash.new { |hash, key| hash[key] = dice.count(key) }
  total = 0
  total += 1000 if counts[1] >= 3
  (2..6).each { |number| total += 100 * number if counts[number] >= 3 }
  total += 100 * (counts[1] % 3)
  total += 50 * (counts[5] % 3)
end

答案 31 :(得分:-1)

def score(dice)
  # You need to write this method
  grouped_die = dice.sort_by{ |i| -dice.count(i)}.first.to_i
  total       = 100 * ( dice.count(1) % 3 ) + 50 * ( dice.count(5) % 3 )
  total       += (grouped_die == 1 ? 1000 : grouped_die * 100) if dice.count( grouped_die ) >= 3
  total
end

答案 32 :(得分:-1)

我的目标是在可读性和代码长度之间找到一个很好的平衡

def score(dice)
  return 0 if dice.empty?

  dice.each do |roll|
    tracker[roll] += 1
  end

  tracker.each do |key, value|
    if ![1,5].include?(key) && value > 2
      score += key * 100
    else
      if value < 3
        key == 1 ? score += (100 * value) : score += (50 * value)
      else
        value -= 3
        key == 1 ? score += (1000 + (value * 100)) : score += (500 + (value * 50))
      end
    end

  return score
end

我仍然想在不牺牲可读性的情况下摆脱一些条件。

答案 33 :(得分:-1)

我试图尽量减少重复并保持相当大的可读性。这是我的看法:

def score(dice)
  score = 0
  (1..6).each do |roll|
    count = dice.count(roll)

    # Triples
    score += roll == 1 ? 1000 : roll * 100 if count >= 3

    # And the rest
    score += {1 => 100, 5 => 50}[roll].to_i * (count % 3)
  end
  score
end

答案 34 :(得分:-1)

def score(dice)
  score = 0
  temp = dice.inject({}) do | result, elem|
    result[elem] = (result[elem]) ? result[elem] + 1 : 1
    result
  end
  temp.each  do |key, value|
    score += (value/3 * 1000) + (value%3)*100 if key == 1
    score += (value/3 * key * 100) + (value%3)*50 if key == 5
    score += (value/3*key*100) if key != 5 && key != 1 && value >= 3
  end
  score
end

答案 35 :(得分:-1)

还可以添加另一项权利吗?

def score(dice)
  roll_counts = Hash.new {|hash, key| hash[key] = 0}

  dice.each {|roll| roll_counts[roll] += 1}

  score = 0
  roll_counts.each do |roll_value, count|
    case roll_value
    when 1
      score += count >=3 ? 1000 + (100 * (count - 3)) : 100 * count
    when 5
      score += count >= 3 ? 500 + (50 * (count - 3)) : 50 * count
    else score += roll_value * 100 if count >= 3
    end
  end
  score
end

答案 36 :(得分:-1)

来自Perl,我的直觉是使用哈希:

def score(dice)
  # You need to write this method
  score = 0
  count = Hash.new(0)

  for die in dice
    count[die] += 1

    is_triple = (count[die] % 3 == 0)
    if die == 1 then
      score += is_triple ? 800 : 100
    elsif die == 5 then
      score += is_triple ? 400 : 50
    elsif is_triple
      score += 100 * die
    end
  end

  return score
end

这样做的好处是可以单次通过dice。我可能用一个数组代替哈希。