Münzwurf-Generator

Wenn du dir nicht sicher bist, in welchem der anderen Foren du die Frage stellen sollst, dann bist du hier im Forum für allgemeine Fragen sicher richtig.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@kbr: Sorry ich versteh's nicht. Meine 54% Ergebnis hat nichts mit dem zu tun was Du da beschreibst und doch, die Wahrscheinlichkeit das wenn ich eine von den 100.000 Sequenzen rauspicke und da dann mindestens eine Sechserreihe enthalten ist, ist bei mir 80%. Und müsste auch nach Deinem Text so sein, denn der beschreibt für mich zweimal das gleiche mit anderen Worten.

Vorausgesetzt Sechserreihe meint 6 oder mehr und nicht *genau* sechs und dann *muss* was anderes kommen. Aber *den* Unterschied lese ich bei Deinem Text nicht heraus. *Dann* käme aber auch weder 54% noch 80% heraus, denn *der* Unterschied kommt bei mir durch eine Interpretation von „K oder Z“ zustande was man ja auf zwei verschiedene Arten verstehen kann — inklusiv oder exklusiv.

Ich habe ja in Code selbst ausprobiert das ich auch 54% herausbekomme wenn ich das „oder“ anders interpretiere. Hast Du auch in Code 80% heraus bekommen oder vermutest Du nur das das wohl heraus kommt wenn man Deine Argumentation zugrunde legt und wir reden gerade aneinander vorbei?

@Zizibee: Bei dem vorgehen wie Du das beschreibst bin ich auf 80% gekommen. Den Code habe ich ja gepostet. Und ich würde auch sagen bei Wurf 1 und 2 ist mindestens eine Viererreihe. Auf 54% komme ich wenn ich das „K oder Z“ so interpretiere das nur entweder Wurf 1 *oder* Wurf 2 ein Treffer ist, aber nicht *beide*.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

@__blackjack__ Das ist ja merkwürdig, ich dachte ich habe das im Jupiter Notebook so umgesetzt, wie ich es eben erklärt habe:

Code: Alles auswählen

import random

REPEATS = 6
CHECKS = 10000
result_counter = 0

for _ in range(0, CHECKS):
    throws = [random.choice("ZK") for throw in range(0,100)]
    old_element = "-"
    same_element_counter = 0
    
    for element in throws:
        if old_element == element:
            same_element_counter = same_element_counter + 1
        else:
            same_element_counter = 0

        old_element = element

        if same_element_counter >= REPEATS:
            result_counter = result_counter + 1
            break
        
print(f'Gefunden {result_counter} von {CHECKS} => {result_counter / CHECKS * 100} %')
Gefunden 5454 von 10000 => 54.54 %
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Zizibee: Hm, und ich denke ich mache im Grunde das gleiche, bekomme aber 80% heraus. Ich versteh's nicht…

Die 54% bekomme ich wenn ich das „K oder Z“ exklusiv interpretiere und die Sechserreihe als „mindestens 6“. Aber Dein Code sieht nach „K oder Z“ inklusiv und Sechserreihe als „mindestens 6“ aus, und da bekomme ich 80%. Also entweder sehe ich den Fehler bei Dir nicht oder ich sehe den Fehler bei mir nicht. ☹️

Nah dran an 54%, nämlich eher so um die 55% bekomme ich bei „K oder Z“ inklusive und Sechserreihe als „exakt 6“.

Randbemerkung `throws` klingt falsch. Das würde wohl eher `tosses` oder `flips` heissen.

Hier mal die Ergebnisse für die vier Varianten:

Code: Alles auswählen

bj@s8n:~$ ./test
80.53% for inclusive or and at least n.
55.07% for inclusive or and exactly n.
54.50% for exclusive or and at least n.
32.58% for exclusive or and exactly n.
bj@s8n:~$ ./test
80.78% for inclusive or and at least n.
55.24% for inclusive or and exactly n.
54.73% for exclusive or and at least n.
32.41% for exclusive or and exactly n.
bj@s8n:~$ ./test
80.71% for inclusive or and at least n.
55.17% for inclusive or and exactly n.
54.45% for exclusive or and at least n.
32.50% for exclusive or and exactly n.
Und das Vala-Programm dazu:

Code: Alles auswählen

private static string create_random_coin_flips (size_t count) {
    var result = new StringBuilder.sized (count);
    for (int i = 0; i < count; ++i) {
        result.append_c ((Random.boolean ()) ? 'H' : 'T');
    }
    return result.str;
}

private static uint count_runs (
    string text, size_t size, bool just_heads, bool exact_size
) {
    var result = 0;
    try {
        var regex = new Regex (
            "([%s])\\1{%u}".printf ((just_heads) ? "H" : "HT", (uint) size - 1)
        );
        MatchInfo match_info;
        
        regex.match (text, 0, out match_info);
        while (match_info.matches ()) {
            if (exact_size) {
                int start, end;
                match_info.fetch_pos (0, out start, out end);
                if (text[start] != text[end]) ++result;
            } else {
                ++result;
            }
            match_info.next ();
        }
    } catch (RegexError error) {
        print ("Error: %s\n", error.message);
        assert (false);
    }
    return result;
}

