Problem z zadaniem - rzuty monetą

0

Cześć

Mam problem z zadaniem z książki pt.Automate the Boring Stuff with Python

Siedzę nad tym drugi dzień i nie mogę wpaść na rozwiązanie - wiem, że kod jest brzydki, chciałbym, żeby na początek po prostu chodził, średnio to ogarniam, prawie cały kod powstał na zasadzie 'spróbuję tak, może zadziała, jak nie, to może tak..'.

W zadaniu chodzi o to, by wygenerować listę 100 rzutów, 'Head' / 'Tail' i sprawdzić jaka jest szansa, że przy 10 tysiącach takich list trafi się nam seria 6 takich samych wyników z rzędu (6x head lub 6x tail obok siebie). Przez kilka godzin w ciągu tych dwóch dni napisałem tyle:

# Coin Flip Streaks
import random

for experimentNumber in range(5):

    list_of_heads_tails = []

    for coin_flip in range(100):
        head_or_tail = random.randint(0, 1)
        if head_or_tail == 0:
            list_of_heads_tails.append('H')
        if head_or_tail == 1:
            list_of_heads_tails.append('T')

    #print(list_of_heads_tails)

    number_of_streaks = 0
    tails = 'T'
    heads = 'H'
    streaks = []
    
    for ht in range(len(list_of_heads_tails) - 5):
        
        if list_of_heads_tails[ht] == heads:
            if list_of_heads_tails[ht + 1] == heads:
                if list_of_heads_tails[ht + 2] == heads:
                    if list_of_heads_tails[ht + 3] == heads:
                        if list_of_heads_tails[ht + 4] == heads:
                            if list_of_heads_tails[ht + 5] == heads:
                                #print('There is a "H" streak!')
                                number_of_streaks += 1
        if list_of_heads_tails[ht] == tails:
            if list_of_heads_tails[ht + 1] == tails:
                if list_of_heads_tails[ht + 2] == tails:
                    if list_of_heads_tails[ht + 3] == tails:
                        if list_of_heads_tails[ht + 4] == tails:
                            if list_of_heads_tails[ht + 5] == tails:
                                #print('There is a "T" streak!')
                                number_of_streaks += 1
    
    streaks.append(total_streaks)
    print('Number of streaks: ' + str(number_of_streaks))

print(streaks)

Prawdopodobnie od tych ifów będą niektórych bolały oczy xD Próbowałem z pętlami, ale chwilowo odpuściłem, chcę, by to działało. Number_of_streaks to jest liczba trafionych szóstek w każdej 100-wynikowej liście. Chciałbym zsumować w tej chwili liczbę number_of_streaks z 5 prób, ale nie mogę do tego dojść.. próbowałem jakoś ze zmiennymi, operacje '+=', w pętli, poza pętlą, próbowałem stworzyć dodatkową listę i zaappendować wyniki, ale cały czas dochodzę do sytuacji gdzie pokazuje mi tylko ostatni wynik number_of_streaks. Może ktoś zechce podpowiedzieć jak to zrobić? Będę też wdzięczny za wszelkie sugestie.

Te listy jakoś mnie przerastają, pewnie powinienem spędzić nad nimi więcej czasu.

0

Moja rada to napisz program, w którym nie będziesz losować, tylko wpiszesz z palca. Oczywiście nie tak duże tablice. Powiedzmy 10 elementów. I pomysł jakbyś ty to rozwiązał na "kartce" i spróbuj to zakodzic. Jak się uda to podmień na randomkwk generowane i koniec :)

0
76021 napisał(a):

Chciałbym zsumować w tej chwili liczbę number_of_streaks z 5 prób, ale nie mogę do tego dojść.. próbowałem jakoś ze zmiennymi, operacje '+=', w pętli, poza pętlą, próbowałem stworzyć dodatkową listę i zaappendować wyniki, ale cały czas dochodzę do sytuacji gdzie pokazuje mi tylko ostatni wynik number_of_streaks. Może ktoś zechce podpowiedzieć jak to zrobić? Będę też wdzięczny za wszelkie sugestie.

Te listy jakoś mnie przerastają, pewnie powinienem spędzić nad nimi więcej czasu.

        total_streaks += number_of_streaks
0
76021 napisał(a):
        if list_of_heads_tails[ht] == heads:
            if list_of_heads_tails[ht + 1] == heads:
                if list_of_heads_tails[ht + 2] == heads:
                    if list_of_heads_tails[ht + 3] == heads:
                        if list_of_heads_tails[ht + 4] == heads:
                            if list_of_heads_tails[ht + 5] == heads:
                                #print('There is a "H" streak!')
                                number_of_streaks += 1
        if list_of_heads_tails[ht] == tails:
            if list_of_heads_tails[ht + 1] == tails:
                if list_of_heads_tails[ht + 2] == tails:
                    if list_of_heads_tails[ht + 3] == tails:
                        if list_of_heads_tails[ht + 4] == tails:
                            if list_of_heads_tails[ht + 5] == tails:
                                #print('There is a "T" streak!')
                                number_of_streaks += 1

