在python中检查一系列掷硬币的序列是否为3

时间:2018-12-16 13:36:23

标签: python python-3.x

我正在尝试创建一个脚本,该脚本可以翻转硬币,直到“正面”连续翻转3次,或者“背面”连续翻转3次为止。

我的尝试是一段很长的代码,没有实现我想要的功能。它只打印一次“头”并永远循环:

import random

cointosses = []
total_count = 0

while total_count >= 0:
    tosses = random.randint(1,2)
    total_count += 1
    if tosses == 1:
        cointosses.append("heads")
    if tosses == 2:
        cointosses.append("tails")
    print(cointosses)
    seq_counter1 = 0
    seq_counter2 = 0
    total_seq = 0
    while total_seq <= 3:
        check1 = "heads"
        check2= "tails"
        for toss in cointosses:
            if toss == check1:
                seq_counter1 +=1 
                seq_counter2 = 0
                if seq_counter1 == 3:
                    total_seq = 3
                    break
            if toss == check2:
                seq_counter1 = 0
                seq_counter2 +=1
                if seq_counter2 == 3:
                    total_seq = 3
                    break

    if total_seq == 3:
        break

我敢肯定有一些更简单的方法可以做到这一点,但是我似乎无法弄清楚。

2 个答案:

答案 0 :(得分:2)

您永远不会离开while循环来检查您的列表。 break语句仅离开for循环(设置total_seq = 3)-您的while循环直到total_seq 更大然后3 -> 无限循环

while total_seq <= 3:        # this is never been left because <= 3
    check1 = "heads"         #                                 ^^ smaller equal
    check2= "tails"
    for toss in cointosses:
        if toss == check1:
            seq_counter1 +=1 
            seq_counter2 = 0
            if seq_counter1 == 3:
                total_seq = 3
                break              # breaks out of the for but total_seq = 3 so in while
        if toss == check2:
            seq_counter1 = 0
            seq_counter2 +=1
            if seq_counter2 == 3:
                total_seq = 3
                break              # breaks out of the for but total_seq = 3 so in while

您只需将代码添加到列表中,然后检查后3个元素是否相等,而不用检查整个列表,即可简化代码 lot 。每次>:

import random

def toss():
    """Return randomly 'heads' or 'tails'."""
    return "heads" if (random.randint(1,2) == 1) else "tails"

# need at least 3 tosses to finish
cointosses = []
for _ in range(3):
    cointosses.append(toss())
    print(cointosses)

# repeat until the set(..) of the last 3 elements contains exactly 1 item 
while not len(set(cointosses[-3:]))==1:
    cointosses.append(toss())
    print(cointosses)

print(f"It took {len(cointosses)} tosses to get 3 equal ones.")

输出2运行:

['tails']
['tails', 'tails']
['tails', 'tails', 'heads']
['tails', 'tails', 'heads', 'heads']
['tails', 'tails', 'heads', 'heads', 'heads']
It took 5 tosses to get 3 equal ones.

['tails']
['tails', 'tails']
['tails', 'tails', 'heads']
['tails', 'tails', 'heads', 'heads']
['tails', 'tails', 'heads', 'heads', 'tails']
['tails', 'tails', 'heads', 'heads', 'tails', 'heads']
['tails', 'tails', 'heads', 'heads', 'tails', 'heads', 'tails']
['tails', 'tails', 'heads', 'heads', 'tails', 'heads', 'tails', 'tails']
['tails', 'tails', 'heads', 'heads', 'tails', 'heads', 'tails', 'tails', 'heads']
['tails', 'tails', 'heads', 'heads', 'tails', 'heads', 'tails', 'tails', 'heads', 'heads']
['tails', 'tails', 'heads', 'heads', ... snipp ..., 'tails', 'heads', 'heads', 'tails']
['tails', 'tails', 'heads', 'heads', ... snipp ..., 'heads', 'heads', 'tails', 'tails']
['tails', 'tails', 'heads', 'heads', ... snipp ..., 'heads', 'tails', 'tails', 'tails']
It took 13 tosses to get 3 equal ones.

如果您不喜欢set(),还可以检查:

while not all(i == cointosses[-1] for i in cointosses[-3:-1]):
    # rest identical

Doku:

答案 1 :(得分:1)

此代码存在一些问题:

1。这段代码会产生无限循环:

仅当变量total_seq包含大于3的值时,内部while循环才会终止。由于可能唯一分配给它的值是0和3 (根据您的代码),因此while循环将永远持续下去。

...
total_seq = 0 #<-----------------------
while total_seq <= 3:
    ...
    for toss in cointosses:
        if toss == check1:
            ...
            if seq_counter1 == 3:
                total_seq = 3 #<-----------------------
                break
        if toss == check2:
            ...
            if seq_counter2 == 3:
                total_seq = 3 #<-----------------------
                break
...

2。您一开始只进行一次coinflip,然后一次又一次地使用此结果

random.randint(...)为您提供一个值,该值存储在币扔列表中(这意味着:您只需翻转一次硬币)内部for循环假设您已经在列表中存储了很多掷骰子。如果可以找到3个连续的硬币夹,则只会将total_seq设置为3

否则,它将只重复内部while循环并再次执行相同的操作,而无需添加新的coinflips (永远不会再次到达外部)

tosses = random.randint(1,2)
...
if tosses == 1:
    cointosses.append("heads")
if tosses == 2:
    cointosses.append("tails")
...
    for toss in cointosses:
        ...
            if seq_counter1 == 3:
                total_seq = 3
                break
        ...
            if seq_counter2 == 3:
                total_seq = 3
                break
...

3。序列计数器 seq_counter1和seq_counter2 仅在前一个coinflip结果不同的情况下才会重置。

由于您只进行一次硬币翻转(如问题2中所述),因此“先前的硬币翻转”始终只是您进行的第一次翻转。 这意味着您在开始时进行一次硬币翻转,然后根据第一次翻转的结果将seq_counter1或seq_counter2递增到3。

...
seq_counter1 = 0
seq_counter2 = 0
...
while total_seq < 3:
    ...
        if toss == check1:
            seq_counter1 +=1
            seq_counter2 = 0
            ...
        if toss == check2:
            seq_counter1 = 0
            seq_counter2 +=1
            ...
...

解决方案

这三个问题都可以通过删除内部的while循环并仅在外部的循环中执行其代码来解决:

import random
cointosses = []
total_count = 0
while total_count >= 0:
    tosses = random.randint(1,2)
    total_count += 1
    if tosses == 1:
        cointosses.append("heads")
    if tosses == 2:
        cointosses.append("tails")
    print(cointosses)
    seq_counter1 = 0
    seq_counter2 = 0
    total_seq = 0
    check1 = "heads"
    check2= "tails"
    for toss in cointosses:
        if toss == check1:
            seq_counter1 +=1
            seq_counter2 = 0
            if seq_counter1 == 3:
                total_seq = 3
                break
        if toss == check2:
            seq_counter1 = 0
            seq_counter2 +=1
            if seq_counter2 == 3:
                total_seq = 3
                break

    if total_seq == 3:
        break

之所以可行,是因为条件 total_seq == 3 已由外部循环中的最后一个if语句进行了测试。

结论

但是,由于您构建了一个列表并一次又一次地遍历该代码,因此该代码并不适用。 每次附加一个硬币时,您都在遍历所有内容。但是,如果您考虑一下:您只需要检查新添加的元素是否创建了连续的行。

如果您想正确执行此操作,则应仅执行一个循环(无嵌套循环):)