private static double run_experiment(
    uint repetition_count,
    uint flip_count,
    uint run_length,
    bool just_heads,
    bool exact_size
) {
    var has_run_count = 0;
    for (int i = 0; i < repetition_count; ++i) {
        var flip_results = create_random_coin_flips (flip_count);
        var run_count = count_runs (
            flip_results, run_length, just_heads, exact_size
        );
        if (run_count > 0) ++has_run_count;
    }
    return (double) has_run_count / repetition_count;
}

public static void main () {
    var repetition_count = 100000;
    var flip_count = 100;
    var run_length = 6;
    string[] or_description = {"inclusive or", "exclusive or"};
    string[] run_description = {"at least n", "exactly n"};
    
    for (var or_variant = 0; or_variant < 2; ++or_variant) {
        for (var run_variant = 0; run_variant < 2; ++run_variant) {
            print (
                "%.2f%% for %s and %s.\n",
                100 *run_experiment (
                    repetition_count,
                    flip_count,
                    run_length,
                    (bool) or_variant,
                    (bool) run_variant
                ),
                or_description[or_variant],
                run_description[run_variant]
            );
        }
    }
}
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@Zizibee: Ich denke ich habe den Fehler in *Deinem* Programm gefunden. Es brauchte einfach nur einen Kaffee. Du testest nicht ob mindestens 6 in einer Reihe sind sondern ob mindestens 7 in einer Reihe sind. Denn wenn `old_element` ungleich `element` ist, dann darf man `same_counter` nicht auf 0 setzen sondern muss mit 1 anfangen. Man hat dann ja den 1. eines möglichen Laufs gefunden, den man mitzählen muss.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Jankie
User
Beiträge: 592
Registriert: Mittwoch 26. September 2018, 14:06

Was mache ich falsch, dass ich immer nur auf ca 74-77% komme?

Code: Alles auswählen

import random

def werfe_muenze(anzahl):
    return [random.choice(["K", "Z"]) for i in range(0, anzahl)]
    
def zaehle_vorkommen(ergebnisse):
    buchstabenfolge = "".join(ergebnisse)
    return buchstabenfolge.count("KKKKKK"), buchstabenfolge.count("ZZZZZZ")

def main():      
    anzahl_sechserserie_kopf = 0
    anzahl_sechserserie_zahl = 0
    for i in range(0,10000):    
        anzahl_kopf, anzahl_zahl = zaehle_vorkommen(werfe_muenze(100))
        anzahl_sechserserie_kopf += anzahl_kopf
        anzahl_sechserserie_zahl += anzahl_zahl
    print(f"Kopf {anzahl_sechserserie_kopf}")
    print(f"Zahl {anzahl_sechserserie_zahl}")
    
main()
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

@__blackjack__: Was du beschreibst, entspricht dem, was ich meinte: Man kann "Wiederholung" (das Worte hatte ich verwendet, in der Aufgabe steht es nicht) so verstehen, dass es eben das eigentliche Element + n Wiederholungen davon sind; also z.B. 1 Element + 6 Wiederholungen davon, was zu einer Gruppengröße von 7 führt . Das ist hier klar ein Programmierfehler (off-by-one-error), da in der Aufgabenstwellung von 6 mal die Rede ist, aber so bin ich im ersten Anlauf eben auf die 54% gekommen:

Code: Alles auswählen

#!/usr/bin/awk -f
function has_sixes(numbers,        i, repeats) {
    for (i=1; i<length(numbers); i++) {
        if (numbers[i] == numbers[i-1]) {
            repeats += 1;
        } else {
            repeats = 0;
        }
        # sic!
        if (repeats == 6) return 1;
    }
    # sic!
    if (repeats >= 6) {return 1} else {return 0};
}

BEGIN {
    srand();
    for (k=0; k<10000; k++) {
        for (j=0; j<100; j++) {
            p = rand();
            if (p<0.5) {
                numbers[j] = "K";
            } else {
                numbers[j] = "Z";
            }
        }
        stats[has_sixes(numbers)] += 1;
    }
    for (key in stats) {
        print key, stats[key]/100;
    }
}

Code: Alles auswählen

% ./flip.awk  
0 45.53
1 54.47
Zuletzt geändert von nezzcarth am Freitag 26. Juni 2020, 11:13, insgesamt 1-mal geändert.
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

Jankie hat geschrieben: Freitag 26. Juni 2020, 10:57 Was mache ich falsch, dass ich immer nur auf ca 74-77% komme?
Du wertest die Anzahl aus. Nach meinem Verständnis ist das nicht gefragt.

Vergleiche folgende Variante deines Codes:

Code: Alles auswählen

#!/usr/bin/env python3
import random

def werfe_muenze(anzahl):
    return [random.choice(["K", "Z"]) for i in range(0, anzahl)]
    
