Recentemente, no Puzzling.SE, escrevi um problema sobre determinar quais duas garrafas de um número maior são envenenadas quando o veneno é ativado apenas se os dois componentes estiverem bêbados. Acabou sendo uma provação, com a maioria das pessoas conseguindo reduzir para 18 ou 19 prisioneiros usando algoritmos completamente diferentes.
A declaração do problema original é a seguinte:
Você é o governante de um reino medieval que adora dar festas. O cortesão que tentou envenenar uma de suas garrafas de vinho da última vez ficou furioso ao saber que você conseguiu identificar qual garrafa ele havia envenenado em mil com apenas dez prisioneiros.
Desta vez, ele é um pouco mais habilidoso. Ele desenvolveu um veneno composto
P
: um líquido binário que só é mortal quando dois componentes individualmente inofensivos se misturam; isso é semelhante a como o epóxi funciona. Ele enviou outro engradado de 1.000 garrafas de vinho. Um frasco tem componenteC_a
e outro tem componenteC_b
. (P = C_a + C_b
)Quem bebe os dois componentes morre na meia-noite da noite em que bebeu o componente final, independentemente de quando durante o dia ingeriu o líquido. Cada componente venenoso permanece no corpo até que o segundo componente seja ativado; portanto, se você beber um componente um dia e outro componente no dia seguinte, morrerá à meia-noite no final do segundo dia.
Você tem dois dias antes da sua próxima festa. Qual é o número mínimo de prisioneiros que você precisa usar para testar, a fim de identificar quais duas garrafas estão contaminadas e qual algoritmo você precisa seguir com esse número de prisioneiros?
Bônus
Além disso, suponha que você tivesse um limite fixo de 20 prisioneiros à sua disposição, qual é o número máximo de garrafas que você poderia testar teoricamente e chegar a uma conclusão precisa sobre quais garrafas foram afetadas?
Sua tarefa é criar um programa para resolver o problema do bônus. Dados os n
prisioneiros, seu programa criará uma programação de testes que será capaz de detectar as duas garrafas envenenadas entre as m
garrafas, sempre que m
for o maior possível.
Seu programa inicialmente terá como entrada o número N
, o número de prisioneiros. Em seguida, ele produzirá:
M
, o número de garrafas que você tentará testar. Essas garrafas serão rotuladas de1
paraM
.N
linhas, contendo os rótulos das garrafas que cada prisioneiro irá beber.
Seu programa tomará como entrada os prisioneiros que morreram no primeiro dia, com o prisioneiro na primeira linha 1
, na próxima linha 2
, etc. Em seguida, ele produzirá:
N
mais linhas, contendo os rótulos das garrafas que cada prisioneiro irá beber. Prisioneiros mortos terão linhas em branco.
Seu programa tomará como entrada os prisioneiros que morreram no segundo dia e produzirá dois números, A
eB
, representando quais as duas garrafas que seu programa acha que contêm o veneno.
Um exemplo de entrada para dois prisioneiros e quatro garrafas pode ir como tal, se garrafas 1
e 3
forem 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.
A programação de testes do seu programa deve determinar com êxito cada possível par de garrafas envenenadas para que seja um envio válido.
Seu programa será pontuado com os seguintes critérios, em ordem:
O número máximo de garrafas que pode discernir para o caso
N = 20
.O número de garrafas para o caso
N = 21
, e casos sucessivamente mais altos depois disso.O comprimento do código. (O código mais curto vence.)