
Пролог
При устройстве на работу меня уже второй раз спрашивают одну и ту же задачу про мышей и отраву. Они как будто из одной методички вопросы берут. Обычно такие логические задачи задают компании, которые высокого мнения о себе. Думаю настало время выдать исчерпывающий ответ на эту тему.
Постановка задачи:
Есть 1000 одинаковых колб с прозрачной жидкостью. В 999 колбах вода, а в одной случайной колбе - отрава. Если мышь попробует отраву, то она погибнет через 1 час (тот час же).
--Как при помощи 10 мышей найти колбу с отравой? Спойлер: Угощать только тех мышей, чей номер равен взведённому биту в двоичном номере колбы. И так для каждой колбы.
--Сколько времена потребуется, чтобы найти отраву? Спойлер: 1 час
--Как при этом погубить как можно меньше мышей? Спойлер: приоритет надо отдавать тем номерам колб, у которых меньшее количество взведенных бит. Меньшая сумма бит.
--А если участие мыши в опыте стоит 100 рублей, а отдельно приобретаемая лицензия на её убийство - тысячу? Как минимизировать расходы на эксперимент?
Пояснения:
1--Любая концентрация отравы приводит к гибели мыши.
2--Метаболизм каждой отдельной мыши не одинаковый и является случайной величиной. После получения отравы одна мышь погибнет через 55 мин, другая через 45 мин, третья через 1 мин. Но через час после получения отравы точно никто не выживет.
I--Иногда задачу перефразируют в контексте "компьютеры и вирусы". Якобы есть 200 программ, одна программа с вирусом и есть 9 DeskTop-ов для проверки. Вирусная программа через неделю после установки сносит OS, стирает весь жесткий диски, выжигает электронную лучевую трубку монитора в 7 местах и прочее. Надо за 1 неделю выявить эту бажную программу.
II--На сайте LeetCode задача и вовсе перефразирована в контексте бедных свинюков (poor-pigs).
458. Poor Pigs
There are buckets
buckets of liquid, where exactly one of the buckets is poisonous. To figure out which one is poisonous, you feed some number of (poor) pigs the liquid to see whether they will die or not. Unfortunately, you only have minutesToTest
minutes to determine which bucket is poisonous.
You can feed the pigs according to these steps:
Choose some live pigs to feed.
For each pig, choose which buckets to feed it. The pig will consume all the chosen buckets simultaneously and will take no time. Each pig can feed from any number of buckets, and each bucket can be fed from by any number of pigs.
Wait for
minutesToDie
minutes. You may not feed any other pigs during this time.After
minutesToDie
minutes have passed, any pigs that have been fed the poisonous bucket will die, and all others will survive.Repeat this process until you run out of time.
Given buckets
, minutesToDie
, and minutesToTest
, return the minimum number of pigs needed to figure out which bucket is poisonous within the allotted time.
Определения
Для понимания дальнейшего разговора надо вспомнить вот этот набор определений:
бит - разряд в десятичной представлении числа. Бит может принимать только значение 0 или 1.
триггер - физический прибор для хранения одного бита информации.
регистр - массив триггеров. Физический прибор для хранения целых чисел.
взведённый бит - тот бит, который равен единице. Например в десятичном числе 8=0b1000 взведенный бит - это 3ий. В числе 4=0b100 взведенный бит - это 2. Отсчет от нуля справа налево.
Решение
По сути это задача на знание двоичной системы счисления. Те, кто умеют переводить из dec в bin скорее всего её решит.
Фаза 1: Занумеровать пробирки
Каждой пробирке надо поставить в соответствие десятично число от 1 до 1000. Можно на каждую пробирку наклеить номер.
Фаза 2: Заполнить таблицу двоичного представления чисел номеров колб
Как известно, в мире существует множество систем счисления. Вот самые распространенные: двоичная, восьмеричная, десятичная и шестнадцатеричная. Мы будет работать с десятичной и двоичной.
Номер колбы, dec |
Номер колбы, bin |
Количество взведенных битов в номере колбы |
0 |
00_0000_0000 |
0 |
1 |
00_0000_0001 |
1 |
2 |
00_0000_0010 |
1 |
3 |
00_0000_0011 |
2 |
.... |
.... |
|
999 |
11_1110_0111 |
8 |
1000 |
11_1110_1000 |
6 |
вот первые несколько номеров

