Recientemente en Puzzling.SE, escribí un problema acerca de determinar qué dos botellas de un número mayor están envenenadas cuando el veneno solo se activa si ambos componentes están borrachos. Terminó siendo una experiencia terrible, con la mayoría de las personas logrando reducirlo a 18 o 19 prisioneros usando algoritmos completamente diferentes.
La declaración original del problema es la siguiente:
Eres el gobernante de un reino medieval al que le encantan las fiestas. El cortesano que trató de envenenar una de sus botellas de vino la última vez se enfureció al saber que logró identificar qué botella había envenenado de 1,000 con solo diez prisioneros.
Esta vez es un poco más astuto. Ha desarrollado un veneno compuesto
P
: un líquido binario que solo es mortal cuando dos componentes individualmente inofensivos se mezclan; Esto es similar a cómo funciona el epoxi. Te ha enviado otra caja de 1,000 botellas de vino. Una botella tiene componenteC_a
y otra tiene componenteC_b
. (P = C_a + C_b
)Cualquiera que beba ambos componentes morirá a la medianoche de la noche en que bebió el componente final, independientemente de cuándo en el día en que bebieron el líquido. Cada componente de veneno permanece en el cuerpo hasta que se activa el segundo componente, por lo que si bebe un componente un día y otro componente al día siguiente, morirá a medianoche al final del segundo día.
Tienes dos días antes de tu próxima fiesta. ¿Cuál es el número mínimo de prisioneros que necesita usar para las pruebas para identificar qué dos botellas están contaminadas y qué algoritmo necesita seguir con ese número de prisioneros?
Bono
Además, suponga que tiene un límite fijo de 20 prisioneros a su disposición, ¿cuál es el número máximo de botellas que en teoría podría probar y llegar a una conclusión precisa sobre qué botellas se vieron afectadas?
Su tarea es construir un programa para resolver el problema de bonificación. Dado a los n
presos, su programa diseñará un cronograma de pruebas que podrá detectar las dos botellas envenenadas entre m
botellas, donde m
sea lo más grande posible.
Inicialmente, su programa tomará como entrada el número N
, el número de prisioneros. Luego generará:
M
, la cantidad de botellas que intentará probar. Estas botellas serán etiquetadas de1
aM
.N
líneas, que contienen las etiquetas de las botellas que tomará cada prisionero.
Su programa tomará como entrada qué presos murieron el primer día, con el prisionero en la primera línea 1
, la siguiente línea 2
, etc. Luego, generará:
N
más líneas, que contienen las etiquetas de las botellas que tomará cada prisionero. Los prisioneros muertos tendrán líneas en blanco.
Luego, su programa tomará como entrada qué prisioneros murieron en el segundo día, y generará dos números A
y B
representará las dos botellas que su programa cree que contienen el veneno.
Un ejemplo de entrada para dos prisioneros y cuatro botellas podría ser así, si las botellas 1
y 3
están envenenadas:
> 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.
El programa de pruebas de su programa debe determinar con éxito cada posible par de botellas envenenadas para que sea un envío válido.
Su programa se puntuará según los siguientes criterios, en orden:
El número máximo de botellas que puede discernir para el caso
N = 20
.El número de botellas para el caso
N = 21
, y sucesivamente casos más altos después de eso.La longitud del código. (El código más corto gana).
fuente
Respuestas:
Python 2.7.9 - 21 botellas
Asumiendo que la especulación de ESultanik es correcta sobre cuál es la información cuando mueren varios prisioneros
Algoritmo: cada preso bebe de cada botella excepto su número (el primer preso no bebe la primera botella). Si no mueren, su botella número está envenenada. Si solo un prisionero sobrevive, la botella extra está envenenada.
fuente
Perl 5 , 66 botellas
(72 botellas para 21 prisioneros)
Los prisioneros se dividen de manera óptima en 2 grupos. Las botellas se agrupan en juegos.
Cada prisionero del grupo 1 beberá de todos los grupos excepto uno. Habrá 1 o 2 sobrevivientes. Los 1 o 2 sets que no fueron tomados por ellos continuarán hasta el día 2.
El día 2, los prisioneros restantes (incluidos los sobrevivientes) beben de todas las botellas restantes, excepto una.
Cuando 2 prisioneros sobreviven, las botellas que no bebieron están envenenadas.
Si solo queda 1 prisionero, entonces la botella que bebieron todos también es sospechosa.
El código incluye una funcionalidad adicional para facilitar las pruebas. Cuando las botellas aplanadas se agregan como parámetros adicionales, no solicitará información sobre quién murió.
Prueba
Prueba sin entrada manual
fuente
Como es tradición, publicaré una respuesta de referencia de último lugar.
Python - 7 botellas
Haga que cada prisionero tome un posible par de botellas, excepto el par de las dos últimas. Si algún prisionero muere, la pareja que bebió ese prisionero fueron los envenenados. De lo contrario, fueron las dos últimas botellas que fueron envenenadas.
Para asignaciones de al menos
n(n-1)/2 - 1
prisioneros, puede hacer hastan
botellas. Paran = 7
, este límite inferior es20
.Solo necesitamos un día para que esta solución funcione. Una solución de dos días con un alcance similar podría obtener hasta 20 botellas por
N = 20
, pero es demasiado trabajo para una respuesta trivial.fuente