Seite 1 von 1

Fehler bei leerer Liste bei min(liste)

Verfasst: Dienstag 16. August 2022, 21:25
von Pitwheazle
Damit meine Würfelchen hier nur dort stehen, wo sie ein Fundament haben, musste ich einen komplizierten Code schreiben.
Bild
Dazu muss ich den kleinsten Wert in einer Liste bestimmen. Wenn die Liste leer ist, bekomme ich einen Fehler - kann ich das vermeiden?

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Dienstag 16. August 2022, 21:29
von Sirius3
Was meinst Du von "Fundament"? Und welcher komplizierte Code?

Zur Frage: in dem Du prüfst, ob die Liste leer ist.

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Dienstag 16. August 2022, 22:08
von Pitwheazle
Ich hatte es mit if liste probiert, aber mich anscheinend vertippt. Jetzt scheint es zu funktionieren.
Zur Frage:
Die Würfelchen werden mit Zufallszahlen erzeugt und da kann ja kein Würfelchen in der Luft hängen. Mit dem Code habe ich mir ziemlich einen abgebrochen - ob er aber elegant ist, wage ich zu bezweifeln. Willst du ihn wirklich sehen?

Code: Alles auswählen

            titel = "Räumliches Vorstellungsvermägen"
            text = "Ups, bei diesem Würfel sind ein paar Bausteine verlorengegeangen.<br>Wieviele sind es?"
            hilfe = ""
            anmerkung = ""
            h_hoehe = 200
            h_breite = 200
            h_n = 6
            t_n = h_n
            v_n = h_n
            start_x = int(h_breite/2) - h_n*10 + t_n*3
            start_y = int(h_hoehe/2) + v_n*10 - t_n*3
            liste = []
            soll = (h_n-1) * (t_n-1) * (v_n-1)
            ist = 0
            for n in range(1, h_n):
                liste.append(n)
                liste.append(n)
            schieb = []
            fehlt_v = []                                            #Liste mit den fehlenden Klötzchen in der vorderen Reihe
            fehlt_r =[]                                             #Liste mit den fehlenden Klötzchen in der rechten Reihe
            for v in range(1, v_n-1):
                for t in range(1, t_n):
                    for h in range(1, h_n):
                        if v == v_n-2 and t == t_n-1:               #sorgt für fehlende Klötzchen in der vorderen Reihe der vorletzten Schicht
                            zuza = random.randint(1,10)
                            if zuza < 8:
                                schieb.append((h*20+start_x-int(t*20*0.3), start_y+t*6-v*20))
                                ist += 1
                            else:
                                fehlt_v.append(h)
                        else:
                            if v == v_n-2 and h == h_n-1:           #sorgt für fehlende Klötzchen in der rechten Reihe der vorletzten Schicht
                                zuza = random.randint(1,10)
                                if zuza < 5:
                                    schieb.append((h*20+start_x-int(t*20*0.3), start_y+t*6-v*20))  
                                    ist += 1
                                else:
                                    fehlt_r.append(t)
                            else:
                                schieb.append((h*20+start_x-int(t*20*0.3), start_y+t*6-v*20))
                                ist += 1
            if fehlt_r:
                fehlt_r_min = fehlt_r[0]
            else:
                fehlt_r_min = 1
            for t in range(1, h_n):
                random.shuffle(liste)  
                list=set(liste[:h_n-2])
                for h in (list):
                    if t < t_n-1 or (h>0 and h not in fehlt_v):
                        if h < h_n-1 or (t < fehlt_r_min):
                            schieb.append((h*20+start_x-int(t*20*0.3), start_y+t*6-(v_n-1)*20))
                            ist += 1                          
            erg = (soll-ist)  

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Dienstag 16. August 2022, 22:42
von narpfel
`min` hat das gewünschte Verhalten schon eingebaut.

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Mittwoch 17. August 2022, 13:08
von Sirius3
Kommentare sollten beschreiben, was der Code macht. Wenn man sie außerhalb des rechten Randes des Editors versteckt, dann sind sie wenig hilfreich. Deshalb schreibt man Kommentare immer in der Zeile vor der, die sie beschreiben soll.
Die Berechnung der Würfelposition tauch vier mal im Code auf, was nicht nur schlecht ist, weil sich hier eine Rechnung wiederholt, sondern auch, weil sie den Code schwer lesbar macht, weil man immer wieder die selbe komplizierte Rechnung lesen und verstehen muß.
Eine Funktion sollte nur eine Sache machen, also entweder Würfel auswürfeln oder die Position von Würfeln berechnen.
Dann sollte man Dinge erst dann brechenen, wenn man sie auch braucht, und nicht viele Zeilen davor, wie bei `liste` oder `soll`. `ist` ist einfach nur die Länge der Liste `schieb` also ist das unnötig, selbst mitzuzählen.