К слову, число ноль тоже надо использовать для перечисления колб.
Фаза 3: Занумеровать мышей
Каждой мыши надо присвоить порядковый номер. От нуля до 9. Мышь будет выступать в качестве бита (триггера).
Фаза 4: Мышь это бит
Мышей мы занумеровали, чтобы сделать из массива мышей воображаемый регистр.
Фаза 5: угощение мышей
А теперь настало время угощать мышей. Делать это надо аккуратно. Сейчас объясню как. Мы берём пробирку, смотрим на ее номер, переводим номер в двоичное представление, выписываем номера установленных в 1 битов и даем испить из этой пробирки только тем мышам, у которых номер совпадает с номером установленного единичного бита.
Пример:
Вот колба 564. Бинарное представление 564=0b 0010_0011_0100. Установленные биты это:2,4,5,9. Это значит, что из колбы 564 надо дать попробовать по капле мышам 2, 4, 5 и 9 . Остальных пропустить.
Номер мыши --> |
9 |
8 |
7 |
6 |
5 |
4 |
3 |
2 |
1 |
0 |
номер пробирки \/ |
двоичное представление номера пробирки |
1 |
0 |
0 |
0 |
1 |
1 |
0 |
1 |
0 |
0 |
564 |
угостить 9 |
угостить 5 |
угостить 4 |
угостить 2 |
И так для всех 1000 колб. Берем колбу и угощаем из нее от нуля до 9 мышей в зависимости от номера колбы. У нас не будет такого, что из одной колбы получат порцию все мыши, так как нет колбы с номером 11_1111_1111=1023.
Получается, что каждая мышь получит коктейль составленный из половины всех пробирок. Нулевая мышь попробует жидкость из всех нечетных пробирок. Вторая мышь попробует из 2; 3; 6; 7; 10; 11 и т д. И так далее. Можно сначала аккуратно составить коктейли, а затем вручить их мышам. Либо все коктейли получатся отравлены, либо частично отравлены, либо все с водой. Тут уж как повезёт.
Все эти коктейли можно приготовить очень быстро, если есть автоматический лабораторный дозатор.

После этого можно засекать 1 час, садиться и просто ждать. Через час должно умереть от 0 до 9 мышей.
Фаза 6: Анализ последствий эксперимента
Мы подбираем погибших мышей, выписываем их номера и составляем двоичное число в котором установлены в один те разряды, которые соответствуют номерам погибших мышей. Переводим это двоичное число в десятичное и , таким образом , мы и получим десятичный номер той пробирки в которой и была отрава. Таким образом, мы за один час найдем номер с отравленной колбой.
Если ни одной мыши не погибло, значит отрава была в нулевой колбе. Её как раз никому не наливали.
Фаза 7: Как при этом погубить как можно меньше мышей?
Более сложная вариация этой классической задачи состоит в том, что накладывает дополнительное ограничение, что надо по возможности умертвить как можно меньше мышей. При этом обычно уменьшают количество исходных пробирок до 100. Решается это достаточно просто. При нумерации пробирок надо отдавать предпочтение тем номерам в которых меньше всего установленных в 1 битов. Вот так. Можно сказать, что появляются новые виртуальные номера (оптимальные номера) для колб.
Как можно заметить, оптимальный номер колбы вовсе не равен её двоичному представлению. Это какая-то другая кодировка. Назовем её кодировка по возрастанию количества установленных в единицу бит. При малом количестве колб, скажем до 200 лучше задействовать именно её.

