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

Jos*_*ody 14 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
Run Code Online (Sandbox Code Playgroud)

非常感谢您提供的任何帮助,因为我试图了解Ruby.

Noa*_*man 41

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

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

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

现在,我并不是说你不允许在你的实现中使用这些东西,但是koan不能要求使用它们.有必须是仅使用事先koans导入的构建的解决方案.

此外,由于模板只是

def score(dice)
  # You need to write this method
end
Run Code Online (Sandbox Code Playgroud)

似乎暗示解决方案不应该定义其他方法或类.也就是说,你应该只更换# 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
Run Code Online (Sandbox Code Playgroud)

这里的方法/结构在以下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
Run Code Online (Sandbox Code Playgroud)

相关StackOverflow问题:


ben*_*hor 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
Run Code Online (Sandbox Code Playgroud)


age*_*fin 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
Run Code Online (Sandbox Code Playgroud)


Dig*_*oss 4

看起来不错。我可能写的有些东西略有不同,比如:

def do_triples number, total
  total + (number == 1 ? 1000 : number * 100)
end
Run Code Online (Sandbox Code Playgroud)

如果你想做一些除了 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
Run Code Online (Sandbox Code Playgroud)