Ohne irgend was am Algorithmus verändert zu haben, wirkt der Code schon viel strukturierter:

Code: Alles auswählen

    titel = "Räumliches Vorstellungsvermägen"
    text = "Ups, bei diesem Würfel sind ein paar Bausteine verlorengegeangen.<br>Wieviele sind es?"
    hilfe = ""
    anmerkung = ""
    h_n = 6
    t_n = h_n
    v_n = h_n
    schieb = []
    # Liste mit den fehlenden Klötzchen in der vorderen Reihe
    fehlt_v = []
    # Liste mit den fehlenden Klötzchen in der rechten Reihe
    fehlt_r =[]
    for v in range(1, v_n-1):
        for t in range(1, t_n):
            for h in range(1, h_n):
                # sorgt für fehlende Klötzchen in der vorderen Reihe der vorletzten Schicht
                if v == v_n-2 and t == t_n-1:
                    zuza = random.randint(1,10)
                    if zuza < 8:
                        schieb.append((h, t, v))
                    else:
                        fehlt_v.append(h)
                else:
                    # sorgt für fehlende Klötzchen in der rechten Reihe der vorletzten Schicht
                    if v == v_n-2 and h == h_n-1:
                        zuza = random.randint(1,10)
                        if zuza < 5:
                            schieb.append((h, t, v))
                        else:
                            fehlt_r.append(t)
                    else:
                        schieb.append((h, t, v))
    if fehlt_r:
        fehlt_r_min = fehlt_r[0]
    else:
        fehlt_r_min = 1


    liste = []
    for n in range(1, h_n):
        liste.append(n)
        liste.append(n)
    for t in range(1, h_n):
        random.shuffle(liste)  
        list=set(liste[:h_n-2])
        for h in list:
            if t < t_n-1 or (h>0 and h not in fehlt_v):
                if h < h_n-1 or (t < fehlt_r_min):
                    schieb.append((h, t, v_n))

    h_hoehe = 200
    h_breite = 200
    start_x = int(h_breite/2) - h_n*10 + t_n*3
    start_y = int(h_hoehe/2) + v_n*10 - t_n*3
    schieb_positionen = [
        (h * 20 + start_x - int(t * 20 * 0.3), start_y + t * 6 - v * 20)
        for h, t, v in schieb
    ]
    soll = (h_n-1) * (t_n-1) * (v_n-1)
    ergebnis = soll - len(schieb)
Ein Set `list` zu nennen, ist aus vielerlei Dingen schlecht. `list` ist der eingebaute Datentyp und sollte nicht durch Variablennamen überdeckt werden. Typen sollten keine Variablennamen sein, vor allem keine falschen.
Der nächste Punkt sind wieder schlechte Variablennamen. h_n, t_n, v_n sollten wohl besser anzahl_wuerfel_in_der_hoehe_plus_eins oder kurz anzahl_hoehe_plus_eins, anzahl_tiefe_plus_eins, anzahl_breite_plus_eins. Entscheiden hier ist, dass Du das plus_eins unterschlagen hast. Ohne das, wundert sich jeder, warum da eine 6 steht, obwohl doch nur fünf Würfel da sind. Ähnliches Problem sind Deine Zufallszahlen (zuza? wirklich?) Mit welcher Wahrscheinlichkeit ist eine Zahl zwischen 1 und 10 kleiner als 5? 40%, also wieder eins daneben.
Da dieses Mißverständnis eine große Fehlerquelle gilt es als erstes, das plus_eins loszuwerden:

