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 list

Damit 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_long
FROM stations
WHERE 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_2
FROM stations s1, stations s2
WHERE 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:

Terminal window
Not implemented Error:
DuckLake does not support functions

Es gibt zwei Möglichkeiten, das Problem zu umgehen.

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.