Blog

Advent des Codes Tag 16: Flüche!

Serge Beaumont

Aktualisiert Oktober 21, 2025
4 Minuten

Ich wusste, dass es eines Tages kommen musste: diese Rätsel, bei denen Sie auf einem charakterbasierten Raster herumlaufen. Tag 15 war so ein Fall. Ich gehöre definitiv nicht zu den Leuten, die Algorithmen zur Durchquerung von Labyrinthen einfach aus der Luft zaubern. Um sie zu lernen, lese ich einen Überblick über den Algorithmus und versuche dann, ihn zu implementieren. Und dann fange ich an, mir den Kopf darüber zu zerbrechen, warum etwas nicht funktioniert oder Ihr Roboter nur entlang von 2 Koordinaten auf und ab geht usw. usw.

Also brauchte ich wieder eine Visualisierung , um die Dinge zu begreifen. Erster Versuch: Einfach halten. Verwenden Sie einfach eine ganze Reihe von print() Anweisungen, und in Kombination mit einer manuellen Pfadprogrammierung dachte ich, dass ich das gut hinbekommen würde. Haha, Herr Wastl, ich trotze Ihrem teuflischen Rätsel! Ich werde einfach manuell gehen! Ich dachte, ich wäre Mr. Smartypants, weil ich die Dinge so einfach hielt, aber ich musste einfach weiterlaufen... und weiterlaufen... und... nun ja.

def manual_route():
  top_cap = '131143133131413131231231231231323242323132324232313'
  to_bottom = '23234234234234234234232424122323232323232324124223242424'
  right_cave = '143143143114142424242142424242424141413123123123231314131313232232323131131'
  finish_bottom = '313232323224231313131313413141441413413413141414242424242441414141141424141131313133131444'
  finish_top_left = '131331313323223232324432332322323112222424'
  backtrack = '3311441111441144222242444'
  explore_right = '41421421421421421421424141341341413131323233131331311414141314141414414141313313143143143143141'
  from_chimney = '31323131431431413131231231231232313131414141441411'
  t_split_left = '3131313131231231231323243234232424112224232424242424242223233232324244242342342424111122223323231'
  appendix = '232424331131331314431313131323233131331314131323131413131231232313131414141441413141424142342423232324242421141414141133'
  backtrack_to_t = '442233333311441133'
  aufwärts_von_t = '1113134331313413411'
  yet_another_t = '4141221133313123123123123132323242424242232342331312323131443331313232323423423423423423242'
  going_down_left = '414111222242423242412412421413344224242423232323323244323323232322232312312323131413133'
  route = top_cap + to_bottom + right_cave + finish_bottom + finish_top_left + backtrack + explore_right + from_chimney + t_split_left + appendix + backtrack_to_t + going_up_from_t + yet_another_t + going_down_left
  Rückweg

Ja, ich war wirklich so dumm und ging auf "3", Strg-R, "41", Strg-R, 2, Strg-R... All das war meine manuelle Erkundung des Labyrinths. Ich war eine Art Zen, das gebe ich zu :-)

Also... war es Zeit für die richtige Sache. Ein Algorithmus, der sich an die Wand schmiegt, und curses. Ich ziehe es vor, so wenig externe Bibliotheken wie möglich zu verwenden, also habe ich mich an das Standardmodul curses gewandt. Das war etwas komplizierter als meine Verwendung von Pillow, weil Unix und History und Terminals und andere Seltsamkeiten. Zum Beispiel, dass jede Koordinate in der Reihenfolgeist. Aus Gründen.

verflucht Ausgabe von Advent of Code Rätsel Tag 16 Teil 2. Mit Sauerstoff gefülltes Labyrinth.
Wir sind in Sicherheit! Das Labyrinth ist mit Sauerstoff gefüllt! Und es lebe u2588, das Full Block Unicode Zeichen!

Es gibt tatsächlich eine ganze Menge raffinierter Dinge, die Sie mit curses tun können, wie Fenster und blinkende Zeichen, aber ich habe mich dafür entschieden, es eng an das Lösen von Rätseln zu koppeln. Das bedeutet, dass Sie einfach das Koordinatensystem des Rätsels eingeben können und die Projektion auf den Bildschirm für Sie erledigt ist.

Ein weiterer Teil ist die Handhabung der Initialisierung und des Abbruchs, was ein bisschen fummelig ist, aber in den Dokumenten klar erklärt wird. Aus diesem Grund habe ich mich entschieden, es als ContextManager zu implementieren, indem ich die Methoden enter() und exit() implementiere. Ich finde die with... Syntax sehr praktisch.

curses verfügt über eine nette Abstraktion, um mit großen Bereichen umzugehen, die außerhalb des projizierbaren Bereichs liegen, nämlich pad. Das bedeutet, dass wir uns keine Gedanken über die Bildschirmgröße machen müssen, wir können refresh() mit Parametern aufrufen, mit denen wir angeben können, welcher Teil von pad angezeigt werden soll.

Ich bin ziemlich zufrieden damit, wie die Convenience-Klasse ausgefallen ist. Hier ist eine einfache Möglichkeit, eine Reihe von Punkten in einer Liste darzustellen.

bounds = CursesVisualizer.boundaries(list_of_points, padding=1)
with CursesVisualizer(bounds) as cv:
 for point in list_of_points:
 cv.plot(point, '#')
 cv.refresh()

Schauen Sie sich die Convenience-Klasse hier an: viel Spaß cursing!

Advent des Codes 2019 Serie

Verfasst von

Serge Beaumont

Contact

Let’s discuss how we can support your journey.