Создание случайного списка и подсчет последовательности из 6 букв - PullRequest
1 голос
/ 07 марта 2020

Я пытаюсь создать программу, которая создаст случайный список голов или хвостов ('H', 'T'), а затем посчитает, сколько раз повторяется либо "H", либо "T" 6 раз. Я думаю, что я выяснил случайный список, который прекрасно работает, когда я запускаю его независимо. Но когда дело доходит до подсчета, я не уверен, как заставить python обнаружить последовательность из 6 одинаковых букв в списке.

for x in range(0, len(coin_list)-1):
    if coin_list[x] == coin_list[x+1] and coin_list[x] == coin_list[x+2] and \
    coin_list[x] == coin_list[x+3] and coin_list[x] == coin_list[x+4] and \
    coin_list[x] == coin_list[x+5]:
       streak_counter+=1
    else:
        continue

    if streak_counter ==6: 
        numberOfStreaks+=1
        streak_counter=0
    else: 
        continue

Сначала этот блок проверяет каждое значение в списке coin_list , а также проверяет, все ли 5 ​​следующих после него значений идентичны первому значению. Если это так, то переменная streak_counter увеличивается на единицу. Затем программа проверяет, равна ли переменная streak_counter 6, если она есть, то переменная numberOfStreaks увеличивается на единицу, а streak_counter сбрасывается в 0.

Когда я запускаю эту программу, я не получаю ожидаемого результата. Программа всегда возвращает, что numberOfStreaks равно 0, и, следовательно, процент полос равен 0%.

Не уверен, где я здесь не так. Любая помощь приветствуется.

import random
numberOfStreaks = 0


for experimentNumber in range(10000):
    # Code that creates a list of 100 'heads' or 'tails' values.
    for i in range(100):
        coin_list=[]
        random_num=random.randint(0, 1)
        if random_num == 1:
            coin_list.append('H')
        elif random_num == 0:
            coin_list.append('T')

    # Code that checks if there is a streak of 6 heads or tails in a row.
    for x in range(0, len(coin_list)-1):
        if coin_list[x] == coin_list[x+1] and coin_list[x] == coin_list[x+2] and \
        coin_list[x] == coin_list[x+3] and coin_list[x] == coin_list[x+4] and \
        coin_list[x] == coin_list[x+5]:
           streak_counter+=1
        else:
            continue

        if streak_counter ==6: 
            numberOfStreaks+=1
            streak_counter=0
        else: 
            continue


print(numberOfStreaks)
print('Chance of streak: %s%%' % (numberOfStreaks / 100))

Ответы [ 3 ]

2 голосов
/ 07 марта 2020

что не так с текущей реализацией (генерация списка монет)

В коде, который генерирует ваш список, вы создаете пустой список для каждой записи, которая должна быть в вашем списке.

for i in range(100):
    coin_list=[]   # <-- here you create an empty list
    random_num=random.randint(0, 1)
    if random_num == 1:
        coin_list.append('H')
    elif random_num == 0:
        coin_list.append('T')

проверка длины списка монет:

len(coin_list)

output: 1

идеи, как это исправить

Это можно исправить, определив список за пределами l oop:

coin_list=[]
for i in range(100):

    random_num=random.randint(0, 1)
    if random_num == 1:
        coin_list.append('H')
    elif random_num == 0:
        coin_list.append('T')

Поскольку вы все равно используете random, вы можете посмотреть random.choice:

coin_list = []
coins = ['H', 'T']
for i in range(100):
    coin_list.append(random.choice(coins))

В обоих исправленных случаях длина списка равна 100.

что не так с подсчетом полос

Далее, streak_counter не определено до ссылки, поэтому должно быть определено:

streak_counter = 0

L oop Если вы напишете для проверки наличия полос, вы столкнетесь со следующей ошибкой:

IndexError: list index out of range

Это потому, что вы пропустили x от 0 до длины вашего списка -1, но затем использовали x + 2,3, 4,5 для доступа к элементам списка. Когда ваш l oop достигнет 4-го элемента в конце списка, он попытается получить доступ к элементу вне списка, что приведет к ошибке.

for x in range(0, len(coin_list)-1):
    if coin_list[x] == coin_list[x+1] and coin_list[x] == coin_list[x+2] and \
    coin_list[x] == coin_list[x+3] and coin_list[x] == coin_list[x+4] and \
    coin_list[x] == coin_list[x+5]:  # < -- here you are accessing x+5
       streak_counter+=1
    else:
        continue

    if streak_counter ==6: 
        numberOfStreaks+=1
        streak_counter=0
    else: 
        continue

