Kürzlich bei Puzzling.SE gab es ein Problem, das ich darüber schrieb, welche zwei Flaschen einer größeren Anzahl vergiftet sind, wenn das Gift nur aktiviert wird, wenn beide Komponenten getrunken sind. Es war eine ziemliche Tortur, und die meisten Menschen schafften es, es mit völlig anderen Algorithmen auf 18 oder 19 Gefangene zu bringen.
Die ursprüngliche Problemstellung lautet wie folgt:
Sie sind der Herrscher eines mittelalterlichen Königreichs, das gerne Partys veranstaltet. Der Höfling, der beim letzten Mal versucht hat, eine Ihrer Weinflaschen zu vergiften, war wütend darüber, dass Sie mit nur zehn Gefangenen herausgefunden haben, welche Flasche er von 1.000 vergiftet hat.
Diesmal ist er ein bisschen schlauer. Er hat ein zusammengesetztes Gift entwickelt
P
: eine binäre Flüssigkeit, die nur dann tödlich ist, wenn sich zwei einzeln harmlose Komponenten mischen. Das funktioniert ähnlich wie Epoxy. Er hat Ihnen eine weitere Kiste mit 1.000 Weinflaschen geschickt. Eine Flasche hat eine KomponenteC_a
und eine andere hat eine KomponenteC_b
. (P = C_a + C_b
)Jeder, der beide Komponenten trinkt, stirbt um Mitternacht in der Nacht, in der er die letzte Komponente getrunken hat, unabhängig davon, wann er am Tag die Flüssigkeit getrunken hat. Jede Giftkomponente bleibt im Körper, bis die zweite Komponente aktiviert wird. Wenn Sie also an einem Tag eine Komponente und am nächsten eine andere Komponente trinken, sterben Sie am Ende des zweiten Tages um Mitternacht.
Sie haben zwei Tage vor Ihrer nächsten Party. Wie viele Gefangene müssen Sie mindestens testen, um festzustellen, welche zwei Flaschen befallen sind, und welchen Algorithmus müssen Sie bei dieser Anzahl von Gefangenen anwenden?
Bonus
Angenommen, Sie hatten ein festes Limit von 20 Gefangenen zur Verfügung. Wie viele Flaschen konnten Sie theoretisch maximal testen und zu einer genauen Schlussfolgerung gelangen, welche Flaschen betroffen waren?
Ihre Aufgabe ist es, ein Programm zur Lösung des Bonusproblems zu erstellen. Angesichts von n
Gefangenen erstellt Ihr Programm einen Testplan, der es ermöglicht, die beiden vergifteten Flaschen in m
Flaschen zu finden, m
sofern diese so groß wie möglich sind.
In Ihrem Programm wird zunächst N
die Anzahl der Gefangenen als Eingabe verwendet . Es wird dann ausgegeben:
M
, die Anzahl der Flaschen, die Sie testen möchten. Diese Flaschen werden von1
bis etikettiertM
.N
Linien, die die Etiketten der Flaschen enthalten, die jeder Gefangene trinkt.
Ihr Programm nimmt dann als Eingabe, welche Gefangenen am ersten Tag gestorben sind, wobei der Gefangene in der ersten Zeile 1
, die nächste Zeile 2
usw. ist. Dann gibt es Folgendes aus:
N
Weitere Zeilen mit den Etiketten der Flaschen, die jeder Gefangene trinkt. Tote Gefangene haben leere Zeilen.
Ihr Programm nimmt dann als Eingabe, welche Gefangenen am zweiten Tag gestorben sind, und gibt zwei Zahlen aus, A
und B
stellt dar, welche zwei Flaschen Ihres Programms das Gift enthalten.
Eine Beispieleingabe für zwei Gefangene und vier Flaschen könnte als solche gelten, wenn Flaschen 1
und 3
vergiftet sind:
> 2 // INPUT: 2 prisoners
4 // OUTPUT: 4 bottles
1 2 3 // OUTPUT: prisoner 1 will drink 1, 2, 3
1 4 // OUTPUT: prisoner 2 will drink 1, 4
> 1 // INPUT: only the first prisoner died
// OUTPUT: prisoner 1 is dead, he can't drink any more bottles
3 // OUTPUT: prisoner 2 drinks bottle 3
> 2 // INPUT: prisoner 2 died
1 3 // OUTPUT: therefore, the poisoned bottles are 1 and 3.
The above algorithm may not actually work in all
cases; it's just an example of input and output.
Der Testplan Ihres Programms muss jedes mögliche Paar vergifteter Flaschen erfolgreich ermitteln, damit es eine gültige Einreichung ist.
Ihr Programm wird nach folgenden Kriterien bewertet:
Die maximale Anzahl Flaschen, die für den Fall erkannt werden kann
N = 20
.Die Anzahl der Flaschen für den Fall
N = 21
und nacheinander höhere Fälle danach.Die Länge des Codes. (Kürzere Code gewinnt.)