Prawdopodobnie od tych ifów będą niektórych bolały oczy xD

Masz racje...

if twoja_lista == ['H', 'H', 'H', 'H', 'H', 'H'] or twoja_lista == ['T', 'T', 'T', 'T', 'T', 'T']:

albo zrób pętle, żeby sprawdzić ten warunek

0

Moim zdaniem to raczej ze stosownych wzorów, ale jak już musisz losować, to zwyczajnie sprawdzaj czy wylosowany element jest taki sam jak poprzedni, i zwiększaj licznik "lokalny" albo zmień poprzedni i ustaw go na jeden jak się wylosuje inna, Listy są w tu w zasadzie zbędne.

edit: co jak będzie 7 obok siebie? albo więcej? to jedna szóstka czy kilka?

0

Jakbyś sobie zrobił ''.join() na liście rzutów to zadanie sprowadziłoby się do wyszukiwania stringu w napisie. W mniejszej skali:

>>> 'HHHH' in 'HHTTHTHTHHHHT'
True
0
def find_multiple_head_or_tail(multiplicity=6):
    HEAD = "".join("H"*multiplicity)
    TAIL = "".join("T"*multiplicity)
    found = 0
    for attempt in range(10000):
        head_or_tail = "".join("H" if random.randint(0,1) == 0 else "T" for x in range(100))
        if HEAD in head_or_tail or TAIL in head_or_tail:
            found += 1
    return (found / 10000) * 100

print(find_multiple_head_or_tail(6))

Średnio 80% :P

0

Takie cuś wymyśliłem, jeśli ktoś bardziej doświadczony rzuci okiem i konstruktywnie skrytykuje to będę wdzięczny. ;) Wydaje mi się, że wynik jest dobry. Zdanie na końcu jest z książki, chodzi oczywiście o % szans na trafienie 6 takich samych w 100 rzutach. Wychodzi w zasadzie przy każdej próbce okolice 50% łącznie na wystąpienie 6 takich samych znaków pod rząd w każdych 100 próbach.

import random
heads = 0
tails = 0
for experiment_Number in range(0,100):
    head_or_tail = ['H' if random.randint(0, 1) == 0 else 'T' for x in range(100)]
    temp_list = []
    for flip in head_or_tail:
        temp_list.append(flip)
        if len(temp_list) == 6:
            result = temp_list.count(temp_list[0]) == len(temp_list)
            if result:
                if temp_list[0] == 'T':
                    tails = tails + 1
                else:
                    heads = heads + 1
            temp_list = []
print('Odds for 6 head in a row: %s%%' % (heads/100) + ' and odds for 6 tails in a row: %s%%' % (tails/100 ))
0

A może tak?

import random
tab = [random.choice(["H", "T"]) for x in range(100)]
total = 0
for i in range(95):
    if not "T" in tab[i:i+5]:
        total += 1
        continue
    if not "H" in tab[i:i+5]:
        total += 1
        continue
print(total)
0

@sig:

import random
heads = 0
tails = 0
for experiment_Number in range(0,10000):
   head_or_tail = ['H' if random.randint(0, 1) == 0 else 'T' for x in range(100)]
   print(head_or_tail)
   for i in range(94):
       if not 'T' in head_or_tail[i:i + 6]:
           heads += 1
           continue
       if not 'H' in head_or_tail[i:i + 6]:
           tails += 1
           continue
print(heads, tails)
print('Odds for 6 head in a row: %s%%' % (heads/100) + ' and odds for 6 tails in a row: %s%%' % (tails/100))

Zrobiłem coś takiego, idąc za Twoją poradą.Trochę się zgubiłem powiem szczerze przy tym zadaniu, czy czy wnik typu 150% jest poprawny? Bo aż mi się wierzyć nie chce, że średnio za każdym razem przynajmniej raz na 100 rzutów trafi się 6 reszek z rzędu. A może ja coś źle liczę.

0

Dodałem wyświetlanie samej tablicy i gdzie to jest


``````python
import random
tab = [random.choice(["H", "T"]) for x in range(100)]
total = 0
for i in range(95):
    if not "T" in tab[i:i+5]:
        print ("od ", i , "do ", i+5, tab[i:i+5])
        total += 1
        continue
    if not "H" in tab[i:i+5]:
        print ("od ", i + 1 , "do ", i+6, tab[i:i+5])
        total += 1
        

print(tab, "\n", total)
0

W ogóle, to po co Ci ta cała tablica, skoro w zasadzie to interesuje Ciebie sam wynik. Tablica Ci w ogóle nie potrzebna. Zwłaszcza, jeśli sobie umyślisz sprawdzać jakieś naprawdę potężne ciągi. Przecież i tak nie będziesz tej tablicy czytał, tylko wyniki Ci są potrzebne.
Z tego co pamiętam, to tego typu zadania były dobrze opisane w książce "Python dla programistów". Bardzo dobra książka tak w ogóle. Polecam.

