Advent of Code

Heute ist Stammtischzeit:
Jeden Donnerstag 20:30 Uhr hier im Chat.
Wer Lust hat, kann sich gerne beteiligen. ;)
  • Vielen Dank für die Mühe meinen Tag 4 Code durchzusehen, ich knapper auch immer noch an Tag 4. Habe beschlossen ich möchte eure Lösungen (in Python) nachvollziehen können bevor ich mich zum nächsten Tag auf mache. Qualität vor Quantität.

    Der Code wurde von mir sehr oft angepasst, wodurch auch das break in der for-Schleife verschwand, aber nicht das else.

    Auch die von dir genannte gewinner Variable in check_bingo_felder() ist ein Überbleibsel, anfangs verstand ich die Aufgabe falsch und summierte erst die Gewinnerzahlen der Bingokarten und multiplizierte diese mit der Summe der unmarkierten Zahlen. So entstand diese Variable.

    Der Aufrufer hat diese Liste ja bereits, sonst hätte er sie nicht übergeben können. So sieht die API so aus, als würde eine neue Liste zurückgegeben und die übergebene Liste unverändert gelassen.

    Da sind wir wieder mit Mutable vs Immutable. Darauf hattest du mich in einem anderem Thread schonmal wegen einem Dictionary darauf hingewiesen. :thumbup:


    Während du meinen Code dir angeschaut hast, schaute ich mir heute Nachmittag deine PDF zu Tag 4 an. Vielen Dank auch dafür! Klasse gemacht und verständlich geschrieben. Gabs die PDF nur aufgrund meiner Rückfrage in #247 oder hattest du die PDF sowieso schon gemacht aber nur nicht veröffentlicht? Gibts denn solche PDFs auch zu anderen Tagen? :S

    Eine kleine Rückfrage zur PDF habe ich aber dennoch, more_itertools.one() das prüft im Grunde nur, dass nur ein Element übergeben wird?

    Also im Grunde so, nur in kurz:

    Python
    if len(liste_) > 1:
        raise ValueError
    else:
        mach_was()

    Ansonsten denke ich (sogar Seite 6 : yield board, number) habe ich alles in der PDF nachvollziehen können. :danke_ATDE:

  • Hallo,

    more_itertools.one() das prüft im Grunde nur, dass nur ein Element übergeben wird?

    'one' prüft nicht nur ob das übergebene Argument nur ein Element enthält sondern gibt dass dann auch zurück. Sonst würde 'random_numbers' aus Wahrheitswerten bestehen, wenn das 'one' nur prüfen würde und 'True' oder 'False' ausgeben würde.

    Also 'one' in ausgeschrieben wäre folgendes:

    Quelle

    So habe ich das zumindest verstanden.

    Grüße

    Dennis

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

  • Naja Du musst halt herausfinden wie man herausfindet wie die Zuordnung von den 10 beobachteten Signalmustern zu den Ziffernwerten ist. Im ersten Teil hatten wir die einfachen Werte und nun eben die ”schweren”. Bei dem Beispiel in der Aufgabe ist ja beispielsweise klar das a→c und b→f gilt, weil wir wissen das "ab" wegen der Länge 2 die Ziffer 1 sein muss, und wir wissen das die Ziffer 1 im Original durch "cf" kodiert wird. Reicht das als Hinweis?

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

  • Ja, in jeder Zeile ist die Zuordnung anders: „Worse, the wire/segment connections are mixed up separately for each four-digit display! (All of the digits within a display use the same connections, though.)“

    Wobei die Info in meinem Hinweis noch nicht ganz reicht. Wir wissen dadurch das zwei Signale die Ziffer 1 kodieren erst einmal nur a→c/f und b→c/f mit / als ”oder” gelesen. Festnageln kann man das aber wenn man sich die anderen Kodierungen für die Ziffern anschaut wo dort welches Segment vorkommt und wo nicht. Da kann es hilfreich sein sich das mal als Tabelle aufzuschreiben. Also beispielsweise Segmente a-f als Spalten und die Ziffern 0 bis 9 als Zeilen und eine Markierung in den Zellen ob das Segment bei der Ziffer an sein muss oder nicht.

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

  • Hallo,

    Tag 10 war ja wieder zügig lösbar.

    Frage in die Runde: wie habt ihr das mit den öffnenden / schließenden Klammern gemacht? Ich habe mit Python folgenden Weg genommen: die Eingabezeilen zeichenweise durchiteriert und jede öffnende Klammer in eine Liste geschrieben. Kommt eine schließende Klammer, wird diese mit der letzten öffnenden Klammer verglichen. Wenn's passt -> öffnende Klammer aus der Liste entfernen. Wenn 's nicht passt -> Fehler.

    Der Ansatz sollte IMHO auch mit jeder anderen Sprache funktionieren, die eine Datenstruktur ähnlich einer Python Liste kennt.

    Hat jemand von euch das anders / besser / schöner / eleganter / umständlicher gemacht?

    Gruß, noisefloor

  • Hallo,

    ich bin gerade auch mal wieder dabei, allerdings bin ich erst bei Tag 5.

    __blackjack__ in welche Form hast du denn die Puzzel-Input-Daten gebacht und wie hast du das Diagramm gezeichnet? Gibts dazu irgendwelche hilfreichen Bibliotheken, mit Ausnahme von NumPy?

    Irgendwie wird das bei mir gerade so zusammengebastelt ?

    Wenn ich mir hier weiter die Zeit nehme, dann muss der Code schon auch etwas her machen und ich will neues/besseres lernen.

    Grüße

    Dennis

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

  • Dennis89 Das Pascal-Programm ist im Beitrag vor dem mit den Bildern. Die Eingabe ist ein Array von `TLine`-Records die aus jeweils zwei `TPoint`-Records zusammengesetzt sind, welche die Endpunkte beschreiben:

    Und die Bilder werden von dem Programm als PGM-Dateien geschrieben. Der Karte ist einfach ein grosses, 2D-Array wo für jeden Punkt gezählt wird, wie oft der von einer Linie getroffen wird. Da es mehr als 255 Linien in der Eingabe gibt, habe ich da einen 16-Bit-Zähler pro Punkt auf der Karte. Der Code zu Speichern der Karte als Bild ist später dazu gekommen und besteht aus einer Funktion zum ermitteln des maximalen Pixelwerts und einer Prozedur, die ein eine PGM-Datei erstellt:

    Die Netpbm-Dateiformate eignen sich super um Bilddateien in den simpelsten Programmiersprachen zu erstellen. Das Dateiformat ist ein kleiner Header aus Textzeilen gefolgt von den Pixeldaten. Entweder als Text oder Binär, je nach Unterformat. Es gibt Bitmaps („portable bitmap“, PBM) also wirklich nur Pixel ”an” oder ”aus”, Graustufenbilder („portable gray map“, PGM) mit bis zu 65536 Graustufen, und Farbbilder („portable pixel map“, PPM) mit bis zu 65536 verschiedenen Werten pro RGB-Komponente. Alle jeweils in Binär oder ”plain”, also komplett alles als Text, auch die Pixeldaten. Als erstes steht in der Datei das Unterformat P1 bis P6 das angibt ob es PBM, PGM, oder PPM in Binär oder Text ist. Dann folgt ein optionaler Kommentar der mit "#" beginnt, gefolgt von der Breite und Höhe in Pixeln. Bei PGM und PPM kommt dann noch der grösste Wert der in den Pixeldaten vorkommt. Das zweite Bild, welches das Programm speichert fängt beispielsweise so an:

    Code
    $ head DAY_05_2.PGM 
    P5
    1000 1000
    6

    Danach folgen dann die 1000×1000 Bytes mit Werten zwischen 0 und 6. Also aus Sicht des Programms für Tag 5 einfach die niederwertigen Bytes des 1000×1000 Integer-Array:

    Am Anfang sind nur Punkte die gar nicht oder nur 1 mal getroffen wurden. Sieht man an den Bildern ja ganz gut, das die Ränder eher langweilig sind und sich mehr in der Mitte abspielt. Also suchen wir mal den Maximalwert 6:

    Code
    $ hd DAY_05_2.PGM | grep -C 3 ' 06 '
    000729f0  01 00 02 00 00 00 00 00  00 01 02 00 00 02 00 00  |................|
    00072a00  00 02 00 00 00 00 00 00  00 00 01 00 01 00 00 00  |................|
    00072a10  00 01 00 01 00 00 00 01  00 01 00 01 00 00 01 01  |................|
    00072a20  00 00 01 00 00 00 00 00  01 00 00 06 01 00 00 02  |................|
    00072a30  00 00 01 01 01 00 00 01  00 01 01 01 01 00 02 00  |................|
    00072a40  02 00 01 00 01 00 00 00  00 00 00 00 00 00 00 00  |................|
    00072a50  00 00 00 01 01 01 02 00  00 00 00 00 00 01 00 00  |................|

    Da sind im Umfeld dann auch ein paar Punkte zu sehen, die 2 mal getroffen wurden. Und der Maximalwert kommt in der ganzen Datei nur ein mal vor.

    Falls man so etwas in einer Programmiersprache machen will, die mit Binärdaten nicht wirklich gut oder nur komplizierter umgehen kann, kann man statt P5 am Anfang P2 ausgeben und die Pixelwerte 1 bis 6 dann einfach als Text in die Datei schreiben, durch beliebige „whitespace“-Zeichen getrennt. Also Leerzeichen und/oder Zeilenenden.

    Wenn man Bilddateien ohne zusätzliche Bibliotheken erzeugen will/muss, sind die Netpbm-Formate so ziemlich das einfachste was man machen kann das standardisiert ist und von den meisten Bildverarbeitungen und Konvertierungsprogrammen direkt gelesen werden kann. Und für Messdaten & Co ist es ganz nett, dass man da auch 16-Bit-Werte als Pixel speichern kann, also deutlich mehr als 256 Stufen/Werte abbilden kann. Reduzieren auf 256 Stufen, abbilden von Graustufen auf Falschfarben usw. kann man dann hinterher mit entsprechenden Werkzeugen machen.

    Beim heutigen Puzzle bietet es sich auch an Bilder zu speichern. Sogar eine Folge von Bildern, die man hinterher in eine GIF-Animation umwandeln könnte.

    Wenn ich das Programm noch einmal überarbeiten/verbessern würde, dann würde ich bei den Liniendaten speichern ob das eine horizontale, vertikale, oder diagonale Linie ist, denn dann kann man schon beim einlesen abbrechen wenn man eine findet die keines davon ist und muss die ganzen Tests nicht beim zeichnen der Linien in den beiden Aufgabenteilen wiederholt machen. Und ich würde bei Teil zwei die Linien von Teil 1 nicht löschen und alles neu zeichnen, sondern für Teil 2 nur die diagonalen Linien über die Linien aus Teil 1 zeichnen um Zeit zu sparen. Und eventuell würde es mich reizen das nicht mit dem 16-Bit protected mode Compiler zu machen, sondern beim real mode zu bleiben und den Speicher für die 1000×1000 Zähler über die EMS- oder XMS-Schnittstelle anzusprechen. Oder das ganze gar in einer Datei auf Platte zu lösen. Deutlich langsamer, würde dafür aber auch in einem PC ohne zusätzlichen Speicher funktionieren. 640 KiB RAM reichen für alles! In einem 16-Bit-DOS-Programm einfach so 2 Megabyte Speicher anzufordern fühlt sich jedenfalls leicht geschummelt an. ?

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

  • Vielen Dank für die sehr ausführliche Antwort.

    Ich glaube nur, das ich mich etwas falsch ausgedrückt habe. Ich bin/war eigentlich auf der Suche nach einem effektiven Ansatz um das Rätsel mit Python zu lösen. Also mich würde interessieren, wie du vorgehen würdest, wenn du Python verwenden "müsstest". Hast du da irgendwelche nützlichen Bibliotheken im Kopf? Würdest du wieder eine Klasse machen, ähnlich wie mit den Vektoren oder was hättest du sonst für Ideen?

    Du musst dir aber nicht die Mühe machen, dass Ganze jetzt zu programmieren. Vielleicht kannst du nur ein "paar" Sätzchen zu deinem Vorgehen schreiben? ☺

    Grüße

    Dennis

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

  • Hallo,

    Dennis89 : die Bibliothek shapely wäre ein Ansatz, die hat Objekte für Punkt, Linien usw und auch Methoden für Schnittpunkte. Aber: Es geht ja "nur" um die Punkte, wo sich mindestens 2 _oder_ mehr Linien schneiden, nicht um die Gesamtzahl der Schnittpunkte. Von daher musst du IMHO sowieso eine 2D Liste bauen, um die Anzahl der Punkt mit 2 oder mehr Schnitten zu zählen. Daraus kannst du dann auch sehr einfach die von __blackjack__ vorgeschlagene Grafik generieren.

    Gruß, noisefloor

  • Hallo,

    apropos Tag 5: ich bekomme für Teil 2 nicht die richtige Lösung für den2. Teil, obwohl mein Python-Code für die Testdaten aus der Aufgabe die korrekte Lösung (also 12) berechnet.

    Ich habe allerdings keine Ahnung, wo der Fehler ist und wo ich zur Fehlersuche ansetzen solle. Von Hand rechnen ist ja keine Option ;)

    Der Code ist im folgenden Spoiler, mein Ergebnis für Teil zwei ist 15969, was wohl zu niedrig ist.

    Spoiler anzeigen

    Sachdienliche Hinweise zur Änderung des Codes für die korrekte Lösung sind willkommen :)

    Gruß, noisefloor

  • Dennis89 DIe beiden Teilfragen waren ja in welche Form ich die Eingabe gebracht habe, und wie die Diagramme/Bilder entstanden sind. Und die habe ich beantwortet. ?

    An dem Pascal-Programm könnte man sich auch ganz gut für eine Python-Implementierung orientieren. Also mindestens mal was die Datentypen angeht. Also einen Punkt- oder Vektor-Datentyp und einen Typ für die Linie der die beiden Endpunkte zu einem zusammengesetzten Wert zusammenfasst.

    Hab's mal überarbeitet und Objekte aus den Records gemacht und alles soweit vorbereitet, dass man die Ozeankarte auch mit anderem Speicher für die Zeilen der Karte implementieren könnte, damit das auch auf Rechnern ohne 286er-Prozessor läuft, also beispielsweise mit EMS-Speicher oder temporäre Datei auf Platte.

    Spoiler anzeigen

    Tag 5 in Pascal, objectorientiert(er):

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

  • noisefloor Mit dem Programm bekomme ich für meine Eingedaten auch einen Wert der niedriger ist als das richtige Ergebnis. Es werden nicht alle Linien gezeichnet. Hier mal eine GIF-Animation in der die für meine Eingabedaten fehlenden Linien blinken:

    Speichern von 2D-Listen mit Werten bis max. 255 als PGM-Datei:

    Python
    def save_pgm(filename, data):
        max_value = max(map(max, data))
        if max_value > 255:
            raise ValueError(f"max value {max_value} too large")
        
        with open(filename, "wb") as file:
            file.write(
                f"P5\n{len(data[0])} {len(data)}\n{max_value} ".encode("ascii")
            )
            file.writelines(map(bytes, data))

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

  • Für die die vergessen haben, das heute der erste Advent ist oder für die, die diesen Thread vergessen haben, hole ich den mal wieder nach oben.

    Wer macht in welcher Sprache mit?

    Ich bin mit Python dabei und lasse mich überraschen wie weit ich komme.

    Grüße

    Dennis

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

  • Ich versuche auch dieses Jahr wieder am Ball zu bleiben. Die ersten drei Tage liessen sich in CBM BASIC V2 auf einem VIC-20 mit 3½ KiB RAM noch gut lösen. ?

    Ansonsten habe ich mir auch mal GW-BASIC auf einem XT-Rechner, also Intel 8088 Prozessor mit 4,77 Mhz angeschaut und bin überrascht wie schlecht das gegenüber dem VIC-20 (MOS 6502, etwas unter 1 Mhz) abschneidet. Ja es ist schneller, aber nicht mal doppelt so schnell, obwohl der Prozessor mehr als 4× so hoch getaktet ist, und die Laufwerke deutlich schneller sind. Der Preis vom PC war bei der Einführung astronomisch, selbst wenn man das mit dem Einführungspreis vom ca. 3 Jahre älteren VIC-20 vergleicht (1981, $299). Selbst QBasic ist lahm auf so einem XT und das gab es erst ab 1991. Wirklich schnell wird es erst mit Turbo Pascal. Kein Wunder dass das so beliebt war. Alternative: handgeschriebener Assembler. War ja für DOS-Programmierer auch sehr verbreitet, diese Attitüde das nur Assembler-Programme das wirklich Wahre sind.

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

  • Wer macht in welcher Sprache mit?

    Letztes Jahr hatte ich mitgemacht - mit bash. Fuer die Aufgaben ist es aber in einer hoeheren Programmiersprache viel leichter die Aufgaben zu loesen. Python ist nicht mein Favorite - und jetzt wieder mein go DevEnvironment zu reaktivieren ist mir gegeben der Timconstraints zu aufwaendig.

    Anyhow - es waren letztes Jahr nette und interessante Challenges - viel Spass allen Teilnehmern :)

Jetzt mitmachen!

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