web-dev-qa-db-ja.com

退屈なものを自動化-コインフリップの筋

同じ問題でも、今ではたくさんの質問があることは知っていますが、少し違うアプローチを試みたと思います。

タスクは、100フリップのサンプルを10.000にして、すべてのサンプルにわたって6xのヘッドまたはテールのストリークの確率を計算することです(私が理解している限り)。しかし、以前の質問では、コーディングの問題は少しあいまいであると説明されていました。したがって、コード内のエラーを指摘するだけでいいのであれば、それは素晴らしいことです:)

私はできるかぎり怠惰にしようとしました。その結果、私のMacbookは本当に一生懸命働いていました。これは私のコードです。現在の値と前の値の比較の最初の反復で問題がありますか(私が理解している限り、インデックス-1(インデックス100)と現在の値を比較しますか?)

import random

#variable declaration

numberOfStreaks = 0
CoinFlip = []
streak = 0

for experimentNumber in range(10000):
    # Code that creates a list of 100 'heads' or 'tails' values.
    for i in range(100):
        CoinFlip.append(random.randint(0,1))
    #does not matter if it is 0 or 1, H or T, peas or lentils. I am going to check if there is multiple 0 or 1 in a row        

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

        if streak == 6:
            numberOfStreaks += 1

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

どこで混乱を起こしましたか?本当に見えない!

1
mr_harm

以下は、推定値を正しく計算する、最初に提供されたコードへのマイナーな変更のセットです。

_####_で始まるコメントを使用して変更をマークし、以下の説明を参照してそれらに番号を付けました。

_import random

#variable declaration

numberOfStreaks = 0

for experimentNumber in range(10000):
    # Code that creates a list of 100 'heads' or 'tails' values.
    CoinFlip = [] #### (1) create a new, empty list for this list of 100
    for i in range(100):
        CoinFlip.append(random.randint(0,1))
    #does not matter if it is 0 or 1, H or T, peas or lentils. I am going to check if there is multiple 0 or 1 in a row        

    #### # (6) example / test
    #### # if uncommented should be 100%
    #### CoinFlip = [ 'H', 'H', 'H', 'H', 'H', 'H', 'T', 'T', 'T', 'T', 'T', 'T' ]

    # Code that checks if there is a streak of 6 heads or tails in a row.
    streak = 1 #### (2, 4) any flip is a streak of (at least) 1; reset for next check
    for i in range(1, len(CoinFlip)): #### (3) start at the second flip, as we will look back 1
        if CoinFlip[i] == CoinFlip[i-1]:  #checks if current list item is the same as before
            streak += 1
        else:
            streak = 1 #### (2) any flip is a streak of (at least) 1

        if streak == 6:
            numberOfStreaks += 1
            break #### (5) we've found a streak in this CoinFlip list, skip to next experiment
                  #### if we don't, we get percentages above 100, e.g. the example / test above
                  #### this makes some sense, but is likely not what the book's author intends

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

これらの変更点の説明

