Advent of Code

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Hm, Teil 1 in Bash hatten wir im Python-Forum auch gerade. Da war mein vorläufiger Endstand das hier:

    Spoiler anzeigen
    Bash
    #!/usr/bin/env bash
    
    readarray MEASUREMENTS < input.txt
    
    INCREASED=0
    for (( i = 1; i < ${#MEASUREMENTS[@]}; i++ )); do
        [[ ${MEASUREMENTS[i]} -gt ${MEASUREMENTS[i-1]} ]] && (( INCREASED++ ))
    done
    
    echo $INCREASED

    Hier ist meine BASIC-Lösung für den C64:

    BASIC
    10 TI$="000000":PRINT"READING INPUT...":DIM A(2000):OPEN 1,8,0,"INPUT01,S":N=0
    20 INPUT#1,A(N):N=N+1:IF ST=0 THEN 20
    30 CLOSE 1:PRINT N;"VALUES IN ";TI$:PRINT"PART 1..."
    40 C=0:FOR I=0 TO N-2:IF A(I)<A(I+1) THEN C=C+1
    50 NEXT:PRINT C;TI$
    60 PRINT"PART 2...":C=0:FOR I=0 TO N-4
    70 X=0:Y=0:FOR J=0 TO 2:K=I+J:X=X+A(K):Y=Y+A(K+1):NEXT:IF X<Y THEN C=C+1
    80 NEXT:PRINT C;TI$

    Ich weiss nicht, ist das auch ohne Spoiler-Tag schon kryptisch genug, oder soll ich so etwas besser verstecken?

    Teil 2 ist ”naiv” gelöst, also einfach das was einem so offensichtlich dazu einfallen sollte. Das berechnet natürlich eine Menge unnötig mehrfach, das wäre also ein Ansatzpunkt um das zu optimieren. Die Laufzeit ist 3m25s wovon die ersten 51s für das laden der Daten drauf geht und Teil 1 ist in ca. 25 Sekunden durch.

    Von der Python-Lösung zeige ich mal ungespoilert das Grundgerüst für den ersten Tag mit Unit-Test(s) aber ohne die konkrete Lösung, falls sich da jemand allgemeine Inspiration holen möchte:

    Ich lese Eingaben bei Advent of Code in der Regel einfach von der Standardeingabe, dann kann ich da mehrere ausprobieren und muss keine Dateinamen fest im Quelltext kodieren. Und aus den Beispielen in den Aufgabenbeschreibungen mache ich Unittests. Meiner Erfahrung nach decken die Beispiele in den Aufgaben fast immer auch die wichtigen Sonderfälle ab, bei denen man am ehesten Fehler machen kann, oder wo in der textuellen Beschreibung Mehrdeutigkeiten sind. Die Beispiele klären so etwas normalerweise.

    Und hier das was in dem Listing oben fehlt — eine Import-Zeile und der Inhalt der `count_increases()` ist ein simpler Ausdruck:

    Spoiler anzeigen
    Python
    from more_itertools import pairwise, windowed
    
    ...
    
    def count_increases(values, window_size):
        return sum(
            a < b for a, b in pairwise(map(sum, windowed(values, window_size)))
        )

    Das was da aus einem externen Package importiert wird, kann man sich auch selber schreiben, beziehungsweise einfach aus der Python-Dokumentation kopieren. Da gibt es ja ein verwandtes Modul und in dessen Dokumentation gibt es ”Rezepte”.

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • Hallo,

    ich freu mich, das ich Ähnlichkeiten mit __blackjack__ 's Code habe.

    VORSICHT, es folgen meine vollständigen Lösungen:

    Spoiler anzeigen

    Mit der zweiten Lösung bin ich noch nicht zufrieden.

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • Da sind sie wieder, die mystischen und viel zu wenig von mir verwendeten Pakete (more)itertools und map. :lol: (siehe anderer Thread)

    Das mit dem Pytest glaube ich habe ich in dem Thread schon letztes Jahr gefragt was es macht und dachte mir das will ich übernehmen. Denkste.

    Und ich dachte es wäre die Stunde vom Slicing der Listen am Tag 1 ;)

    Bin gespannt welche verschiedenen Lösungsansätze man noch im Dezember sehen wird.

  • Danke in die Runde für den Tipp zum Advent of Code. Das kannte ich noch nicht!

    Na, dann probier ich es auch mal.

    Hier mein Lösungsweg für Teil 2 von heute:

    Spoiler anzeigen

    Einmal editiert, zuletzt von simonz (2. Dezember 2021 um 16:53) aus folgendem Grund: __blackjack__'s Tipp zu den Beispieldaten eingearbeitet

  • simonz ``split("\n")`` zum Aufteilen in Zeilen ist nicht so praktisch denn dabei entsteht in der Regel am Ende eine leere Zeichenkette in der Liste, die man nicht haben will. Steht ja auch in Deinem Kommentar. Die `splitlines()`-Methode hat das Problem nicht. Und die erste Leerzeile kann man durch einen \ nach den """ unterdrücken.

    Die Beispieleingaben binde ich in der Regel als Konstante so ein:

    Python
    EXAMPLE_LINES = """\
    forward 5
    down 5
    forward 8
    up 3
    down 8
    forward 2
    """.splitlines()

    Dann gibt es keine extra Leerzeichen an den Zeilenanfängen und keine leeren Zeichenketten am Anfang oder Ende.

    Dennis89 Bei Tag zwei ist in der Auswertungsfunktion die innerste „list comprehension“ (LC) überflüssig. Die macht ja im Grunde gar nichts ausser alles in einer Liste zu sammeln. Das ginge mit `list()` einfacher, aber auch das ist ja unnötig. Der Name `_` ist ja eigentlich für Werte die *nicht* verwendet werden. Und man hätte das mit `map()` kürzer schreiben können. Und auch hier ist die LC nicht nötig, ein Generatorausdruck hätte es auch getan.

    Hofei Deine Navigator-Klassen enthalten redundanten Code. Das wäre eine Gelegenheit mal was mit Vererbung zu machen und eine gemeinsame Basisklasse aus den beiden heraus zu ziehen und nur noch die tatsächlichen Unterschiede in den beiden zu kodieren.

    Die `move()`-Methode liesse sich aufgrund der dynamischen Natur von Python drastisch kürzen.

    Ungetestet:

    Spoiler anzeigen

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • Ich stelle meinen Code jeden Tag immer hier hin. Da gibt es auch ein Script day.sh mit dem man schnell und einfach einen existierenden Code eines Tages aufrufen kann.

    Ich wuerde vorschlagen Ihr stellt ihn auch ins github oder sonstwohin. Ansonsten wird dieser Thread doch ziemlich codelastig :lol: . Bei Fragen oder Diskussionen zum Code kann man leicht Links zum Code hier posten wie z.B. diese Zeile wo ich wie __blackjack__ vorschlug - die Scripts so geaendert habe dass sie immer stdin lesen.

  • Hm. Ich mag Git/Github nicht wirklich.

    Meine BASIC-Lösung ist heute schon deutlich länger als die gestern:

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • __blackjack__ Danke für deine Tipps/Verbesserungen. Das ich '_' als Name verwendet habe, lag daran das ich keinen sinnvollen Namen fand und mir die Zeit ausging. (Daran hätte ich eigentlich merken sollen, dass da etwas überflüssiges gemacht wird).

    Auch für heute fehlt mir bis jetzt noch etwas die Zeit. Das geht schon gut los ?

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • Inspiriert von framp 's in #208 erwähntem Script day.sh habe ich mir auch ein Helferlein gebaut.

    Es bietet neben diversen Kommandos eine optionale Mini-"IDE" (per tmux).

    Ist ein nettes Programmierprojekt so nebenbei.

    Bei Interesse:

    Spoiler anzeigen

    Hinweis: Das ist die erste Version (gewesen).

    Korrekturen etc. pflege ich bei Github: https://github.com/gchriz/aoc

    4 Mal editiert, zuletzt von simonz (4. Dezember 2021 um 08:00) aus folgendem Grund: Hinweis auf Version und Github. Textänderungen. Screenshot hinzugefügt.

  • Habe eben Deinen tmux Code downloaded. Da Du Python in Deinen Scripts nutzt und auch sonst noch ein paar Kleinigkeiten unterschiedlich sind zu meinem Environment musste ich noch ein paar Dinge anpassen. Aber jetzt funktioniert es auch mit meinen bash Scripts :bravo2:

    :no_sad: ... Kein Backupkein Mitleid ... :no_sad:
    :) Nutze lieber raspiBackup bevor Du in die Luft 💥 gehst wie ein HB Männchen :)

    Einmal editiert, zuletzt von framp (2. Dezember 2021 um 23:00) aus folgendem Grund: Typos

  • Ich weiss nicht, ist das auch ohne Spoiler-Tag schon kryptisch genug, oder soll ich so etwas besser verstecken?

    Ich kann nur für mich sprechen und bevor ich das entschlüssle versuche ich anders zu bescheissen ?

    Gibts für heute eine Python-Lösung die nicht nur aus 'for'-Schleifen und '+=' besteht, sondern dem Niveau den Lösungen aus #203 entspricht?

    Ich habe zwar für das Iterieren 'pairwise' genutzt aber danach nur aneinander gereite 'if'-Abfragen gefolgt von Rechenoperationen.

    Ich habe aber das Gefühl, dass das schöner und eleganter geht?

    Nur für heute habe ich keinen Kopf mehr und morgen gehts ja schon weiter ?

    Grüße

    Dennis

    🎧 With the music execution and the talk of revolution, it bleeds in me and it goes 🎧

  • Ich habe was mit Operatorüberladung und `Enum` und nur ein ``if``/``else`` (also von dem ``if __name__ …`` abgesehen). Aber ansonsten jeweils eine ``for``-Schleife in den beiden Teillösungen über die Steueranweisungen.

    Spoiler anzeigen

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

  • dass das schöner und eleganter geht

    Die Frage ist immer aus akademischer Sicht interessant. Aber ich kann immer nur empfehlen klaren und verstaendlichen Code - auch wenn er nicht elegant ist - zu schreiben. Ein jeder Code will gewartet werden und das ist meist nicht derjenige der den Code geschrieben hat :shy: Auch wenn man ihn selbst geschrieben hat - nach einer gewissen Zeit versteht man nicht mehr was man sich damals "elegant" ueberlegt hatte :shy:

  • dass man die Spracheigenschaften und Bibliotheken ausschöpfen darf.

    man bist Du :) .

    Aber aus Maintenancegesichtspunkten wirst Du das meinst nicht mehr sein - speziell wenn Du gut bist. Du kannst nicht voraussetzen das Dein Nachfolger der Deinen Code maintainen muss denselben Erfahrungshoizont wie Du hast. Du kannst Dich natuerlich darauf setzen - so what - und die fuer Dich - und vielleicht auch objektiv betrachtete - eleganteste Loesung herausknobeln.

    Aber wehe wenn Du mal Code maintainen musst den jemand geschrieben hat der noch besser ist als Du beim Ausschoepfen und Du musst einen Bug in dem ausgeschopften Code innerhalb einer Stunde fixen damit die Produktion wieder laeuft ... Dann bist Du froh wenn der Code nicht ausgeschoepft sondern schnell zu verstehen ist.

    ... ich habe das diverse Male erleben duerfen . Nobody is perfect und es gibt immer welche die mehr aus den moeglichen Sprachmoeglichkeiten ausschoepfen als Du. Und Du bist dann derjenige der wie Ochs vorm Scheunentor steht wenn er geaendert werden muss.

    Nimms bitte nicht persoenlich - das Du steht hier fuer jeden der kodiert :)

  • Das sehe ich nicht so. Du setzt hier IMHO Sprachumfang und Bibliothek ausschöpfen und elegant zu sehr mit unklar und unverständlich gleich. Die Spracheigenschaften und Bibliotheken sind doch gerade dazu da um klareren und leichter verständlicheren Code zu schreiben. Wenn man das nicht macht, dann endet das in Code der den kleinsten gemeinsamen Nenner von einem Querschnitt von prozeduralen Programmiersprachen verwendet, und keine Bibliotheksfunktionen verwendet, die Sachen einfacher machen und gut getestet sind. Die einzelnen Anweisungen mögen auf diese Weise verständlicher sein, aber es sind dann halt deutlich mehr für die gleiche Aufgabe, es muss also auch mehr Code gelesen und verstanden werden, und es werden dann auch gerne mal Fehler gemacht, die man durch Bibliotheksfunktionen hätte vermeiden können.

    Zum Beispiel bei Tag 1 hatte ich in Teil 2 bei meiner BASIC-Lösung einen typischen „off by one“-Fehler und am Ende des Arrays ein Element zu viel addiert. Im Python-Forum hat das auch jemand in Bash gelöst und hatte einen „off by one“-Fehler am Anfang des Arrays gemacht. Das kann einem mit `pairwise()` und/oder `windowed()` in Python nicht passieren. Und wer diese Funktionen nicht kennt, kann in deren Dokumentation nachlesen was die machen, inklusive Beispielen wo man Argumente und Ergebnisse sieht. Das ist ja nicht irgendwie undurchsichtiges Hexenwerk oder Geheimwissen. Es ist eleganter, weil einfacher und weniger fehleranfällig als selbst geschriebenes jonglieren mit verschachtelten Schleifen und Indexzugriffen mit zusätzlichen Offsets.

    Man kann nicht bei jedem den gleichen Erfahrungshorizont voraussetzen, aber doch auch nicht bei jedem Programm vom Programmieranfänger ausgehen, der nur das erste drittel des Anfängertutorials durch hat. Bei Python dürfte ich dann keine Klassen schreiben, keine Ausnahmen behandeln, oder gar auslösen, und müsste in den wenigen Funktionen die neben dem ganzen Code auf Modulebene stehen, auch noch ``global`` verwenden. ?

    “Dawn, n.: The time when men of reason go to bed.” — Ambrose Bierce, “The Devil's Dictionary”

Jetzt mitmachen!

Du hast noch kein Benutzerkonto auf unserer Seite? Registriere dich kostenlos und nimm an unserer Community teil!