puzzler
puzzler

Reputation: 5

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

Upvotes: 0

Views: 271

Answers (5)

supercar lover
supercar lover

Reputation: 45

use a while loop

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)

Upvotes: 0

theberzi
theberzi

Reputation: 2645

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.

Upvotes: 0

Mark
Mark

Reputation: 92440

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

Upvotes: 2

Filip Młynarski
Filip Młynarski

Reputation: 3612

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

Upvotes: 0

Devesh Kumar Singh
Devesh Kumar Singh

Reputation: 20490

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.

Upvotes: 0

Related Questions