# Python Dice : Avoiding Triple Repetitions

I got this DICE puzzle to solve and my mind is stuck on a scenario.

How many times did it occur in the trial, that exactly two `6` were rolled after each other? For example, in sequence `56611166626634416` it occurred twice, that exactly two `6` were thrown after each other.

Question is: how to avoid letting the counter count those 666.

Note: I have tried multiple trackers (keys), but then I have another issue which is:

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)
``````

Counter should be equal to 2

On Best Solutions

Here's easy and efficient solution without using any extending libraries. We define `stack` that is equal to amount of consecutive `6`'s we've seen, every time any digit other than `6` occur (or after looping over our throws) we check whether `stack` is equal to `2`, if so we increment our `counter_6` and reset `stack` to `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
``````
On

A simpler approach I can think of is to mark the 3rd six in 3 consecutive sixes, by an integer which cannot occur in a throw of a dice. e.g. -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]
``````

After this, you can iterate through the list, and increate the counter when you encounter two consecutive 6s and the third element isn't -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
``````

This approach can be refined for sure.

On

`itertools.groupby()` will give you groups of consecutive numbers more or less out of the box:

``````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)]
``````

You can combine that with `collections.Counter` to get the counts of the `(6,6)` tuples:

``````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
``````
On

One possible approach is to use a regex. This way you can specify exact patterns and simply count how many times they occur, with the added benefit that this could also work for results for systems that have letters or symbols.

``````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
``````

The capturing group in the middle `(6{2})` matches what we need, and the non-capturing groups around it ensure that we don't match any cluster of 3 or more sixes. `\A` and `\Z` are required to match the start and end of the string, or else "not a six" `[^6]` will look for a different character and find none.

Note that variable names in Python should use `snake_case`, and crucially, the first letter should be lower case to distinguish variables from class names.