Исправление для этого было бы позволить x работать от 0 до len(list)-5, это позволило бы завершить l oop. Тем не менее, способ проверки полосы является немного своеобразным:

for x in range(0, len(coin_list)-5):
    print(x)
    if coin_list[x] == coin_list[x+1] and coin_list[x] == coin_list[x+2] and \
    coin_list[x] == coin_list[x+3] and coin_list[x] == coin_list[x+4] and \
    coin_list[x] == coin_list[x+5]:
        streak_counter+=1
    else:
        continue

Оператор if проверяет, есть ли шесть последовательных идентичных записей в вашем списке. Если это так, вы увеличиваете streak_counter.

Далее вы проверяете, является ли streak_counter 6, затем вы считаете это штрихом и шагом numberOfStreaks.

if streak_counter ==6: 
    numberOfStreaks+=1
    streak_counter=0
else: 
    continue

Проблема в том, что для streak_counter, равного 6, условие if coin_list[x] == ... должно быть выполнено шесть раз. Итак, вам нужно как минимум 11 последовательных идентичных значений, чтобы зарегистрировать полосу из шести.

пытается исправить это

Теперь, как решить эту проблему, я думаю, зависит от того, как вы считаете полосы: последовательность из 7 голов одна полоса из семи или две полоски из шести?

Для первого случая вы могли бы сделать что-то вроде этого:

s = ''.join(coin_list) # convert everything to string

tails_streaks = []
heads_streaks = []

for tails in s.split('H'): # remove all heads and check if what remains is at least 6 long
    if len(tails) >=6:
        tails_streaks.append(len(tails))

for heads in s.split('T'): # ditto for tails
    if len(heads) >=6:
        heads_streaks.append(len(heads))

Если вы хотите сосчитать все вхождения из шести последовательных идентичных результатов (что означает подсчет одной монеты несколько раз):

tails_sixes = []
heads_sixes = []

for tails in s.split('H'):
    if len(tails) >=6:
        tails_sixes += 1 + len(tails) - 6 

for heads in s.split('T'):
    if len(heads) >=6:
        heads_sixes += 1 + len(tails) - 6
0 голосов
/ 07 марта 2020

Используйте zip для формирования полосы и подсчитайте те, которые имеют только одно значение:

from random import choice
from itertools import islice

flipCount = 20
streakSize = 6

coinList    = [choice("HT") for _ in range(flipCount)]
allHeads    = tuple("H",)*streakSize
allTails    = tuple("T",)*streakSize
streakCount = sum( s==allHeads or s==allTails
                   for s in zip(*(islice(coinList,i) for i in range(streakSize))))

output:

print("".join(coinList))
print(streakCount)

# HHHHTTHHHHHHHTTHTHHH
# 2
0 голосов
/ 07 марта 2020

1) Как написано, вы должны увеличивать количество последовательностей при streak_counter == 1, потому что вы увеличиваете его на 1 при обнаружении полосы . Вы, вероятно, получаете 0, потому что шансы на полосу 11 намного ниже.

2) Как сказал Błotosmętek, было бы проще просто сделать строку (str1 = ''.join(coint_list)), а затем использовать метод count строки (str1.count('HHHHHH')). Если вы хотите сосчитать все серии с 6 длинами (например, HHHHHHH = 2 серии), просмотрите ответы здесь.

Обновление: я провел некоторое тестирование и обнаружил, что метод регулярных выражений в связанный ответ для всех прогонов 6 намного быстрее. Вот тестовый сценарий, который я использовал

from random import randint as randi
import re
import timeit


# Create test list
longg = ['H' if randi(0,1) == 1 else 'T' for i in range(10000)]
longg = ''.join(longg)


def regVer(s):
    matches = re.finditer(r'(?=(H{6}|T{6}))',s)
    return len(list(matches))

def listVer(s):
    n = 6
    li = [s[i:i+n] for i in range(len(s)-n+1)]
    count = 0
    for i in li:
        if i == 'H'*6 or i == 'T'*6:
            count += 1
    return count

print('regCount: {}'.format(regVer(longg)))
print('Time elapsed: {}'.format(timeit.timeit('regVer(longg)', number=100, globals=globals())))
print('listCount: {}'.format(listVer(longg)))
print('Time elapsed: {}'.format(timeit.timeit('listVer(longg)', number=100, globals=globals())))

, который дал следующий вывод:

regCount: 356
Time elapsed: 0.070616307
listCount: 356
Time elapsed: 0.281572281

Может быть, я просто глуп, как сделать понимание списка?

...