Нещодавно в Puzzling.SE виникла проблема, про яку я писав про визначення того, які дві пляшки з більшої кількості отруєні, коли отрута активується, лише якщо обидва компоненти випиті. Це в кінцевому підсумку було досить тяжким випробуванням, і більшість людей встигли зменшити його до 18 або 19 в'язнів, використовуючи абсолютно різні алгоритми.
Оригінальний вислів проблеми такий:
Ви правитель середньовічного царства, який любить влаштовувати вечірки. Придворний, який останній раз намагався отруїти одну з ваших пляшок вина, розлютився, дізнавшись, що вам вдалося визначити, яку пляшку він отруїв із 1000 лише десятьма в'язнями.
Цього разу він трохи хитріший. Він розробив композитну отруту
P
: бінарну рідину, яка лише смертельна, коли змішуються два індивідуально нешкідливі компоненти; це схоже на те, як працює епоксидна смола. Він прислав вам ще одну ящик з 1000 пляшок вина. Одна пляшка має компонент,C_a
а інша - компонентC_b
. (P = C_a + C_b
)Кожен, хто п’є обидва компоненти, загине від удару опівночі вночі, коли він випив остаточний компонент, незалежно від того, коли в день вбирали рідину. Кожен компонент отрути залишається в організмі, поки другий компонент не активізується, тому, якщо ви будете пити один компонент один день, а інший - наступний, ви помрете в півночі наприкінці другого дня.
Ви маєте два дні до наступної вечірки. Яку мінімальну кількість ув'язнених потрібно використовувати для тестування, щоб визначити, які дві пляшки забруднені та який алгоритм потрібно дотримуватись із цією кількістю ув'язнених?
Бонус
Крім того, припустимо, у вас було встановлене обмеження в 20 в’язнів, яке максимальне число пляшок ви могли теоретично випробувати і прийти до точного висновку про те, які пляшки постраждали?
Ваше завдання - створити програму для вирішення проблеми з бонусом. З огляду на n
ув'язнених, ваша програма розробить графік тестування, який зможе виявити дві отруєні пляшки серед m
пляшок, де m
це можливо більше.
Ваша програма спочатку буде приймати як вхід кількість N
, кількість ув'язнених. Потім буде виведено:
M
, кількість пляшок, яку ви спробуєте випробувати. Ці пляшки будуть марковані від1
доM
.N
лінії, що містять етикетки пляшок, які випиє кожен ув'язнений.
Тоді ваша програма прийме як вхід, який ув'язнені померли в перший день, ув'язнений на першій лінії буде 1
, наступний рядок і 2
т. Д. Потім він виведе:
N
більше рядків, що містять етикетки пляшок, які випиє кожен ув'язнений. Померлі в’язні матимуть порожні рядки.
Тоді ваша програма прийме як вхід, який ув'язнені померли на другий день, і виведе два числа, A
і B
, представляючи, які дві пляшки, на вашу думку, програма містить отруту.
Приклад для двох в'язнів і чотирьох пляшок може бути таким, якщо пляшки 1
і 3
отруєні:
> 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.
Графік тестування вашої програми повинен успішно визначати кожну можливу пару отруєних пляшок, щоб вона була дійсною.
Ваша програма буде оцінена за такими критеріями, щоб:
Максимальна кількість пляшок, яку він може помітити для справи
N = 20
.Кількість пляшок для корпусу
N = 21
та послідовно більше випадків після цього.Довжина коду. (Коротший код виграє.)