我很快得出的结论是,我不能成为一名程序员。尽管在Ruby Koans上做了大量的笔记和实践,直到完成Codecademy的Ruby课程三次,目前正在通过Chris Pine的书每天平均学习6小时...这个当前的Koan是一个练习沮丧和认识到不是每个人都可以成为程序员。
练习如下
# Greed is a dice game where you roll up to five dice to accumulate
# points. The following "score" function will be used to 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.
def score(dice)
end
首先看一下所有内容,我假设测试会通过dice
提供随机数功能?或者我需要自己写吗?现在我必须限制掷骰子的范围?然后,我所要做的就是得到数字并将它们放入一个数组中,但最多只有5个位置(所以就像while array has 5 or less entries?
我需要定义点系统的工作方式。所以像score[0] = 100, score[2]= 200
这样的东西?但是现在我已经对分数进行了硬编码,如果第一个位置不是1但是5是什么呢?那么数字是50个。那么if / else语句怎么样呢?
if score[0] == 1
point = 100
elsif score[0] == 5
point = 50
else point = 0
然后我重复这个位置[1] - [4]?
尽管想要非常糟糕,我不想简单地谷歌答案,我宁愿因缺乏更好的词而得到某种方向。
希望这不是一般问题,但你怎么处理这样的事情呢?也许在解决这个问题之前,我应该首先从头到尾阅读Pine的书?
答案 0 :(得分:1)
你可以写下你的方法:
def score(d1,d2,d3,d4,d5)
...
end
您需要做的第一件事是确定五个值中的三个是否相同。如果三个相同,则需要知道它们是1
还是其他值,并且您需要知道其他两个值是什么。如果最多两个值相同,那么您也需要知道它。这确实是问题的症结所在。所以让我们写一个方法:
def partition(d1,d2,d3,d4,d5)
...
end
从score
调用,如下所示:
three_value, other_values = partition(d1,d2,d3,d4,d5)
其中:
three_value
等于三个相等值组(1-6
)或(例如)nil
的公共值;和other_values
是来自[d1,d2,d3,d4,d5]
的两个值的数组,它排除了三个相等的值(如果有一组三个相等的值)或[d1,d2,d3,d4,d5]
(如果没有组)三个相等的值)。例如,
three_value, other_values = partition(1,3,4,3,6)
#=> [nil, [1, 3, 4, 3, 6]]
three_value, other_values = partition(1,3,4,3,3)
#=> [3, [1, 4]]
three_value, other_values = partition(1,3,3,3,3)
#=> [3, [1, 3]]
three_value, other_values = partition(3,3,3,3,3)
#=> [3, [3, 3]]
方法partition
之后,方法score
非常简单:
def score(d1,d2,d3,d4,d5)
three_value, other_values = partition(d1,d2,d3,d4,d5)
total = case three_value
when 1 then 1000
when nil then 0
else three_value * 1000
end
other_values.each do |i|
total += case i
when ...
...
when ...
...
end
end
end
在我们开始使用方法partition
之前,我们可以简化score
,如下所示:
def score(*d)
three_value, other_values = partition(*d)
total = case three_value
when 1 then 1000
when nil then 0
else three_value * 1000
end
other_values.each do |i|
total += case i
when ...
...
when ...
...
end
end
end
使用" splat"操作员*
很方便,因为我们不关心骰子卷的顺序。在调用方法score
或partition
时,如果d = [1,3,4,3,3]
,则score(*d)
与以下内容相同:
score(1,3,4,3,3)
(看看为什么*
被调用" splat"?)
在上面的方法score
中,d
(不是*d
)是一个包含五个值的数组。
现在让我们看看方法partition
。我们需要计算每个结果(1-6
)出现的次数。哈希是一个很好的工作:
def partition(*d)
counts = {}
d.each do |i|
if counts.key?(i)
counts[i] += 1
else
counts[i] = 1
end
end
...
end
假设d = [1,3,4,3,3]
。然后
counts #=> {1=>1, 3=>3, 4=>1}
我们现在需要找到具有最大值的密钥。为此,我们可以使用Enumerable#max_by:
k, v = counts.max_by { |k,v| v }
#=> [3, 3]
k #=> 3
v #=> 3
我们可以像这样计算other_values
:
other_values = case v
when 3
d - [k]
when 4
(d - [k]) << k
when 5
(d - [k]) << k << k
else
d
end
注意Array#-是数组差异方法。
最后,
three_value = (v >= 3) ? k : nil
和partition
将返回:
[three_value, other_values]
你能把所有这些放在一起吗?
[在您使用代码之前,您可能不想阅读以下内容。]
获得Ruby经验后,您可以按如下方式编写partition
:
def partition(*d)
k,v = d.each_with_object(Hash.new(0)) { |i,h| h[i]+=1 }.max_by(&:last)
(v < 3)) ? [nil, d] : [k, d - [k] + [k]*(v-3)]
end
旁白:我希望看到核心方法Array#difference
,我定义并详细阐述here。这将允许表达partition
正文的最后一行:
(v < 3)) ? [nil, d] : [k, d.difference([k,k,k])]