Récemment à Puzzling.SE, il y a eu un problème que j'ai écrit sur la détermination de deux bouteilles parmi un plus grand nombre qui sont empoisonnées lorsque le poison ne s'active que si les deux composants sont ivres. Cela a fini par être une véritable épreuve, la plupart des gens réussissant à le ramener à 18 ou 19 prisonniers en utilisant des algorithmes complètement différents.
L'énoncé du problème d'origine est le suivant:
Vous êtes le dirigeant d'un royaume médiéval qui aime organiser des fêtes. Le courtisan qui a tenté d'empoisonner une de vos bouteilles de vin la dernière fois était furieux d'apprendre que vous avez réussi à identifier la bouteille qu'il avait empoisonnée sur 1000 avec seulement dix prisonniers.
Cette fois, il est un peu plus rusé. Il a développé un poison composite
P
: un liquide binaire qui n'est mortel que lorsque deux composants individuellement inoffensifs se mélangent; ceci est similaire au fonctionnement de l'époxy. Il vous a envoyé une autre caisse de 1 000 bouteilles de vin. Une bouteille a un composantC_a
et une autre a un composantC_b
. (P = C_a + C_b
)Quiconque boit les deux composants mourra sur le coup de minuit la nuit où ils ont bu le composant final, quel que soit le jour où ils ont bu le liquide. Chaque composant toxique reste dans le corps jusqu'à ce que le deuxième composant s'active, donc si vous buvez un composant un jour et un autre composant le lendemain, vous mourrez à minuit à la fin du deuxième jour.
Vous avez deux jours avant votre prochaine fête. Quel est le nombre minimum de prisonniers que vous devez utiliser pour effectuer des tests afin d'identifier les deux bouteilles contaminées et quel algorithme devez-vous suivre avec ce nombre de prisonniers?
Bonus
De plus, supposons que vous disposiez d'une limite fixe de 20 prisonniers, quel est le nombre maximum de bouteilles que vous pourriez théoriquement tester et arriver à une conclusion précise sur les bouteilles qui ont été affectées?
Votre tâche consiste à créer un programme pour résoudre le problème des bonus. Étant donné les n
prisonniers, votre programme élaborera un calendrier de tests qui sera en mesure de détecter les deux bouteilles empoisonnées parmi les m
bouteilles, là où elles m
sont aussi grandes que possible.
Votre programme prendra initialement en entrée le nombre N
, le nombre de détenus. Il affichera alors:
M
, le nombre de bouteilles que vous tenterez de tester. Ces bouteilles seront étiquetées du1
auM
.N
lignes contenant les étiquettes des bouteilles que chaque détenu va boire.
Votre programme prendra alors en entrée quels prisonniers sont morts le premier jour, avec le prisonnier sur la première ligne 1
, la ligne suivante 2
, etc. Ensuite, il produira:
N
plus de lignes, contenant les étiquettes des bouteilles que chaque prisonnier va boire. Les prisonniers morts auront des lignes blanches.
Votre programme prendra alors en entrée quels prisonniers sont morts le deuxième jour, et sortira deux nombres, A
et B
, représentant les deux bouteilles que votre programme pense contenir le poison.
Un exemple d'entrée pour deux prisonniers et quatre bouteilles peut être utilisé comme tel, si des bouteilles 1
et 3
sont empoisonnées
> 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.
Le calendrier des tests de votre programme doit déterminer avec succès chaque paire possible de bouteilles empoisonnées afin que ce soit une soumission valide.
Votre programme sera noté selon les critères suivants, dans l'ordre:
Le nombre maximum de bouteilles qu'il peut discerner pour la caisse
N = 20
.Le nombre de bouteilles pour la caisse
N = 21
, puis les caisses successivement plus élevées par la suite.La longueur du code. (Le code plus court gagne.)