0
Dodałem wyświetlanie samej tablicy i gdzie to jest

Tzn. Średnio częściej niż raz na 100 rzutów monetą występuje 6x reszka z rzędu lub orzeł. Po prostu myślałem, że jest to nie możliwe, aby było to tak często. Gdzieś na necie wyczytałem(ale chyba błędnie) że szansa na to powinna wynosić 50%, a trafia się to średnio 3x na 100 rzutów.

W ogóle, to po co Ci ta cała tablica, skoro w zasadzie to interesuje Ciebie sam wynik. Tablica Ci w ogóle nie potrzebna. Zwłaszcza, jeśli sobie umyślisz sprawdzać jakieś naprawdę potężne ciągi. Przecież i tak nie będziesz tej tablicy czytał, tylko wyniki Ci są potrzebne. Z tego co pamiętam, to tego typu zadania były dobrze opisane w książce "Python dla programistów". Bardzo dobra książka tak w ogóle. Polecam.

To zadanie jest z książki po prostu, i założenia są tam takie, aby wykorzystać do tego tablicę, poszukam i pomyślę, jakby można było to zrobić bez używania tablicy, bo szczerze mówiąc nie mam zielnoego pojęcia na ten moment. Bo gdzieś to trzeba sprawdzać.

1

wersja bez tablicy, po prostu pamięta poprzedni rzut i z nim porównuje rozrzut ma całkiem spory, od 0 do 10

import random
total = 0
before = ""
temp = 0
for i in range(100):
    throw = random.choice(["T", "H"])
    if throw == before:
        temp += 1
        if temp >= 6:
            total += 1
    else:
        before = throw
        temp = 1
print(total)

0
Dzikiwąż napisał(a):

Bo gdzieś to trzeba sprawdzać.

Tworzysz zmienne, których używasz jako liczniki. Do tego masz dwie zmienne - obecna i poprzednia, Jeśli obecna liczba to parzysta (czy tam np. reszka) i poprzednia też, to wtedy sobie gdzieś tam w innych zmiennych to zliczasz wedle potrzeby. Jeśli obecna jest parzysta a poprzednia nie to zerujesz ten główny licznik. Oczywiście po każdym porównaniu podstawiasz obecną na poprzednią i losujesz nową obecną. I tak się to kręci.

Edit
A no właśnie, np. tak jak to kolega wyżej w tej samej chwili napisał.

0

Zawsze możesz też zmniejszyć rozmiar tablicy do np 10, i przygotować własne tablice gdzie będziesz z góry znał ilość takich zdarzeń. I dzięki temu przetestować różne algorytmy / poprawiać je aż przejdą twoje testy.

0

Jaki tutaj powinien wyjść ostatecznie wynik?

Jaki jest poziom tego zadania? Nie poradziłem sobie z nim, byłem w stanie napisać część kodu, ale ostatecznie skopiowałem kod z SO, przeanalizowałem krok po kroku na pythontutor jak działa program i wprowadziłem poprawki. Czyszczenie listy przed utworzeniem nowej oraz wyzerowanie zmiennej streak po inkrementacji numberOfStreaks. Jakie mogę z tego wyciągnąć wnioski? (początkujący)

Wychodzi ok. 0.08%

import random

numberOfStreaks = 0
coinFlip = []
streak = 0

for experimentNumber in range(10000):
    # Code that clears the list
    coinFlip.clear()
    # Code that creates a list of 100 'heads' or 'tails' values.
    for i in range(100):
        coinFlip.append(random.randint(0,1))     

    # Code that checks if there is a streak of 6 heads or tails in a row.
    for i in range(len(coinFlip)):
        if i == 0:
            pass
        elif coinFlip[i] == coinFlip[i-1]:  #checks if current list item is the same as before
            streak += 1 

        if streak == 6:
            numberOfStreaks += 1
        
        if streak == 6:
            streak -= 6

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

W sprawdzarce jest błąd, dałem jej "na sztywno" 12 jedynek i wyrzuciła 1 zamiast 2, potrzebna 13 żeby zadziałała poprawnie. oto mój kod


coinFlip = [1, 1, 1, 1,1, 1, 1, 1,1, 1, 1, 1]
print(len(coinFlip))
streak = 0
numberOfStreaks = 0
#print(len(coinflip))
for i in range(len(coinFlip)):
        if i == 0:
            pass
        elif coinFlip[i] == coinFlip[i-1]:  #checks if current list item is the same as before
            streak += 1 

        if streak == 6:
            numberOfStreaks += 1

        if streak == 6:
            streak -= 6
print('było', (numberOfStreaks))

1 użytkowników online, w tym zalogowanych: 0, gości: 1