Posts by __blackjack__

    rodiboki Ergänzend zu dem was hyle schon geschrieben hat: as beim Import ist zum umbenennen — GPIO wird hier aber gar nicht umbenannt.

    Man nummeriert keine Namen. Dann will man sich entweder bessere Namen überlegen, oder gar keine Einzelnamen und -werte, sondern eine Datenstruktur. Oft eine Liste.

    Man kann einigen GPIO-Funktionen auch Sequenzen von Pin-Nummern übergeben statt da für jede Nummer einen einzelnen Aufruf zu machen. Und wo das nicht geht, kann man selbst eine Schleife oder eine „comprehension“ schreiben um da nicht zig mal die gleiche Abfrage für variierende Pin-Nummern machen zu müssen. Ungetestet:

    Edit: Abfrage so schnell wie möglich, Ausgabe aber nur wenn sich was geändert hat:

    Mit fertigen Algorithmus meine ich den Algorithmus den man üblicherweise verwendet wenn man Dinge, die Abhängigkeiten haben, so sortiert, das die Abhängigkeiten alle vorher vorkommen. Link zu Wikipedia:

    Display Spoiler

    Mir geht's auch um's Lösen und Lernen bzw. Üben. Wenn ich erkenne, dass man da eine Standardlösung anwenden kann, und weiss in welchem Modul es die gibt, dann erfinde ich das Rad nicht noch mal neu. Bei der mul(…,…)-Aufgabe hast Du doch wahrscheinlich auch das re-Modul verwendet und das nicht selbst noch mal neu implementiert‽ Das wäre ja auch so etwas wo man den regulären Ausdruck nehmen könnte, da einen Zustandsautomaten draus aufzeichnen könnte, um den dann selber in Code umzusetzen.

    Den Sortieralgorithmus hatte ich auch im Studium schon mal implementieren müssen. Nach der Beschreibung in „Introduction to Algorithms“ (der „Cormen“). Das sind nur drei relativ simple Schritte, die voraussetzen, dass man eine Tiefensuche über den Graphen schreiben kann. Was ja letztlich auch kein Hexenwerk ist.

    Bei Deinen rules (ich weigere mich ein my davor zu schreiben 😜) wäre collections.defaultdict() sinnvoll. Und statt append() und danach sort() könnte man bisect.insort() verwenden, was ein neues Element in eine sortiere Liste an der passenden Stelle einfügt. Oder man hängt erst einmal alles an und macht dann noch eine Schleife über die ganzen Listen und sortiert die jeweils einmal. Wobei die Listen später mit in-Tests verwendet werden, also eigentlich besser set()s wären.

    mysort() sortiert nichts, das wäre vom Namen her besser compare_pages() oder etwas in der Richtung.

    Das is_test-Flag sieht an vielen Stellen aus, als würde da logging mit einem Loglevel nachgebaut.

    Mir gefällt die Strukturierung der Regeln nicht so ganz. Fester Satz an Schlüsseln die Zeichenketten sind, deutet in der Regel auf eine Klasse hin. Und ich hätte da auch eher Regeln = Seitennummer → (before=Seitennummern, after=Seitennummern) statt Regeln = (before=Seitennumer → Seitennummern, after=Seitennummer → Seitennummern) gemacht. Denn die beiden Wörterbücher haben ja die selben Schlüssel, sind also ”parallele” Datenstrukturen.

    hanshesse1951 Wer hat denn bestätigt, dass das Programm okay ist?

    Das Programm selber kann auch nicht unbedingt etwas dafür, das eventuell ein anderes Programm den Pin bereits zur Verwendung konfiguriert hat.

    Das mit dem setwarnings() ist allerdings kein guter Rat. Statt Warnungen zu ignorieren, sollte man die Ursache heraus finden und beseitigen. Meistens reicht es einfach in den eigenen Programmen konsequent am Programmende hinter sich aufzuräumen, also GPIO.cleanup() in einem finally-Block auszuführen.

    Oder man steigt von GPIO auf gpiozero um. Das kümmert sich selbst ums aufräumen am Programmende. Und blinken geht damit auch einfacher.

    simonz Für Teil 2 von heute (Tag 5) selbst was geschrieben, oder ein Modul mit dem fertigen Algorithmus verwendet?

    Der letzte Fehler den ich beseitigen musste, war dass der Hinweis ernst gemeint war, die Regeln die nicht vorhandene Seiten in der Aktualisierung betreffen zu ignorieren. In meinen Eingabedaten sind nämlich Regeln die sich widersprechen. Die Regeln 21|77, 22|21, und 77|22 sind nicht gleichzeitig erfüllbar. Die kommen aber zusammen auch in keiner meiner Aktualisierung vor. 🙂

    choose_music_randomly() ist ja ein bisschen wortreich umgesetzt:

    Python
    def choose_music_randomly(sound_files):
        random_sound_file = random.choice(sound_files)
        return random_sound_file
    
    # Ist eigentlich nur das hier:
    
    choose_music_randomly = random.choice

    Und da kann man die Funktion auch einfach weglassen, wenn man bloss ein Alias für random.choice() definiert.

    Die Aufräumarbeiten bei den beiden Ausnahmebehandlungen sollten da nicht zweimal stehen, sondern einmal in einem finally-Block. Dann braucht man auch nicht allgemein jede Ausnahme behandeln und da einfach den Traceback unterdrücken. Ein mixer.quit() könnte man da noch hinzufügen.

    Das Gegenstück zum mixer.quit() mixer.init() — ist zwar idempotent, aber ich würde das trotzdem nur einmal aufrufen.

    Im fadeout() ist das stop() schon enthalten. Dafür sollte man mit dem unload() warten bis der Ton tatsächlich ausgeblendet ist. Diese API ist asynchron, die ist ja für Hintergrundmusik gedacht. Oder man spart sich das unload() einfach.

    Zwischenstand (ungetestet):

    VFR750 Was heisst denn „funktioniert nicht“ konkret? Bei der Konfiguration die Du gezeigt hast, sind einigen Tasten die gleichen Codes zugeordnet. Konkret sind das

    • 0x033C000001000398 → KEY_MENU, KEY_VOLUMEDOWN, KEY_RECORD
    • 0x033E000001000705 → KEY_VOLUMEUP, KEY_INFO, KEY_CHANNELUP
    • 0x033E000001000397 → KEY_3, KEY_CHANNELDOWN, KEY_MUTE
    • 0x033F000001000397 → KEY_5, KEY_CONTEXT_MENU

    Das sollte wohl eher nicht so sein‽

    devil P Anmerkungen zum Hauptprogramm: time wird importiert, aber nirgends verwendet. Das auf Modulebene definierte n wird ($GOTT sei Dank) auch nirgends verwendet.

    Bei den drei Pfadkonstanten sollte das im Namen stehen, dass es sich um Dateipfade handelt und beispielsweise CAR_IMAGE nicht für ein Autobild steht, sondern für den Pfad zu einer Datei. Es würden sich auch pathlib.Path-Objekte anbieten, statt Zeichenketten, dann könnte man auch den Pfad zu den drei Dateien als Konstante definieren und muss den nur einmal im Programm stehen haben.

    Es macht überhaupt keinen Sinn etwas in der Form name: list = [] zu schreiben. Na klar ist das vom Typ list wenn man da eine leere Liste zuweist. Das sieht man auch ohne die Typannotation. Sowohl als menschlicher Leser, aber auch eine statische Typprüfung kann das ohne die Annotation problemlos erkennen. Also weg mit der Annotation. Als nächstes ist es aber auch in allen Fällen wo das steht unsinnig dem jeweiligen Namen eine leere Liste zuzuweisen, die nämlich in keinem der Fälle irgendwo verwendet wird.

    Die Ausnahme”behandlung” beim laden von gepickelten Daten ist falsch. Da wird alles mit der Ausgabe " no file" und einem Programmende behandelt, so dass man da gar keine Chance hat herauszufinden was los ist wenn es die Datei gibt aber aus einem anderen Grund eine Ausnahme ausgelöst wird. Am besten lässt man die Behandlung hier einfach weg: Das Programm wird dann auch abgebrochen und man bekommt den tatsächlichen Grund. Und man hätte beim Aufrufer auch noch die Chance den Programmabbruch zu verhindern und die Ausnahme anders, sinnvoll zu behandeln. Ansonsten gehört ein Programmabbruch nicht in irgendwelche Hilfsfunktionen.

    Öffnen von Dateien am besten immer mit der with-Anweisung zusammen. Dann wird der Code sicherer, einfacher, und man kann auch nicht die Klammern beim close()-Aufruf vergessen wie in save_image(). Wobei diese Funktion nirgends verwendet wird.

    bewegung im Hauptprogramm macht als Variable keinen Sinn. Das wird an zwei stellen sinnlos auf False gesetzt, und nur an einer Stelle an einen sinnvollen Wert gebunden, der nur ein einziges mal gleich in der nächsten Zeile für eine if-Bedingung verwendet wird. Dafür braucht man das nicht an einen Namen binden. mov_roi ist ebenfalls überflüssig. Das wird eine Zeile weiter an buffer1 gebunden und sonst nicht verwendet, also kann man das gleich an buffer1 binden. buffer1 an eine Kopie von einem leeren buffer2 zu binden ist auch überflüssig, weil das nie verwendet wird. Beim nächsten Schleifendurchlauf wird buffer1 an das nächste Videobild gebunden.

    Es sieht so ein bisschen so aus als wenn buffer1 und buffer2 immer zwei aufeinanderfolgende Videobilder sein sollten, beziehungsweise Ausschnitte daraus. Das liesse sich deutlich einfacher und eben auch deutlicher ausdrücken mit einem Iterator über die Bilder/Ausschnitte und itertools.pairwise(). Auch das erste Testbild würde dann verschwinden, weil man keine leeren Bilder mehr erzeugen muss und damit auch die Grösse dafür nicht kennen muss.

    Bei crop_image() könnte man statt der magischen Indexzugriffe, den Inhalt des zweiten Arguments an sinnvolle Namen binden.

    check_movement() würde ich als falsch beschreiben. Ja das macht was es soll, aber wenn man Numpy-Arrays hat, schreibt man keine verschachtelten Schleifen darüber um mit jedem einzelnen Wert das gleiche zu machen, sondern nutzt die Arrays so wie sie gedacht sind. x für die Zeilen und y für die Spalten ist auch ungewöhnlich bis verwirrend. Wenn man Numpy tatsächlich verwendet ist die Funktion ein Zweizeiler.

    determine_car() macht zu viel. Das ermittelt nicht nur das Auto sondern ruft selbst dann auch noch eine weitere Funktion auf die ein Fenster öffnet und etwas anzeigt. Statt ein Ergebnis zu ermitteln und an den Aufrufer zurück zu geben.

    Das erste Argument heisst colors es wird aber mit etwas aufgerufen was car_color (Einzahl) heisst. Das ist verwirrend. count ist auf deutsch Anzahl, das ist wohl auch falsch. Man kann enumerate() auch einen Startwert migeben, dann braucht man selbst keine 1 addieren. Das result-Flag macht keinen Sinn.

    show_result() macht überhaupt nichts mit dem ersten Argument.

    Ein Array mit mit einer RGB-Farbe kann man mit numpy.full() in einem Schritt erstellen, statt erst ein Array mit lauter 1en zu erstellen, und die dann mit den RGB-Werten zu überschreiben.

    Zwischenstand (ungetestet):

    Ja, ich bin dabei. Der Altair Emulator ist immer noch am Bubblesort der zweiten Liste für den ersten Aufgabenteil. Mal sehen ob das heute noch fertig wird.

    Dass das Ergebnis richtig sein wird, weiss ich weil der DOS-PC mit QBasic das selbe Programm in ca. 2 Minuten abgearbeitet hatte. 8080 mit 2 Mhz vs. 486 mit 33 Mhz. 🤣