def zaehle_vorkommen(ergebnisse):
    buchstabenfolge = "".join(ergebnisse)
    return buchstabenfolge.count("KKKKKK") > 0 or  buchstabenfolge.count("ZZZZZZ") > 0

def main():      
    sechser = 0
    for i in range(10_000):    
        resultat= zaehle_vorkommen(werfe_muenze(100))
        sechser += resultat
    print(sechser)
    
main()

Code: Alles auswählen

% ./jankie.py
8021
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@nezzcarth: Die Variante hatte ich bis Zizibee seinen Code gezeigt hat überhaupt gar nicht auf dem Schirm. Also kann ich das in der Konversation mit Dir vorher nicht beschrieben haben‽ Was die Lauflänge angeht war da bei mir immer nur die Unterscheidung zwischen „mindestens 6“ oder „exakt 6“. Klar ergibt „exakt 6“ (fast) die gleiche Wahrscheinlichkeit wie „mindestens 1 + 6 Wiederholungen” aber der Test darauf sieht ja anders aus, weswegen ich da so überhaupt nicht drauf gekommen bin, dass Du das gemeint haben könntest.

Diese „1 + 6 Wiederholungen“ gibt der Aufgabentext IMHO nicht her, während er IMHO bei „mindestens 6“ oder „exakt 6“ wirklich interpretationsfähig wäre, wenn da am Ende die 80% nicht erwähnt werden würden.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
nezzcarth
User
Beiträge: 1764
Registriert: Samstag 16. April 2011, 12:47

@__blackjack__: Das habe ich undeutlich formuliert, entschuldige bitte. Ich meinte "beschrieben" in Bezug auf deinen Post um 11:44 an Zizibee in dem du den Fehler erklärst, nicht in Bezug auf deine und meine Konversation davor.

Und wie du schon sagst, der Aufgabentext gibt meine Interpretation nicht her, aber in die Falle bin ich halt getappt und habe mich über die 54% gewundert. :)
Benutzeravatar
kbr
User
Beiträge: 1508
Registriert: Mittwoch 15. Oktober 2008, 09:27

Ich werfe hier mal meinen Code rein. Als erstes berechne ich, wie häufig Sechserreihen in 100er Sequenzen zu finden sind und komme damit auf ca. 76%.

Code: Alles auswählen

import re
import random

pat = re.compile('1{6}')
runs = int(1e4)
choices = '0', '1'
sequence_size = 100

def has_match():
    return len(pat.findall(''.join(random.choice(choices) for _ in range(sequence_size))))

matches = sum(has_match() for _ in range(runs))
print(f'probability: {matches / runs * 100:4.1f} %')
Dann modifiziere ich has_match() um zu testen, ob eine Sequenz zumindest eine Sechserreihe enthält:

Code: Alles auswählen

def has_match():
    return bool(pat.search(''.join(random.choice(choices) for _ in range(sequence_size))))
Das ergibt dann ca. 54%. Die Differenz kommt dadurch zustande, dass die Sechserreihen nicht gleichverteilt über alle 100er Sequenzen vorkommen.

D.h., werden nur die 100er Sequenzen betrachtet, dann werden etwa 46% davon keine Sechserreihen enthalten.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

@kbr: Du hast also das „K oder Z“ als exklusives oder interpretiert im Gegensatz zum Aufgabensteller. Und der Code vor der Modifikation mit dem `bool` ist falsch. Also entweder der Code oder der Text in der `print()`-Ausgabe, denn das ist ja keine Wahrscheinlichkeit wenn man da `len()` statt `bool()` verwendet.
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Zizibee
User
Beiträge: 229
Registriert: Donnerstag 12. April 2007, 08:36

@__blackjack__: Danke fürs drüberschauen. Da nezzcarth auch 54 % als Ergbenis raus hatte, bin ich gar nicht auf die Idee gekommen, den Fehler in meinem Code zu suchen.
Benutzeravatar
kbr
User
Beiträge: 1508
Registriert: Mittwoch 15. Oktober 2008, 09:27

@__blackjack__: ja, ich hatte nur nach Kopf gesucht (möglicherweise hatte ich das 'oder' aus Kopf oder Zahl verinnerlicht). Wenn ich nach Kopf und Zahl suche komme ich auch auf 80% für mindestens eine Sechserreihe pro Sequenz.

Der Sinn von len() entspricht Aufgabe Teil 2. Das ergibt dann ca. 1.5 Sechserreihen pro Sequenz.
Benutzeravatar
__blackjack__
User
Beiträge: 14052
Registriert: Samstag 2. Juni 2018, 10:21
Wohnort: 127.0.0.1
Kontaktdaten:

Oh den 2. Teil habe ich gar nicht beachtet. Aber da stellt sie dann ja auch wieder die Frage wie eine Sechserreihe eigentlich definiert ist. Gibt ja drei Möglichkeiten. :-)
“Vir, intelligence has nothing to do with politics!” — Londo Mollari
Antworten