Code: Alles auswählen

    titel = "Räumliches Vorstellungsvermägen"
    text = "Ups, bei diesem Würfel sind ein paar Bausteine verlorengegeangen.<br>Wieviele sind es?"
    hilfe = ""
    anmerkung = ""
    anzahl_breite = 5
    anzahl_tiefe = anzahl_breite
    anzahl_hoehe = anzahl_breite
    schieb = []
    # Liste mit den fehlenden Klötzchen in der vorderen Reihe
    fehlt_v = []
    # Liste mit den fehlenden Klötzchen in der rechten Reihe
    fehlt_r =[]
    for v in range(anzahl_hoehe - 1):
        for t in range(anzahl_tiefe):
            for h in range(anzahl_breite):
                # sorgt für fehlende Klötzchen in der vorderen Reihe der vorletzten Schicht
                if v == anzahl_hoehe - 2 and t == anzahl_tiefe - 1:
                    if random.random() < 0.7:
                        schieb.append((h, t, v))
                    else:
                        fehlt_v.append(h)
                # sorgt für fehlende Klötzchen in der rechten Reihe der vorletzten Schicht
                elif v == anzahl_hoehe - 2 and h == anzahl_breite - 1:
                    if random.random() < 0.4:
                        schieb.append((h, t, v))
                    else:
                        fehlt_r.append(t)
                else:
                    schieb.append((h, t, v))

    if fehlt_r:
        fehlt_r_min = fehlt_r[0]
    else:
        fehlt_r_min = 0

    liste = list(range(anzahl_breite)) * 2
    for t in range(anzahl_breite):
        random.shuffle(liste)  
        positionen = set(liste[:anzahl_breite - 1])
        for h in positionen:
            if t < anzahl_tiefe - 1 or (h >= 0 and h not in fehlt_v):
                if h < anzahl_breite - 1 or (t < fehlt_r_min):
                    schieb.append((h, t, anzahl_hoehe))

    hoehe = 200
    breite = 200
    start_x = int(breite/2) - anzahl_breite * 10 + anzahl_tiefe * 3 + 7
    start_y = int(hoehe/2) + anzahl_hoehe * 10 - anzahl_tiefe * 3 - 7
    schieb_positionen = [
        (h * 20 + start_x - int(t * 20 * 0.3), start_y + t * 6 - v * 20)
        for h, t, v in schieb
    ]
    soll = anzahl_breite * anzahl_tiefe * anzahl_hoehe
    ergebnis = soll - len(schieb)
An manchen Stellen scheinst Du Breite und Tiefe verwechselt zu haben. Und im letzten Teil scheint die Höhe eins zu hoch zu sein.
Was hast Du Dir beim mittleren Teil mit der Liste `liste` gedacht? Irgendwie habe ich das Gefühl da steckt wieder eine einfache Wahrscheinlichkeit dahinter. Ohne Erklärung versteht man das nicht.

Code: Alles auswählen

    for t in range(anzahl_tiefe):
        for h in range(anzahl_breite):
            if ((t == anzahl_tiefe - 1 and h in fehlt_v)
                or (h == anzahl_breite - 1 and t >= fehlt_r_min)):
                pass
            elif random.random() < 0.666667:
                schieb.append((h, t, anzahl_hoehe - 1))

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Mittwoch 17. August 2022, 17:09
von Pitwheazle
Gute Güte - hast du dich da wirklich reingeschafft? Dann sollte ich mir wirklich beim Benennen von Variablen und beim Kommentieren mehr Mühe geben.
Ich stelle immer wieder fest, dass es mir schwer fällt, komplexere Codes zu entwickeln und schreibe oft halt noch, wie ich das von Basic kenne, Zeile für Zeile. Das mit dem

Code: Alles auswählen

        (h * 20 + start_x - int(t * 20 * 0.3), start_y + t * 6 - v * 20)
        for h, t, v in schieb
    ]
ist ja wirklich viel einfacher - so Sachen muss ich unbedingt lernen. Das mit der Anzahl der Würfelchen war mir nicht so wichtig, ändere ich aber und das mit den Zufallszahlen habe ich einfach ausprobiert, bis es mir gefallen hat, da war mir der tatsächliche Wert nicht so wichtig.

