Python 骰子:避免三次重复

Python Dice : Avoiding Triple Repetitions

我要解决这个 DICE 难题,我的思绪停留在一个场景上。


在试验中发生了多少次,恰好两个 6 相继滚动?例如,在 56611166626634416 序列中它出现了两次,恰好有两个 6 被抛出。


问题是:如何避免让计数器计数那些666。

注意:我尝试了多个跟踪器(密钥),但我遇到了另一个问题:

IndexError: list index out of range

Throws=[6,6,2,6,6,6,3,6,6,3,6,6,6]
Counter_6 = 0
X=0


for i in range (0,len(Throws)):

    if i==len(Throws) or i+1>len(Throws) or i+2>len(Throws):
        key1= Throws[i]
        key2=0
        key3=0

    elif i+2>=len(Throws):
        key1 = Throws[i]
        key2 = Throws[i + 1]
        key3 = 0

    else:
        key1=Throws[i]
        key2 = Throws[i + 1]
        key3 = Throws[i + 2]
    print("key 1 is", key1)
    print("key 2 is", key2)
    print("key 3 is", key3)

    if key1==6 and key2==6 and key3!=6 and X==0:
        Counter_6 = Counter_6 + 1
        X=1
    elif key1!=6 and key2 ==6 and key3==6 and X==0:
        Counter_6 = Counter_6 + 1
        X=1
    elif key1==6 and key2==6 and key3==6:
        Counter_6 = Counter_6
        X=0

print("number of double 6 are: ",Counter_6)

计数器应等于 2

我能想到的一个更简单的方法是用一个不能出现在掷骰子中的整数来标记连续 3 个 6 中的第 3 个 6。例如-1

throws=[6,6,2,6,6,6,3,6,6,3,6,6,6]
counter = 0

for i in range (0, len(throws)-2):

    if throws[i] == 6 and throws[i+1] == 6:
        if throws[i+2] == 6:
            throws[i+2] = -1
print(throws)
#[6, 6, 2, 6, 6, -1, 3, 6, 6, 3, 6, 6, -1]

之后可以遍历list,遇到连续两个6,第三个不是-1的时候,就创建计数器

for i in range (0, len(throws)-2):

    if throws[i] == 6 and throws[i+1] == 6 and throws[i+2] != -1:
        counter+=1

print(counter)
#2

这种方法肯定可以改进。

itertools.groupby() 将或多或少地为您提供一组连续的数字:

from itertools import groupby

throws =  [6,6,2,6,6,6,3,6,6,3,6,6,6]
[tuple(v) for k,v in groupby(throws)]

>> [(6, 6), (2,), (6, 6, 6), (3,), (6, 6), (3,), (6, 6, 6)]

您可以将其与 collections.Counter 结合使用以获得 (6,6) 元组的计数:

from itertools import groupby
from collections import Counter

throws =  [6,6,2,6,6,6,3,6,6,3,6,6,6]
c = Counter(tuple(v) for k,v in groupby(throws))
c[(6,6)]

>> 2

一种可能的方法是使用正则表达式。这样您就可以指定确切的模式并简单地计算它们出现的次数,还有一个额外的好处是这也适用于具有字母或符号的系统的结果。

import re

throws = [6, 6, 2, 6, 6, 6, 3, 6, 6, 3, 6, 6, 6]

throws_string = "".join(str(x) for x in throws)  # Make the list into a string to be able to apply regex to it.

match = re.findall(r"(?:[^6]|\A)(6{2})(?:[^6]|\Z)", throws_string)

assert len(match) == 2

中间的捕获组 (6{2}) 匹配我们需要的,它周围的非捕获组确保我们不匹配任何 3 个或更多 6 的簇。 \A\Z 需要匹配字符串的开头和结尾,否则 "not a six" [^6] 将查找不同的字符并找到 none.

注意 Python 中的变量名应该使用 snake_case,最重要的是,第一个字母应该小写以区分变量和 class 名称。

这是不使用任何扩展库的简单高效的解决方案。我们定义 stack 等于我们已经看到的连续 6 的数量,每次出现 6 以外的任何数字时(或在我们的抛出循环之后)我们检查是否 stack 等于 2,如果是这样,我们增加 counter_6 并将 stack 重置为 0

throws = [6,6,2,6,6,6,3,6,6,3,6,6,6]
counter_6 = 0
stack = 0

for i in throws:
    if i == 6:
        stack += 1
    else:
        if stack == 2:
            counter_6 += 1
        stack = 0
if stack == 2:
    counter_6 += 1

print(counter_6) # --> 2

使用 while 循环

Throws=[6,6,2,6,6,6,3,6,6,3,6,6,6]
Counter_6 = 0
i=0
while i < len(throws)-1:
 if throws[i]==throws[i+1] and throws[i] == 6:
  i=i+2
  Counter_6= Counter_6 + 1
else:
  i=i+1
print(Counter_6)