2025-09-11
Buchstabenrätsel mit DuckDB lösen
Gábor Szárnyas
Die Nederlandse Spoorwegen (NS) veröffentlicht jede Woche ein „Buchstabenrätsel“,
bei dem ein Begriff vorgegeben wird, dessen Buchstaben sich im Namen eines niederländischen Bahnhofs finden.
Für eine Übereinstimmung muss es kein perfektes Anagramm sein – zum Beispiel passt Amsterdam (9 Buchstaben) sowohl zu mastered (8 Buchstaben) als auch zu Dream Master (11 Buchstaben), weil alle drei Begriffe dieselben Buchstaben enthalten, nur mit unterschiedlicher Wiederholungshäufigkeit. Nennen wir das ein „schwaches Anagramm“.
Das Rätsel in der ersten Septemberwoche war Clumsy Rental Red. Versuchen wir, die Lösung mit DuckDB zu finden!
Buchstaben-Makro
Zuerst legen wir ein Makro an, das einen String in eine sortierte Liste eindeutiger Zeichen verwandelt:
CREATE MACRO order_letters(s) AS lower(s) -- convert all characters to lowercase .regexp_replace( -- remove all non-Unicode letters '[^\p{L}]', '', 'g' ) .string_to_array('') -- turn the string into a list .list_distinct() -- eliminate duplicate elements from the list .list_sort(); -- sort the listDamit können wir prüfen, ob zwei Begriffe schwache Anagramme sind:
SELECT order_letters('Amsterdam') AS letters_1, order_letters('mastered') AS letters_2, order_letters('Dream Master') AS letters_3, letters_1 = letters_2 AS matches_1, letters_1 = letters_3 AS matches_2;| letters_1 | letters_2 | letters_3 | matches_1 | matches_2 |
|---|---|---|---|---|
| [a, d, e, m, r, s, t] | [a, d, e, m, r, s, t] | [a, d, e, m, r, s, t] | true | true |
Tatsächlich sind beide Ausdrücke schwache Anagramme von Amsterdam!
Abgleich mit Bahnhofsnamen
Um das Rätsel zu lösen, brauchen wir eine Liste von Bahnhöfen. Glücklicherweise gehören zu unseren Lieblingsdatensätzen bei DuckDB die niederländischen Bahndatensätze, einschließlich Fahrten und Bahnhöfe. Wir können eine Tabelle mit den Bahnhofsnamen anlegen:
CREATE TABLE stations AS FROM 'https://blobs.duckdb.org/nl-railway/stations-2023-09.csv';Dann können wir die Bahnhofsnamen auswählen, die schwache Anagramme des Rätsels sind:
SELECT name_longFROM stationsWHERE order_letters(name_long) = order_letters('Clumsy Rental Red');Wir verderben die Lösung nicht, aber Sie können sie unten aufdecken.
Klicken Sie, um die Lösung zu sehen.
[Lelystad Centrum](https://en.wikipedia.org/wiki/Lelystad_Centrum_railway_station)Tabellenmakro zum Finden schwacher Anagramme
Um einen Bahnhofsnamen zu finden, der ein schwaches Anagramm zu einem Begriff ist, können wir ein Tabellenmakro nutzen:
CREATE MACRO find_weak_anagram(s) AS TABLE SELECT name_long FROM stations WHERE order_letters(name_long) = order_letters(s);Dann finden wir die Lösung mit einer einfachen SQL-Anweisung:
FROM find_weak_anagram('Clumsy Rental Red');Schwache-Anagramm-Bahnhofspaare
Wir wurden neugierig: Gibt es zwei Bahnhöfe, deren Namen schwache Anagramme voneinander sind? Wir können ein kartesisches Produkt der Bahnhofsnamen bilden und ihre sortierten Buchstaben vergleichen:
SELECT s1.name_long AS station_1, s2.name_long AS station_2FROM stations s1, stations s2WHERE s1.name_long.order_letters() = s2.name_long.order_letters() -- ensure symmetry-breaking AND s1.name_long < s2.name_long -- make sure the station names don't contain each other AND NOT s1.name_long.contains(s2.name_long) AND NOT s2.name_long.contains(s1.name_long);Es gibt tatsächlich drei Bahnhofspaare, deren Namen schwache Anagramme voneinander sind:
| station_1 | station_2 |
|---|---|
| Melsele | Selm |
| Etten-Leur | Lunteren |
| Diemen Zuid | Emmen Zuid |
Aufräumen
Die meiste Zeit müssen Sie nach einem einfachen DuckDB-Skript nicht aufräumen: Das Schließen der In-Memory-Datenbanksitzung erledigt das Aufräumen. Es lohnt sich aber darauf hinzuweisen, dass Makros in DuckDB persistiert werden und das in die Quere kommen kann – z. B. beim Kopieren der Datenbank in ein DuckLake:
ATTACH 'ducklake:metadata.ducklake' AS my_ducklake;COPY FROM DATABASE memory TO my_ducklake;DuckLake unterstützt keine Makros (Funktionen), daher wirft es folgenden Fehler:
Not implemented Error:DuckLake does not support functionsEs gibt zwei Möglichkeiten, das Problem zu umgehen.
-
Wenn Sie die Makros behalten müssen und DuckDB als Catalog-Datenbank für DuckLake nutzen, können Sie das DuckDB-zu-DuckLake-Migrationsskript verwenden. Das migriert die Makros in den Catalog Ihres DuckLake.
-
Wenn Sie die Makros nicht brauchen oder die Catalog-Datenbank des Ziels sie nicht unterstützt, können Sie sie mit folgenden Befehlen löschen:
DROP MACRO order_letters;DROP MACRO TABLE find_weak_anagram;Ohne die Makros gelingt das Kopieren nach DuckLake.
Zusammenfassung
Das war unser kurzer Leitfaden zum Lösen des NS-Rätsels. Ist das ein Datenbankproblem? Nicht wirklich, aber DuckDBs SQL erlaubt es, es knapp zu formulieren und in weniger als 0,1 Sekunden zu lösen! Und ja, ChatGPT kann dieses Rätsel lösen – aber es braucht fast eine Minute (und eine Menge Rechenressourcen), um sich durchzurechnen.
Viel Spaß beim Rätseln!
Diese Woche lautet das Rätsel
Zere Tanda Voozan. Die Lösung des wöchentlichen Rätsels finden Sie auf der NS-Website.
Update zu schwachen vs. starken Anagrammen
Leser-Feedback hat gezeigt, dass die NS-Rätsel starke Anagramme sind (mit derselben Buchstabenanzahl wie der Bahnhofsname) und der Rätselbegriff der ersten Septemberwoche tatsächlich Clumsy Rental Ted und nicht Clumsy Rental Red war!
Letzteres lässt sich nicht mehr prüfen, aber wir haben historische Daten angesehen, sie durch unser DuckDB-Löser-Skript gejagt, und es stellte sich heraus, dass es in 95 % der Fälle starke Anagramme sind.
Gelegentlich gibt es aber auch schwache Anagramme wie Alleen Costume Hut für Houten Castellum, obwohl Rätselbegriff und Bahnhofsname unterschiedlich viele e-Buchstaben haben.