При умной кодировке для поиска отравы среди 100 колб в жертву придется принести максимум три мыши из 10. А при наивной кодировке погибнет аж 6 мышей! Вот такие пирожки с капустой, понимаете?
А в остальном всё то же самое.
N мышей могут проверить 2^N колб за 1 раунд.
Количество мышей |
Количество пробирок |
1 |
1 |
2 |
4 |
4 |
16 |
8 |
256 |
10 |
1024 |
Мы могли бы и в 1023-х пробирках найти отраву за 1 час. Число 1000 было выбрано только лишь, чтобы дезориентировать читателя.
Итоги
Вот такие вот препоны чинят соискателям при трудоустройстве. Лично мне хотелось, чтобы в работе было по более практических задач, а не придуманной работы.
Тем не менее, теперь и Вы умеете решать классическую задачу про мышей и отраву и можете объяснить решение другим.
Как видите двоичная кодировка далеко не всегда самая оптимальная. Вспомните хотя бы коды Грея для кодировки диска абсолютных энкодеров. Есть ещё код Джонсона и прочие двоичные коды.
Если Вам при устройстве на работу задают эту задачу, то сначала сделайте вид, что Вы никогда не слышали про эту задачу, задумайтесь на 20...40 секунд и только потом начните воспроизводить это решение.
Ссылки
№ |
Название |
URL |
1 |
Загадка о тысяче пробирок |
|
2 |
Аналитика по задаче |
https://docs.google.com/spreadsheets/d/1DN4wJo3kCX1mzBhXZqNcawi1d3Xey24ArS25zyAEaD4/edit?gid=0#gid=0 |
3 |
Задача о двоичной мыши и тысяче пробирок |
https://vk.com/@thecode.media-zadacha-o-dvoichnoi-myshi-i-tysyache-probirok |
4 |
Задача о двоичной мыши и тысяче пробирок |
|
5 |
Задача о двоичной мыши и тысяче пробирок |
|
7 |
Задача про две ёмкости для жидкости |
|
8 |
Сканирование шины RS485 (битовая логика в действии) |
|
6 |
Ликбез по формулам google spreadsheets |
https://support.google.com/docs/answer/3098245?sjid=8977904692612096953-EU |
Комментарии (74)
nivorbud
18.05.2025 00:17--Как при помощи 10 мышей найти колбу с отравой? Спойлер: надо применить бинарные вычисления
Если речь о собеседовании, то правильно будет отказаться от выполнения такой задачи до выяснения недостающих деталей. В таком виде решить задачу невозможно, разработчику придется додумывать детали ТЗ, и вероятно получится не то, что нужно заказчику.
Сына год назад готовил к ОГЭ, сейчас готовлю к ЕГЭ. Насмотрелся на кучу задачек, где невозможно понять условие, пока не влезешь в голову составителя задачки.
Например:
1) Что произойдет с силой постоянного тока, протекающего через обмотку электромагнита, если изменить полярность источника питания? У меня в голове сразу возникают переходные процессы, индукция, резкое кратковременное возрастание сопротивления и т.д. А подразумеваемый автором ответ: изменится направление тока. Правильная формулировка ТЗ должна указывать - через какое время рассматривать изменение.
2) Как быстрее охладить кастрюлю с компотом, закрытой крышкой: положить лед на крышку или под дно кастрюли? В реальной жизни между крышкой и компотом будет прослойка воздуха (пусть и с паром), а это теплоизолятор, поэтому возникает соображение, что класть лед на крышку - сомнительная затея. Однако, подразумеваемый составителем задачи ответ: клать лед надо подо дно (из-за эффекта конвекции). По-видимому, автор подразумевал, что кастрюля наполнена компотом полностью до краев, без воздушного зазора, чего автор в условии не указал почему-то. А ученику что делать?
ЗЫ
И в задаче про мышей также. Ответ "бинарные вычисления" подразумевает произвольное додумывание - смешивание содержимого колб, что многократно уменьшает концентрацию вещества и тем самым изменяет условие задачи. Так что корректным ответом на собедесовании вероятно будет отказ от решения такой задачи с объяснением причин (неполноты условия).
blik13
18.05.2025 00:17Так что именно нужно уточнять в условии этой задачи?
Если кто-то решит задачу иначе это не значит что ответ не будет принят.
nivorbud
18.05.2025 00:17Так что именно нужно уточнять в условии этой задачи?
Нужно уточнение, что можно смешивать и получившейся концентрации будет достаточно для теста, либо дать иную информацию по концентрации.
Если кто-то решит задачу иначе это не значит что ответ не будет принят.
Без домыслов эту задачу невозможно решить. Поэтому надо просто уточнить ТЗ. Может быть, это тест на то, как испытуемый отнесется к криво составленному ТЗ? Такое ведь тоже может быть.
blik13
18.05.2025 00:17Достаточно будет этого:
Если мышь попробует отраву, то она погибнет через 1 час.
Вам предварительно не нужно ничего смешивать.
nivorbud
18.05.2025 00:17Достаточно будет этого
В реальной жизни недостаточно. Что означает термин "попробует"? Выпьет всю пробирку? Десятую долю? Любую долю? Без четкой расшифровки этого термина невозможно решить эту задачу.
AGalilov
Жаль мышек.
yadowit
Тогда надо взять 1000 мышей и напоить каждую из своей колбы. Результат: Найдено за минимальное время, с минимальными потерями мышей.
Politura
Из 1000 мышей за час кто-нибудь может умереть просто так, а не потому-что там что-то выпил :)
bogolt
999 достаточно
PPRT_E
О, вы корпоративный архитектор?
alexandr93
На литкоде это бедные свиньи)) https://leetcode.com/problems/poor-pigs/
wataru
Там сильно более сложная версия задачи. Надо найти минимальное количество подопытных, чтобы опеределить отраву за K раундов.