![]() |
|||
Das Drei-Töchter-ProblemWenn man schlecht im Kopfrechnen ist muss man sich halt anders zu helfen wissen. So ging es mir auch als ich über das "Drei-Töchter-Problem" gestolpert bin. In eine nette Geschichte verpackt kann die Aufgabenstellung hier nachgeschlagen werden, für die weitere Betrachtung taugt allerdings auch die folgende Zusammenfassung: Das Alter dreier Töchter soll miteinander multipliziert 36 ergeben, die Summe soll einer nicht genannten Zahl entsprechen. Durch die Nennung der Summe darf die Lösung jedoch noch nicht eindeutig werden - dazu bedarf es der weiteren Information, dass eine der Töchter die älteste ist. Durch Zerlegung in drei Faktoren erhalten wir eine Liste von möglichen Alterskombinationen. Zwei dieser Kombinationen werden eine gleiche Summe bilden, und die Lösung ist diejenige der beiden Kombinationen, bei der die beiden ältesten Töchter keine Zwillinge sind. Um also den Kopf nicht zu sehr anstregen zu müssen lösen wir die Aufgabe mit Hilfe des Rechners. Die Wahl des Hilfsmittels fällt auf SQL! Zunächst erstellen wir eine Tabelle mit allen Werten, die das Alter einer der Töchter annehmen kann:
CREATE TEMPORARY TABLE z( f INT );
INSERT INTO z SELECT 1; INSERT INTO z SELECT 2; ... INSERT INTO z SELECT 35; INSERT INTO z SELECT 36; Mit Hilfe dieser Tabelle können wir nun die Kombinationen durchgehen, die die erste Forderung erfüllen:
SELECT a.f, b.f, c.f FROM z AS a, z AS b, z AS c WHERE (a.f*b.f*c.f=36) AND (a.f<=b.f AND b.f<=c.f) GROUP BY a.f, b.f, c.f;
Erweitert um die zweite Bedingung (die Summe ermöglicht keine eindeutige Lösung) erhalten wir das folgende Statement:
SELECT a1+a2+a3 AS s, COUNT(*) AS s_count FROM (SELECT a.f AS a1, b.f AS a2, c.f AS a3 FROM z AS a, z AS b, z AS c WHERE (a.f*b.f*c.f=36) AND (a.f<=b.f AND b.f<=c.f) GROUP BY a.f, b.f, c.f) GROUP BY s HAVING s_count>1;
Die eindeutige Lösung erhalten wir nun, indem wir die Kombination auswählen, die in der Summe s ergibt und eine Tochter die älteste ist:
SELECT a.f, b.f, c.f FROM z AS a, z AS b, z AS c, (SELECT a1+a2+a3 AS s, COUNT(*) AS s_count FROM (SELECT a.f AS a1, b.f AS a2, c.f AS a3 FROM z AS a, z AS b, z AS c WHERE (a.f*b.f*c.f=36) AND (a.f<=b.f AND b.f<=c.f) GROUP BY a.f, b.f, c.f) GROUP BY s HAVING s_count>1) WHERE (a.f<=b.f AND b.f<c.f) AND (a.f*b.f*c.f=36) AND (a.f+b.f+c.f=s);
Wer sich jetzt für das Endergebnis interessiert, den setze ich (fies, nicht wahr?) jetzt vor die Wahl sich im Kopfrechnen zu üben oder ein Datenbanksystem zu bemühen. Zum Ausprobieren eignet sich SQLite besonders gut, da es nicht installiert (und/oder konfiguriert) werden muss. MySQL eignet sich wieder einmal nicht so gut: Sub-Selects werden erst ab der 4er-Version unterstützt und Joins auf sich selbst gehen mit temporären Tabellen überhaupt nicht! (Warum soll ich hinterher aufräumen, wo es das System auch selbst könnte?!?) |
Die Community:
Noch kein Mitglied? Jetzt kostenlos anmelden!
|
|