在 for 循环中删除元素
Remove elements while in a for loop
我有一个简单的纸牌游戏,我目前正在为我的论文工作。
规则很简单。您有一副 52 张牌,从 1 到 10 以及杰克、皇后、马。
你从牌组抽一张牌。如果它是一个数字,它将被添加到您的帐户中。如果您抽到 J、Q 或马,您的帐户将重置为 0。每次抽奖后,您可以决定是要再次抽奖还是停止抽奖。
对于这个游戏,我在这个网站的帮助下编写了一个代码。
它应该给出准确绘制 "target" 的概率。
因此,例如抽奖的概率,这样您的帐户中就有 1 个积分,
是 4/52,因为你有四个 1。 Programm 确实给了我这个值。
但是您帐户中恰好有 2 个积分的概率是
4/52 + 4/52*3/51。您可以画一个 2,概率为 4/52,或者一个 1 和另一个 1,概率为 4/52*3/51。
这里的代码搞砸了。它计算您的帐户中恰好有 2 个点的概率
4/52 + 4/52*4/51 我不明白为什么?
谁能帮帮我?
import collections
import numpy as np
def probability(n, s, target):
prev = {0: 1} # previous roll is 0 for first time
for q in range(n):
cur = collections.defaultdict(int) # current probability
for r, times in prev.items():
cards = [card for card in range(1, 11)] * 4
for i in cards[:]:
cards.remove(i)
# if r occurred `times` times in the last iteration then
# r+i have `times` more possibilities for the current iteration.
cur[r + i] += times
prev = cur # use this for the next iteration
return (cur[t]*np.math.factorial(s-n)) / (np.math.factorial(s))
if __name__ == '__main__':
s = 52
for target in range(1, 151):
prob = 0
for n in range(1, 52):
prob += probability(n, s, target)
print(prob)
编辑:我很确定,那行
for i in [i for i in cards]:
是问题所在。因为cards.remove(i)移除抽到的牌,但我不在乎,反正可以抽到。
编辑 2:仍在搜索。我尝试了这两个问题中的建议
How to remove list elements in a for loop in Python?
和
How to remove items from a list while iterating?
没有达到应有的效果。
我假设你想用 probability(n, s, target) 来计算你从 s 张卡片中恰好抽出 n 个值的总和恰好是 target 的概率。
那么你就会遇到n>=2的问题。如果我没理解错的话,对于循环中的每一次迭代
for q in range(n):
你在 cur[sum] 中保存了抽一张牌 (p=0)、两张牌 (p=1) 等后达到总和的方法数。但是当你设置 p=1 时,你不会 "remember" 你在设置
时已经画了哪张牌
cards = [i for i in range(1, 11)] * 4
之后。因此,如果您先抽到了“1”(四种可能性),您仍然可以从牌组中抽出四个“1”,这将为您提供 4/52*4/51。
作为旁注:
如果 i==11 是否应该进行某种检查,因为这应该重置您的帐户?
我已经解决了。大约 4 天后。
这是代码:
import numpy as np
def probability(cards, target, with_replacement = False):
x = 0 if with_replacement else 1
def _a(idx, l, r, t):
if t == sum(l):
r.append(l)
elif t < sum(l):
return
for u in range(idx, len(cards)):
_a(u + x, l + [cards[u]], r, t)
return r
return _a(0, [], [], target)
if __name__ == '__main__':
s = 52 # amount of cards in your deck
cards = [c for c in range(1, 11)] * 4
prob = 0
for target in range(1, 151): # run till 150 points
prob = probability(cards, target, with_replacement = False)
percentage = 0
for i in range(len(prob)):
percentage += np.math.factorial(len(prob[i])) * np.math.factorial(s-len(prob[i]))/(np.math.factorial(s))
print(percentage)
此代码是我的问题的解决方案。因此可以关闭此线程。
对于那些想知道它作为 tl;dr 版本的功能的人。
您有一个列表(在本例中为卡片)。该代码为您提供了列表中元素的所有可能组合,例如元素的总和等于目标值。此外,它还给出了上述纸牌游戏中绘制特定值的概率。上面提到的游戏基本上是猪骰子游戏,但有纸牌。
我有一个简单的纸牌游戏,我目前正在为我的论文工作。 规则很简单。您有一副 52 张牌,从 1 到 10 以及杰克、皇后、马。 你从牌组抽一张牌。如果它是一个数字,它将被添加到您的帐户中。如果您抽到 J、Q 或马,您的帐户将重置为 0。每次抽奖后,您可以决定是要再次抽奖还是停止抽奖。
对于这个游戏,我在这个网站的帮助下编写了一个代码。 它应该给出准确绘制 "target" 的概率。 因此,例如抽奖的概率,这样您的帐户中就有 1 个积分, 是 4/52,因为你有四个 1。 Programm 确实给了我这个值。
但是您帐户中恰好有 2 个积分的概率是 4/52 + 4/52*3/51。您可以画一个 2,概率为 4/52,或者一个 1 和另一个 1,概率为 4/52*3/51。 这里的代码搞砸了。它计算您的帐户中恰好有 2 个点的概率 4/52 + 4/52*4/51 我不明白为什么?
谁能帮帮我?
import collections
import numpy as np
def probability(n, s, target):
prev = {0: 1} # previous roll is 0 for first time
for q in range(n):
cur = collections.defaultdict(int) # current probability
for r, times in prev.items():
cards = [card for card in range(1, 11)] * 4
for i in cards[:]:
cards.remove(i)
# if r occurred `times` times in the last iteration then
# r+i have `times` more possibilities for the current iteration.
cur[r + i] += times
prev = cur # use this for the next iteration
return (cur[t]*np.math.factorial(s-n)) / (np.math.factorial(s))
if __name__ == '__main__':
s = 52
for target in range(1, 151):
prob = 0
for n in range(1, 52):
prob += probability(n, s, target)
print(prob)
编辑:我很确定,那行
for i in [i for i in cards]:
是问题所在。因为cards.remove(i)移除抽到的牌,但我不在乎,反正可以抽到。
编辑 2:仍在搜索。我尝试了这两个问题中的建议
How to remove list elements in a for loop in Python?
和
How to remove items from a list while iterating?
没有达到应有的效果。
我假设你想用 probability(n, s, target) 来计算你从 s 张卡片中恰好抽出 n 个值的总和恰好是 target 的概率。 那么你就会遇到n>=2的问题。如果我没理解错的话,对于循环中的每一次迭代
for q in range(n):
你在 cur[sum] 中保存了抽一张牌 (p=0)、两张牌 (p=1) 等后达到总和的方法数。但是当你设置 p=1 时,你不会 "remember" 你在设置
时已经画了哪张牌cards = [i for i in range(1, 11)] * 4
之后。因此,如果您先抽到了“1”(四种可能性),您仍然可以从牌组中抽出四个“1”,这将为您提供 4/52*4/51。
作为旁注: 如果 i==11 是否应该进行某种检查,因为这应该重置您的帐户?
我已经解决了。大约 4 天后。
这是代码:
import numpy as np
def probability(cards, target, with_replacement = False):
x = 0 if with_replacement else 1
def _a(idx, l, r, t):
if t == sum(l):
r.append(l)
elif t < sum(l):
return
for u in range(idx, len(cards)):
_a(u + x, l + [cards[u]], r, t)
return r
return _a(0, [], [], target)
if __name__ == '__main__':
s = 52 # amount of cards in your deck
cards = [c for c in range(1, 11)] * 4
prob = 0
for target in range(1, 151): # run till 150 points
prob = probability(cards, target, with_replacement = False)
percentage = 0
for i in range(len(prob)):
percentage += np.math.factorial(len(prob[i])) * np.math.factorial(s-len(prob[i]))/(np.math.factorial(s))
print(percentage)
此代码是我的问题的解决方案。因此可以关闭此线程。 对于那些想知道它作为 tl;dr 版本的功能的人。
您有一个列表(在本例中为卡片)。该代码为您提供了列表中元素的所有可能组合,例如元素的总和等于目标值。此外,它还给出了上述纸牌游戏中绘制特定值的概率。上面提到的游戏基本上是猪骰子游戏,但有纸牌。