【问题标题】:Python - calculate die rolls and count doublesPython - 计算骰子并计算双打
【发布时间】:2013-09-06 21:21:08
【问题描述】:

问题:我需要掷 3 个骰子。如果两个(或三个)骰子返回相同的数字,则停止。如果 3 个骰子都是唯一的(例如 2、4 和 6),则再次掷骰子。执行此操作,直到掷出双倍/三倍,或 7 次,以先到者为准。

注意:我是 python 新手。

这是我目前所拥有的,但这实际上是生成了 216 种可能的组合:

import itertools

all_possible = list(itertools.permutations([1,2,3,4,5,6],3))
input = raw_input()

print all_possible

生成这种类型的输出:

[(1, 2, 3), (1, 2, 4), (1, 2, 5), (1, 2, 6), (1, 3, 2), (1, 3, 4), (1, 3, 5), (1, 3, 6), (1, 4, 2), (1, 4, 3), (1, 4, 5), (1, 4, 6), (1, 5, 2), (1, 5, 3), (1, 5, 4), (1, 5, 6), (1, 6, 2), (1, 6, 3), (1, 6, 4), (1, 6, 5), (2, 1, 3), (2, 1, 4), (2, 1, 5), (2, 1, 6), (2, 3, 1), (2, 3, 4), (2, 3, 5), (2, 3, 6), (2, 4, 1), (2, 4, 3), (2, 4, 5), (2, 4, 6), (2, 5, 1), (2, 5, 3), (2, 5, 4), (2, 5, 6), (2, 6, 1), (2, 6, 3), (2, 6, 4), (2, 6, 5), (3, 1, 2), (3, 1, 4), (3, 1, 5), (3, 1, 6), (3, 2, 1), (3, 2, 4), (3, 2, 5), (3, 2, 6), (3, 4, 1), (3, 4, 2), (3, 4, 5), (3, 4, 6), (3, 5, 1), (3, 5, 2), (3, 5, 4), (3, 5, 6), (3, 6, 1), (3, 6, 2), (3, 6, 4), (3, 6, 5), (4, 1, 2), (4, 1, 3), (4, 1, 5), (4, 1, 6), (4, 2, 1), (4, 2, 3), (4, 2, 5), (4, 2, 6), (4, 3, 1), (4, 3, 2), (4, 3, 5), (4, 3, 6), (4, 5, 1), (4, 5, 2), (4, 5, 3), (4, 5, 6), (4, 6, 1), (4, 6, 2), (4, 6, 3), (4, 6, 5), (5, 1, 2), (5, 1, 3), (5, 1, 4), (5, 1, 6), (5, 2, 1), (5, 2, 3), (5, 2, 4), (5, 2, 6), (5, 3, 1), (5, 3, 2), (5, 3, 4), (5, 3, 6), (5, 4, 1), (5, 4, 2), (5, 4, 3), (5, 4, 6), (5, 6, 1), (5, 6, 2), (5, 6, 3), (5, 6, 4), (6, 1, 2), (6, 1, 3), (6, 1, 4), (6, 1, 5), (6, 2, 1), (6, 2, 3), (6, 2, 4), (6, 2, 5), (6, 3, 1), (6, 3, 2), (6, 3, 4), (6, 3, 5), (6, 4, 1), (6, 4, 2), (6, 4, 3), (6, 4, 5), (6, 5, 1), (6, 5, 2), (6, 5, 3), (6, 5, 4)]

这也不是很好,因为它只产生没有双倍或三倍 - 据我所知,一切都只是独特的组合。

---------更新---------- 好的——我拿了这个,并通过从数组中剥离每个值并对它们求和(可能以最不有效的方式)来扩展它。它可以工作,如果在休息之前生成了多个集合,它们都会打印出来。我现在要做的是总结。所以:

def gen_random_termagants():
for _ in range(7): 
    # instead of three separate variables, we use a list here
    # the nice thing is, that you can freely vary the number of
    # 'parallel' dice rolls this way 
    dice = [random.randint(1, 6) for _ in range(3)]

    # this is more general and will break as soon as there are
    # duplicate (die) values in the list (meaning, break, if not all elements 
    # are different)
    first_die = dice[0]
    second_die = dice[1]
    third_die = dice[2]
    total_term = first_die + second_die + third_die
    print "Total: %s" % total_term
    if len(dice) > len(set(dice)):
        break

这是输出示例:

How many tervigons? ::>3
Let's calculate some termagants based on 3 tervigons...
You'll get a minimum of 9 termagants per turn.
You'll get a maximum of 54 termagants per turn.
minimums: 5 turns [45] :: 6 turns [54] :: 7 turns [63]
averages: 5 turns [157] :: 6 turns [189] :: 7 turns [220]
maximums: 5 turns [270] :: 6 turns [324] :: 7 turns [378]
Total: 9
Total: 8

所以在这个例子中,我希望它返回 17(即 9 + 8)。

【问题讨论】:

  • 请不要添加更多问题,只需打开新问题即可。

标签: python probability dice


【解决方案1】:

Python 带有一个great standard library(正如您在使用 itertools 时可能已经发现的那样),您还可以在其中找到一个 random 模块。

您可以使用random.randint 来模拟掷骰子。有多种方法可以解决这个问题。第一个代码示例有些局限,第二个更通用。

import random

# '_' (underscore) is used for values that are generated, but that you do not
# care about - here we only want to repeat seven times and do not care about
# the actual loop count 
for _ in range(7): 
    # generate three random numbers between [1 and 6] 
    # and store the values in a, b, c respectively (tuple unpacking)
    a, b, c = (random.randint(1, 6) for _ in range(3))

    # if one of the conditions holds, break out of the loop early
    if a == b or a == c or b == c or a == b == c:
        break

正如@Paulo 指出的,您可以使用另一种更简洁 的方法来检查列表(或元组)的n 元素是否都不同,即您将所有元素放入set:

for _ in range(7): 
    # instead of three separate variables, we use a list here
    # the nice thing is, that you can freely vary the number of
    # 'parallel' dice rolls this way 
    dice = [random.randint(1, 6) for _ in range(3)]

    # this is more general and will break as soon as there are
    # duplicate (die) values in the list (meaning, break, if not all elements 
    # are different)
    if len(dice) > len(set(dice)):
        break

回答您更新的问题,只需使用sum

    total = sum(dice)

【讨论】:

  • 我是random.randint(1, 6)
  • @PauloAlmeida,谢谢,已更正(从切片语义过度概括;)
  • 如何从random.randint 行返回一个列表,然后只返回if len(rolls) != len(set(rolls))
  • @PauloAlmeida,我一直在考虑一种更短更通用的方式来表达if... - 很好的变化,我更新了我的答案,谢谢。
  • 我喜欢这个解决方案,并对其进行了扩展——请参阅原始问题中的更新以获取更多问题 :)
【解决方案2】:

这是输入排列的正确输出,您要求的是笛卡尔积。见product

例如这将打印您期望的输出。

from itertools import product

d = [ x for x in range(1, 7) ]
for r in product(d, d, d):
    print r

【讨论】:

  • 你也可以product(d, repeat=3).
  • 另外,您可以简化为d = range(1, 7)
  • @flornquake 这只适用于小于 3 的 python 版本,对吧?
  • @mr2ert 在 Python 3 中也可以使用,因为范围对象可以迭代多次。
猜你喜欢
  • 2020-05-24
  • 1970-01-01
  • 2016-08-18
  • 2015-07-20
  • 2021-09-23
  • 2019-03-04
  • 2020-06-06
  • 2011-02-10
  • 1970-01-01
相关资源
最近更新 更多