Das mit der Liste in der Mitte ist mir nicht besser eingefallen (ich war aber ganz stolz, dass ich das irgendwie hinbekommen habe.
Diese Routine berechnet die Würfelchen im obersten Stockwerk:
Zuerst eine Liste mit den doppelten Zahlen bis zur maximalen Breite:
[1, 1, 2, 2, 3, 3, 4, 4, 5, 5]
... dann sortiere ich diese Liste in jeder Reihe zufällig neu:
[3, 5, 1, 2, 4, 2, 3, 4, 5, 1]
...und wähle dann die ersten (hier) vier aus und sorge mit "set" dafür, dass keine Zahl doppelt ist:
{1, 2, 3, 5}
... in dieser Zeile werden dann die Würfelchen 1, 2, 3 und 5 gezeichent und
dann kommt die nächste Reihe:
[5, 3, 2, 1, 4, 1, 4, 5, 2, 3]
{1, 2, 3, 5}
[1, 4, 3, 3, 2, 1, 5, 2, 4, 5]
{1, 3, 4}
[1, 3, 3, 5, 5, 2, 4, 1, 2, 4]
{1, 3, 5}
[4, 5, 3, 4, 1, 2, 1, 3, 2, 5]
{3, 4, 5}
Und später muss vorm Zeichnen noch überprüfen, ob ein Klötzchen drunter da ist. Bei der rechten Seite wollte ich, dass auch kein Klötzchen vor einer Lücke steht.
Besser kann ich das nicht :( .

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Mittwoch 17. August 2022, 17:42
von Pitwheazle
Nochmals Danke! Ich habe alles eingebaut, geht prima!
(ich saß mehrere Tage an dem Code - wie lange hast du denn für die Verbesserungen gebraucht?)

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Mittwoch 17. August 2022, 19:19
von Sirius3
Code verändern ist ja deutlich einfacher, als Code von Grund auf zu entwickeln.

Für guten Code braucht es aber gute Vorbereitung. Bei Dir ist es einmal das Problem genau zu beschreiben. Du hast zwei Ebenen, die vorletzte Ebene soll an den Rändern fehlende Würfel haben, und eine letzte Ebene mit zusätzlich an zufälligen Stellen fehlenden Würfeln:

Code: Alles auswählen

    second_last_plane = [
        [
            (t == anzahl_tiefe - 1 and random.random() >= 0.7)
            or (v == anzahl_breite - 1 and random.random() >= 0.4)
            for h in range(anzahl_breite)
        ] for t in range(anzahl_tiefe)
    ]
    last_plane = [
        [
            missing or random.random() >= 2/3
            for missing in row
        ] for row in second_last_plane
    ]
Und noch der Code zum Umwandeln dieser Listen in die eigentlichen Würfelpositionen:

Code: Alles auswählen

    hoehe = 200
    breite = 200
    start_x = breite // 2 - anzahl_breite * 10 + anzahl_tiefe * 3 + 7
    start_y = hoehe // 2 + anzahl_hoehe * 10 - anzahl_tiefe * 3 - 7
    full_plane = [[False] * anzahl_breite] * anzahl_tiefe
    schieb_positionen = [
        (start_x + h * 20 - t * 6, start_y + t * 6 - v * 20)
        for v, plane in enumerate([full_plane] * (anzahl_hoehe - 2) + [second_last_plane, last_plane])
        for t, row in enumerate(plane)
        for h, missing in enumerate(row)
        if not missing
    ]
    soll = anzahl_breite * anzahl_tiefe * anzahl_hoehe
    ergebnis = soll - len(schieb_positionen)

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Donnerstag 18. August 2022, 16:26
von Pitwheazle
Ich bin schwer beeindruckt. Konntest du sowas von Anfang an oder anders gefragt: Kann man das lernen? Sieht toll aus und ich vermute, du hast das einfach so geschrieben, ohne es ausprobiert zu haben. ... Es funktioniert auf Anhieb!
Leider verstehe ich höchstens Ansätze von deinem Code. Wahrscheinlich ist das auch der Grund warum ich in Schach verliere und auch in meinem Mathestudium nicht so erfogreich war. Ich fürchte, ich muss weiter kleine Brötchen backen und meine Programme "linear" schreiben. Siehst du eine Möglichkeit mir auf die Sprünge zu helfen wie das funktioniert?

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Donnerstag 18. August 2022, 21:25
von Sirius3
Der Trick ist, viel zu üben. Nach dreißig Jahren fällt einem das dann einfacher.
Was konkret verstehst Du daran nicht?

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Donnerstag 18. August 2022, 22:12
von Pitwheazle
Machst du das auch beruflich?

Also ich habe mir mal die Listen anzeigen lassen. Die erste (second-last_plane) verstehe ich (einigermaßen) die erste Liste besteht aus False/True für die Reihen in der vorletzten Schicht.
Bei der zweite Schleife (last_plane), steht "missing" für "false" in der ersten Liste?
Wofür steht "False" in "full_plane = [[False] * anzahl_breite] * anzahl_tiefe"?
Und wie funktioniert "for v, plane in enumerate([full_plane] * (anzahl_hoehe - 2) + [second_last_plane, last_plane])"?

Und dann noch die Variable: "v" ist nicht definiert und erzeugt eine Fehlermeldung und "h" scheint nicht genutzt zu werden. (Ich hatte h als horizontal (Breite) und v als vertikal (Höhe) gedacht - und t als Tiefe).

Ach, wenn ich schon am Frage stellen bin: Du kennst ja mein Projekt. In meinem OpenOffice Programm, sieht man, wie die Klötzchen nacheinander "aufgebaut" werden - das gefällt mir und macht die Aufgabe nachvollziehbar. Das könnte man ja sicher auch als Animation in svg nachstellen. Aber was ich noch nicht verstanden habe: Mal angenommen, mir gelingt es, irgendwann meinen Rechentrainer zu veröffentlichen, und mehrere Schülerinnen und Schüler greifen gleichzeitig auf diese Aufgabe zu, macht das Performanceprobleme?

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Freitag 19. August 2022, 07:58
von Sirius3
Wenn `v` nicht definiert ist, `h` aber nicht benutzt wird, dann wird das ein trivialer Tippfehler sein, der bei einbuchstabigen Variablennamen vorkommen kann und mir eingerutscht ist, weil ich zum Schluß noch versucht habe, da irgendeine Konsistenz reinzubringen.

Bei komplizierten Ausdrücken hilft es, die auseinander zu nehmen, hier also:

Code: Alles auswählen

    full_cube = [full_plane] * (anzahl_hoehe - 2) + [second_last_plane, last_plane]
    schieb_positionen = [
        (start_x + h * 20 - t * 6, start_y + t * 6 - v * 20)
        for v, plane in enumerate(full_cube)
        for t, row in enumerate(plane)
        for h, missing in enumerate(row)
        if not missing
    ]
und der Variablenname dient auch gleichzeitig der Dokumentation, was denn der Sinn des Konstrukts ist.

Jetzt willst Du also auch noch animierte svg-Dateien schreiben. Ja, das geht auch, weil css Animationen unterstützt. Und diese Animation läuft ja auf dem Rechner der Schüler, die einzigen mit Performance-Problemen macht also der Browser Deiner Schüler.

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Samstag 20. August 2022, 15:21
von Pitwheazle
Sirius3 hat geschrieben: Donnerstag 18. August 2022, 21:25 Der Trick ist, viel zu üben. Nach dreißig Jahren fällt einem das dann einfacher.
Ich beschäftige mich ja erst seit Januar diesen Jahres mit dem Thema - vielleicht ist da ja noch Hoffnung. Aber in 30 Jahren werde ich 98!
(Vielleicht sagt jetzt ja mal jemand zur Aufmunterung, dass das für 8 Moante ja schon ganz gut geht und dass ich die Hoffnung nicht aufgeben soll :) .)
Sirius3 hat geschrieben: Freitag 19. August 2022, 07:58 Wenn `v` nicht definiert ist, `h` aber nicht benutzt wird, dann wird das ein trivialer Tippfehler sein
... erstaunlicherweise funktioniert es aber auch so.
Sirius3 hat geschrieben: Freitag 19. August 2022, 07:58 Und diese Animation läuft ja auf dem Rechner der Schüler, die einzigen mit Performance-Problemen macht also der Browser Deiner Schüler.
... hätte ich (ausnahmsweise) vor dem Posten nachgedacht, hätte ich eigentlich auch selbst drauf kommen können!

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Samstag 20. August 2022, 18:59
von Dennis89
Pitwheazle hat geschrieben: Samstag 20. August 2022, 15:21 (Vielleicht sagt jetzt ja mal jemand zur Aufmunterung, dass das für 8 Moante ja schon ganz gut geht und dass ich die Hoffnung nicht aufgeben soll :) .)
Für 8 Monate geht das ja schon ganz gut, geb die Hoffnung nicht auf 🧐


SCNR

Re: Fehler bei leerer Liste bei min(liste)

Verfasst: Sonntag 21. August 2022, 12:18
von Pitwheazle
Dennis89 hat geschrieben: Samstag 20. August 2022, 18:59 Für 8 Monate geht das ja schon ganz gut, geb die Hoffnung nicht auf 🧐
Das ist sehr lieb von dir, danke schön.
SCNR