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.)
la source
Réponses:
Python 2.7.9 - 21 bouteilles
En supposant que la spéculation d'ESultanik est juste sur ce que l'entrée est lorsque plusieurs prisonniers meurent
Algorithme: chaque prisonnier boit dans chaque bouteille sauf son nombre (le premier prisonnier ne boit pas la première bouteille). S'ils ne meurent pas, leur bouteille numérotée est empoisonnée. Si un seul prisonnier survit, la bouteille supplémentaire est empoisonnée.
la source
Perl 5 , 66 bouteilles
(72 bouteilles pour 21 prisonniers)
Les prisonniers sont divisés de manière optimale en 2 groupes. Les bouteilles sont regroupées en sets.
Chaque prisonnier du groupe 1 boira de tous les sets sauf un. Il y aura 1 ou 2 survivants. Les 1 ou 2 sets qui n'ont pas été bu par eux continueront jusqu'au jour 2.
Le jour 2, les prisonniers restants (y compris les survivants) boivent dans toutes les bouteilles restantes sauf une.
Lorsque 2 prisonniers survivent, les bouteilles qu'ils n'ont pas bu sont empoisonnées.
S'il ne reste qu'un prisonnier, la bouteille qu'ils ont tous bu est également suspecte.
Le code inclut des fonctionnalités supplémentaires pour faciliter les tests. Lorsque les bouteilles empoisonnées sont ajoutées en tant que paramètres supplémentaires, il ne demandera pas d'informations sur qui est décédé.
Tester
Test sans saisie manuelle
la source
Comme c'est la tradition, je posterai une réponse de référence à la dernière place.
Python - 7 bouteilles
Faites boire à chaque prisonnier une paire de bouteilles possible à l'exception de la paire des deux dernières. Si un prisonnier meurt, la paire que ce prisonnier a bu était celle empoisonnée. Sinon, ce sont les deux dernières bouteilles qui ont été empoisonnées.
Pour les attributions d'au moins des
n(n-1)/2 - 1
prisonniers, vous pouvez faire jusqu'à desn
bouteilles. Pourn = 7
, cette limite inférieure est20
.En réalité, nous n'avons besoin que d' un jour pour que cette solution fonctionne. Une solution de deux jours avec une portée similaire pourrait obtenir jusqu'à 20 bouteilles
N = 20
, mais c'est trop de travail pour une réponse triviale.la source