我正在迈出递归和动态编程的第一步,并且有一个关于形成子问题来建模递归的问题。
问题:
有多少种不同的方式 翻转一个公平的硬币5次而没有 连续三个或更多头?
如果有人可以提供一些评论很多的代码(Ruby首选但不是必需的)来帮助我实现目标。如果重要的话,我不是学生,这是对Project Euler问题的修改,使我很容易理解。我只需要编写递归公式。
如果您想将问题抽象为有多少种不同的方式来翻转一枚硬币Y次并且没有连续Z或更多的头,这也可能是有益的。再次感谢,这个网站摇滚。
答案 0 :(得分:6)
您只需为此创建一个公式:
在没有连续3个头的情况下翻转硬币5次的方法的数量等于5个硬币翻转的组合的数量减去连续至少三个头的组合的数量。在这种情况下:
HHH-- (4 combinations)
THHH- (2 combinations)
TTHHH (1 combination)
组合总数= 2 ^ 5 = 32.而32 - 7 = 25。
如果我们连续N次掷硬币N次,则总量为2 ^ N且至少Q头的量为2 ^(N-Q + 1)-1。所以一般的答案是:
Flip(N,Q) = 2^N - 2^(N-Q+1) +1
当然,你可以使用递归来模拟总量:
flipme: N x N -> N
flipme(flipsleft, maxhead) = flip(flipsleft, maxhead, 0)
flip: N x N x N -> N
flip(flipsleft, maxhead, headcount) ==
if flipsleft <= 0 then 0
else if maxhead<=headcount then 0
else
flip(flipsleft - 1, maxhead, headcount+1) + // head
flip(flipsleft - 1, maxhead, maxhead) // tail
答案 1 :(得分:1)
这不是采用所有可能的5位序列并去除有三个连续1位的情况(假设1 =头,0 =尾)?
答案 2 :(得分:1)
这是我在Ruby中的解决方案
def combination(length=5)
return [[]] if length == 0
combination(length-1).collect {|c| [:h] + c if c[0..1]!= [:h,:h]}.compact +
combination(length-1).collect {|c| [:t] + c }
end
puts "There are #{combination.length} ways"
所有递归方法都以最后一个案例的早期开始。
return [[]] if length == 0
这将返回一个组合数组,其中唯一的零长度组合是[]
下一位(简化)是......
combination(length-1).collect {|c| [:h] + c } +
combination(length-1).collect {|c| [:t] + c }
所以..这说..我想要一个比所需长度短的所有组合,其中:head添加到每个组合中......加上所有组合都是一个较短的尾部添加到它们。
考虑递归的方法是......“假设我有一个方法来做n-1案例......我需要添加什么才能使它覆盖n个案例”。对我而言,感觉就像感应一样。
此代码将生成头部和尾部的所有组合,直到给定的长度。
我们不希望有:h:h:h。这只能发生在我们:h:h并且我们添加:h。所以......我在添加:h时放了一个if c[0..1] != [:h,:h]
,因此当它即将构成无效组合时,它将返回nil
而不是数组。
然后我必须compact
结果忽略所有仅nil
的结果
答案 3 :(得分:0)
这分解为:
当第一次翻转是头部+第一次翻转是尾巴时,有多少种方法可以翻转一枚硬币四次:
所以在python中:
HEADS = "1"
TAILS = "0"
def threeOrMoreHeadsInARow(bits):
return "111" in bits
def flip(n = 5, flips = ""):
if threeOrMoreHeadsInARow(flips):
return 0
if n == 0:
return 1
return flip(n - 1, flips + HEADS) + flip(n - 1, flips + TAILS)
答案 4 :(得分:0)
这是在Python中实现它的一种方法:
#This will hold all possible combinations of flipping the coins.
flips = [[]]
for i in range(5):
#Loop through the existing permutations, and add either 'h' or 't'
#to the end.
for j in range(len(flips)):
f = flips[j]
tails = list(f)
tails.append('t')
flips.append(tails)
f.append('h')
#Now count how many of the permutations match our criteria.
fewEnoughHeadsCount = 0
for flip in flips:
hCount = 0
hasTooManyHeads = False
for c in flip:
if c == 'h': hCount += 1
else: hCount = 0
if hCount >= 3: hasTooManyHeads = True
if not hasTooManyHeads: fewEnoughHeadsCount += 1
print 'There are %s ways.' % fewEnoughHeadsCount
答案 5 :(得分:0)
这是一个使用Ruby yield
语句的递归组合函数:
def combinations(values, n)
if n.zero?
yield []
else
combinations(values, n - 1) do |combo_tail|
values.each do |value|
yield [value] + combo_tail
end
end
end
end
你可以使用正则表达式连续解析三个头:
def three_heads_in_a_row(s)
([/hhh../, /.hhh./, /..hhh/].collect {|pat| pat.match(s)}).any?
end
最后,你会得到这样的答案:
total_count = 0
filter_count = 0
combinations(["h", "t"], 5) do |combo|
count += 1
unless three_heads_in_a_row(combo.join)
filter_count += 1
end
end
puts "TOTAL: #{ total_count }"
puts "FILTERED: #{ filter_count }"
这就是我如何做到的:)