Seite 1 von 1

Zufallsexperiment, Ergebnis plotten

Verfasst: Mittwoch 1. Juni 2022, 08:32
von PatrickF
Hallo zusammen,

wieder ein kleiner Versuch meinerseits: Ein Programm, was solange Wortkombinationen ausgibt, bis ein bestimmtes Wort gefunden wurde.
Wie immer etwas anfängerhafter 'Frankenstein-Code', da ich manche Snips von Stackoverflow etc. kopiere...

Code: Alles auswählen

import random
import string
import matplotlib.pyplot as plt
string.ascii_lowercase # or _uppercase or string.ascii_letters für Groß- und Kleinbuchstaben
def random_char(y):
    return ''.join(random.choice(string.ascii_lowercase) for x in range(y))

ergebnis=[]
durchgang=5

for _ in range (durchgang):
    zaehler=0
    while True:
        zaehler+=1
        suche="x"
        wort=random_char(len(suche))
        print (zaehler,"=",wort,"| ", end='')
        if (wort==suche):
            ergebnis.append(zaehler)
            print("<-- Gefunden")
            break
print(f"\nAnzahl der Durchgänge: {durchgang} / Menge jeweils: {ergebnis}/ Durchschnitt: {sum(ergebnis)/len(ergebnis)}")

# Ergebnis ausgeben

x = [1,2,3,4,5] # hier müsste irgendwie die Anzahl der Durchgänge als Variable rein?!
y = [ergebnis]
  
plt.plot(y)
plt.plot(x)
  
plt.xlabel('Durchgänge')

plt.ylabel('Benötigte Versuche')
 
plt.title('Ergebnis') 

plt.show()
Funktioniert soweit (wobei auf meiner Rechnermöhre mit Thonny sehr langsam bei längeren Wörtern), allerdings bekomme ich den Ergebnisplot nicht hin. Stelle mir vor dass auf der X-Achse die Durchgänge abgebildet werden und auf der Y-Achse die Anzahl, bis das gesuchte Wort erschien.

Macht es Sinn, die Ergebnisse in einem Tupel zu speichern statt einer Liste? Wie könnte man die einzelnen Durchgänge speichern für eine Art 'Gesamtübersicht'?

Ich weiß natürlich, dass man die Ergebnisse auch per Stochastik ganz einfach berechnen kann, ist halt for fun und zum lernen von Python...

Grußies
Pf

Re: Zufallsexperiment, Ergebnis plotten

Verfasst: Mittwoch 1. Juni 2022, 11:19
von __blackjack__
@PatrickF: Diese „ich weiss dass das nicht so gut ist, weil Anfänger“-Begründung zieht nicht wirklich. Wenn Du weisst das bestimmte Sachen schlecht sind, dann verbessere die. Sonst bleibt das immer so. Denn wenn Du nicht irgendwann mal anfängst zu lernen wie man sauber Programmiert, Namen sinnvoll wählt, und so weiter, wie soll das denn auf magische Weise später mal passieren?

Und auch kopierter Code ist kein Grund den nicht entsprechend zu überarbeiten.

Die Zeile wo ``string.ascii_lowercase`` mit dem Kommentar steht ist sinnfrei, weil das ``string.ascii_lowercase`` keinen Effekt hat. Das Kommentarzeichen sollte da wohl am Anfang der Zeile stehen. Und im Kommentar sollte man sich entweder für Deutsch oder für English entscheiden.

`random_char()` ist als Name inhaltlich falsch, weil das keine zufälligen Buchstaben erzeugt, sondern ein zufälliges Wort. Und der Name beschreibt auch keine Tätigkeit.

`y` sollte `length` heissen und da `x` nicht verwendet wird, würde man da per Konvention den Namen `_` verwenden.

`durchgang` ist kein guter Name für die Gesamtanzahl der Durchgänge. Da würde man als Leser eher die Nummer des aktuellen Durchgangs erwarten.

