Pasjansowy zegar czy zegarowy pasjans?

https://xpil.eu/tbs

Solitaire znaj膮 wszyscy[citation needed]. Wyk艂ada艂y go nasze babcie i prababcie, by艂 te偶 do艂膮czany przez Microsoft do wi臋kszo艣ci wersji Windows.

Jest jednak wiele innych pasjans贸w. Jeden z nich - kt贸rego nauczy艂a mnie babcia - to Zegar.

Zegar jest - w odr贸偶nieniu od Solitaire - pasjansem stuprocentowo deterministycznym. Innymi s艂owy wynik zale偶y wy艂膮cznie od pocz膮tkowego potasowania talii. Nie ma tu 偶adnego miejsca na my艣lenie, na decydowanie; po prostu robimy krok po kroku to, co ka偶膮 nam karty. Ma艂o tw贸rcze, ale czasem cz艂owiek potrzebuje[citation needed] mechanicznego, bezmy艣lnego przek艂adania kart. Taki reset.

Szczeg贸艂y samego pasjansa dobrze obja艣nia 艁ukasz z portalu Przystanek Plansz贸wka (KLIK), sk膮d zreszt膮 ukrad艂em obrazek do dzisiejszego wpisu. Je偶eli kto艣 nie zna Zegara, mo偶e sobie tam poczyta膰. Tutaj natomiast poka偶臋 jak zrobi膰 symulacj臋 Zegara w Pythonie aby sprawdzi膰 jak cz臋sto wychodzi, a jak cz臋sto - nie wychodzi.

Zanim zaczn臋, powiem jeszcze, 偶e za dzieciaka wyk艂ada艂em Zegar do艣膰 cz臋sto. Nie pami臋tam ile razy mi si臋 uda艂o "wygra膰", ale by艂y to przypadki bardzo rzadkie.

OK, lecimy:

from random import sample
wygrane, ilosc_prob = 0, 100000

for proba in range(ilosc_prob):
    stos = sample(range(52), 52)  # tasujemy tali臋

    # zegar to lista list:
    # zewn臋trzna lista ma 13 element贸w (12 godzin plus stosik na 艣rodku)
    # ka偶dy z 13 element贸w jest list膮 4-elementow膮 (stos 4 kart)
    # przyk艂adowo zegar[11][0] to pierwsza karta godziny 11
    zegar = []

    for i in range(13):  # rozk艂adamy zegar
        zegar.append(stos[i::13])

    krole = 0  # licznik kr贸li (kr贸l贸w?)

    karta = 0  # startujemy od 艣rodka zegara
    while 1:  # gramy!
        karta = zegar[karta % 13].pop()  # bierzemy kolejn膮 kart臋
        if karta % 13 == 0:  # je偶eli trafili艣my na kr贸la
            krole += 1  # liczymy go
            if krole == 4:  # je偶eli to ostatni kr贸l
                break  # koniec pasjansa

    # je偶eli odkryli艣my wszystkie 12 godzin zegara, uda艂o si臋
    if(sum(map(lambda x: x == [], zegar)) == 12):
        wygrane += 1

print(wygrane/ilosc_prob)

Przy liczbie pr贸b 1M (lub wi臋cej) wynik prawie zawsze wychodzi w okolicach 0.077. A wi臋c 77 razy na 1000 pasjans wychodzi. Pozosta艂e 923 razy - nie wychodzi.

Najbardziej frustruj膮ce jest, kiedy ju偶 prawie, prawie wyszed艂, odkryli艣my 11 godzin, brakuje tylko jednej - i ostatni kr贸l pojawia si臋 odrobin臋 za wcze艣nie.

No dobra. Skoro pasjans nie wychodzi za cz臋sto, mo偶e spr贸bujmy policzy膰 ile 艣rednio godzin uda si臋 odkry膰 zanim pojawi si臋 czwarty kr贸l?

from random import sample
wygrane, ilosc_prob, odkryte = 0, 100000, 0

for proba in range(ilosc_prob):
    stos = sample(range(52), 52)  # tasujemy tali臋

    # zegar to lista list:
    # zewn臋trzna lista ma 13 element贸w (12 godzin plus stosik na 艣rodku)
    # ka偶dy z 13 element贸w jest list膮 4-elementow膮 (stos 4 kart)
    # przyk艂adowo zegar[11][0] to pierwsza karta godziny 11
    zegar = []

    for i in range(13):  # rozk艂adamy zegar
        zegar.append(stos[i::13])

    krole = 0  # licznik kr贸li (kr贸l贸w?)

    karta = 0  # startujemy od 艣rodka zegara
    while 1:  # gramy!
        karta = zegar[karta % 13].pop()  # bierzemy kolejn膮 kart臋
        if karta % 13 == 0:  # je偶eli trafili艣my na kr贸la
            krole += 1  # liczymy go
            if krole == 4:  # je偶eli to ostatni kr贸l
                break  # koniec pasjansa

    # zliczamy ilo艣膰 odkrytych godzin
    odkryte += sum(map(lambda x: x == [], zegar))

print(odkryte/ilosc_prob)

Modyfikacja jest niewielka: zamiast zlicza膰 wygrane pasjanse, po ka偶dym pasjansie zliczamy ilo艣膰 odkrytych godzin.

Ile razy bym tego nie uruchamia艂, zawsze wychodzi mi oko艂o 6.99. Czyli wyk艂adaj膮c Zegar mo偶emy si臋 spodziewa膰, 偶e odkryjemy siedem godzin zanim trafimy na ostatniego kr贸la.

Wyja艣nienie sposobu liczenia odkrytych godzin:

Operator map dzia艂a tak, 偶e wywo艂uje zadan膮 funkcj臋 dla ka偶dego elementu zadanej listy i zwraca list臋 wynik贸w. W naszym przypadku list膮 jest zegar po zako艅czeniu pasjansa, a funkcj膮 jest sprawdzenie, czy element listy jest sam w sobie pust膮 list膮 (x == []). Na ko艅cu sumujemy wynik. Operator por贸wnania zwraca True / False, kt贸re s膮 traktowane przez sum jako 1 / 0.

https://xpil.eu/tbs

Leave a Comment

Komentarze mile widziane.

Je偶eli chcesz do komentarza wstawi膰 kod, u偶yj sk艂adni:
[code]
tutaj wstaw sw贸j kod
[/code]

Je偶eli zrobisz liter贸wk臋 lub zmienisz zdanie, mo偶esz edytowa膰 komentarz po jego zatwierdzeniu.