以下は、これらの変更の簡単な説明です。それぞれがほぼ独立しており、コードの異なる問題を修正しています。

  1. 各実験の開始時のCoinFlipリストのクリア/作成
    • これがないと、新しい要素は前の実験のリストにaddedになります。
  2. 単一の_'H'_または_'T'_(または_1_または_0_)であっても、フリップが1 のストリークを表すことの確認
    • この変更がない場合、コードは実際には最初のコインフリップに対して6回続けて一致する必要があり、合計が7になります(少し直感的ではない代替変更は、_if streak == 6:_を_if streak == 5:_で置き換えることです)
  3. range(1, len(CoinFlip))を使用して2番目のフリップからチェックを開始します(n.b.リストにはゼロからインデックスが付けられます)
    • コードがリストに沿って振り返ると、0で始まるrange()を含むforループは、インデックス_0_をインデックス_-1_と誤って比較します( リストの最後の要素
  4. (スコープを移動し、)各チェックの前にstreakカウンターをリセットします
    • この変更を行わないと、実験の最初のストリークが前の実験の部分的なストリークに追加される可能性があります(推奨されるデモについてはコードのテストを参照)
  5. ストリークが見つかったら、チェックを終了します
    • 「2番目の部分は、ストリークがあるかどうかをチェックします」- Coin Flip Streaks

本のこの質問はやや不十分に指定されており、最後の部分は「--[少なくとも?]かどうかを確認する[single?]ストリークのいずれかを意味すると解釈できます- [precisely?] 6 [or more?]が見つかりました "。このソリューションはcheckをブール評価として解釈し(つまり、このリストにストリークが含まれていたか含まれていないことのみを記録し)、aを非排他的に解釈します(つまり、長い縞または複数の縞を数える;質問で提供されたコードでそうだったように)。

(オプション6.)コードのテスト

コメントアウトされた「例/テスト」を使用すると、通常ランダムに生成されるフリップを、すべての実験で同じ既知の値に切り替えることができます。この場合、100%として計算される固定リスト。タスク仕様の解釈に同意せず、(5。)で説明されているチェックの終了を無効にすると、すべての実験で6つの2つの異なる縞があるので、プログラムは200%を報告すると期待できます。この入力と組み合わせてbreakを無効にすると、それが正確に報告されます。

このタイプの手法(既知の入力を使用し、出力を確認する)を常に使用して、コードが主張どおりまたは期待どおりに機能するか機能しないかを納得させる必要があります。

固定入力_CoinFlip = [ 'H', 'H', 'H', 'H', 'T', 'T', 'T' ]_を使用して、(4。)で修正された問題を強調表示できます。元に戻すと、コードは6つの連続するHまたはTのストリークを含む実験(すべてこの入力を使用)の割合を50%として計算します。 (5.)は独立した問題を修正しますが、追加されたbreakを削除すると、エラーがさらに悪化し、計算されたパーセンテージが99.99%に上がります。この入力の場合、ストリーク6を含む計算されたパーセンテージは0%になります。

ここに提供されているように、完全なコードは約80%の推定値を生成します。これは意外かもしれませんが、 book の作成者は、これが事実である可能性があることを示唆しています。

本当にランダムなコインフリップで発生する可能性が非常に高いとしても、人間は6つの頭または6つの尾の連続をほとんど書きません。

-Al Sweigart、 Coin Flip Streaks

追加のソースを検討することもできます。 WolframAlpha は、「100枚のコインフリップで6頭の連なり」が発生する可能性がおよそ1 in 2であることを計算します。ここでは、6(以上)の頭のストリークor 6(以上)の尾のストリークが発生する可能性を推定しています。あなたはさらに可能性が高いと期待することができます。この累積的な効果のより簡単で独立した例として、通常のトランプのパックからハートを選ぶ確率は52分の13ですが、ハートを選ぶorダイヤモンドは52分の26になると考えてください。 。


計算上の注意

また、作者がパーセンテージの計算に近道を取っていることを理解するのにも役立ちます。これは、初心者が最終的な計算を見るのを混乱させるかもしれません。

パーセントが計算されます:

\frac{x}{total}\times100

total実行する実験の数は10000になることがわかっています

\frac{x}{10000}\times100

したがって

\frac{x}{10000}\times100=\frac{100x}{10000}=\frac{x}{100}

Postscript:最後の行で_100_を_100.0_に変更する自由をとった。これにより、コードはPython 2でパーセンテージを正しく計算できます。これは、質問と本で指定されているPython 3では必要ありません。

0
jtjacques

私のアマチュアの試み

import random

#reset strakes
numberOfStreaks = 0
#main loop
for experimentNumber in range(10000):

    # Code that creates a list of 100 'heads' or 'tails' values.
    # assure the list is empty and all counters are 0
    coinFlip=[]
    H=0
    T=0
    for fata in range(100):
        # generate random numbers for head / tails
        fata = random.randint(0,1)
        #if head, append 1 head and reset counter for tail
        if fata == 0:
            coinFlip.append('H')
            H += 1
            T = 0
        #else if tail append 1 tail and reset counter for head
        Elif fata == 1:
            coinFlip.append('T')
            T += 1
            H = 0

    # Code that checks if there is a streak of 6 heads or tails in a row.
    # when head and tail higher than 6 extract floored quotient and append it to numberOfStreaks,
    # this should take into consideration multiple streaks in a row.

    if H > 5 or T > 5:
        numberOfStreaks += (H // 6) or (T // 6) 

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

出力:

Chance of streak: 3.18%
0
Marius
import random
numStreaks = 0
test = 0
flip = []

#running the experiment 10000 times

for exp in range(10000):
    for i in range(100): #list of 100 random heads/tails

        if random.randint(0,1) == 0:
            flip.append('H')
        else:
            flip.append('T')

    for j in range(100): #checking for streaks of 6 heads/tails

        if flip[j:j+6] == ['H','H','H','H','H','H']:
            numStreaks += 1
        Elif flip[j:j+6] == ['T','T','T','T','T','T']:
            numStreaks += 1
        else:
            test += 1 #just to test the prog
            continue
print (test)
chance = numStreaks / 10000
print("chance of streaks of 6: %s %%" % chance )
0
Anu