`ergebnis` als Einzahl für mehere Ergebnisse ist irreführend. Vielleicht auch der Grund warum Du dann später den Fehler gemacht hast diese Liste noch mal in eine Liste zu stecken.

Statt `zaehler` manuell hoch zu zählen, bietet sich `itertools.count()` an.

`suche` ist wieder kein guter Name für `gesuchtes_wort`. Man muss den immer gleichen Wert auch nicht für jeden Durchgang und jeden Rateversuch erneut definieren. Das kann man *einmal* am Anfang machen.

`x` kann man offensichtlich mit `range()`, `list()` und den passenden Argumenten erzeugen. Und `y` ist einfach nur ein umbenanntes `ergebnis`, warum also umbennen und nicht einfach `ergebnis` verwenden.

Es macht keinen Sinn die jeweilige Durchgangsanzahl zu plotten. Das ist einfach nur eine Gerade. Und ein „line plot“ macht bei diesen Daten keinen Sinn, weil zwischen den Werten ja gar keine Zwischenwerte existieren, die durch eine Linie interpoliert werden könnten.

Bei der Beschriftung ist dann "Durchgänge" sehr irreführend, denn die Zahl steht ja für die Nummer des Durchgangs und nicht die Anzahl der Durchgänge.

Zwischenstand:

Code: Alles auswählen

#!/usr/bin/env python3
import random
import string
from itertools import count

import matplotlib.pyplot as plt

#
# `string.ascii_lowercase` oder `string.ascii_uppercase` oder
# `string.ascii_letters` für Groß- und Kleinbuchstaben.
#
ALPHABET = string.ascii_lowercase


def create_random_word(length):
    return "".join(random.choice(ALPHABET) for _ in range(length))


DURCHGANGSANZAHL = 5


def main():
    gesuchtes_wort = "x"
    assert set(gesuchtes_wort).issubset(set(ALPHABET))

    versuchsanzahlen = []
    for _ in range(DURCHGANGSANZAHL):
        for zaehler in count(1):
            wort = create_random_word(len(gesuchtes_wort))
            print(zaehler, "=", wort, "| ", end="")
            if wort == gesuchtes_wort:
                versuchsanzahlen.append(zaehler)
                print("<-- Gefunden")
                break
    print(
        f"\nAnzahl der Ergebnisse: {len(versuchsanzahlen)} / Menge jeweils: {versuchsanzahlen}/ Durchschnitt: {sum(versuchsanzahlen)/len(versuchsanzahlen)}"
    )

    plt.scatter(range(1, len(versuchsanzahlen) + 1), versuchsanzahlen)
    plt.xlabel("Durchgang")
    plt.ylabel("Benötigte Versuche")
    plt.title("Ergebnis")
    plt.show()


if __name__ == "__main__":
    main()

Re: Zufallsexperiment, Ergebnis plotten

Verfasst: Donnerstag 2. Juni 2022, 09:04
von PatrickF
Bei den Variablennamen überlege ich in der Tat komplett auf englisch umzuswichen ( :D ), ist eventuell dann auch einfacher für nicht deutschsprachige.

Was bedeutet "x wird nicht verwendet?" Ist das eine Python-Konvetion? Danke für den Hinweis auf itertools.count(), kannte ich noch nicht.

Re: Zufallsexperiment, Ergebnis plotten

Verfasst: Donnerstag 2. Juni 2022, 09:25
von __blackjack__
Das `x` in ``''.join(random.choice(string.ascii_lowercase) for x in range(y))`` wird nicht verwendet. Bei der ``for``-Schleife im Hauptprogramm hast Du die Laufvariable ja schon `_` genannt. Der Name ist Konvention für Namen die man aus syntaktischen Gründen schreiben muss, deren Wert einen aber gar nicht interessiert. Neben Laufvariablen sieht man das auch öfter bei Zuweisungen an eine Namensliste wenn man mehrere Werte entpackt, aber nicht an allen interessiert ist.