Что пишут в блогах

Подписаться

Онлайн-тренинги

Конференции

Что пишут в блогах (EN)

Разделы портала

Про инструменты

Лучшие вакансии

.
Решение черного ящика номер 31 при помощи анализа данных
07.11.2019 00:00

Автор: Джоэп Шууркс (Joep Schuurkes)
Оригинал статьи
Перевод: Ольга Алифанова

Джеймс Линдси создал ряд потрясающих загадок черного ящика. Это крошечные приложения, которые подталкивают вас разобраться, что же они делают (поддержать Джеймса в создании этих загадок можно на его Patreon-страничке). У двух из этих загадок –29 and 31 – теперь есть не только интерфейс, но и API.

Это навело меня на мысль. Если исследовать загадки через графический интерфейс, то начинаешь с ввода – пробуешь различные виды ввода в надежде выявить логику вывода. Затем эта логика поощряет дальнейшее исследование.

Однако при наличии API, и из-за природы загадки 31, очень легко получить результаты для всех возможных комбинаций исходных данных. Это означает, что исследование можно начинать с результатов, а не с ввода.

Три важных замечания, прежде чем я расскажу вам, как и что я делал.

Во-первых, эта статья- спойлер решения для загадки 31, поэтому отличной идеей будет пойти и решить ее самостоятельно. Как минимум поиграйте с ней хоть чуть-чуть, чтобы понимать, что там на входе и что на выходе.

Во-вторых, несколько месяцев назад я уже решил эту загадку через графический интерфейс. Поэтому это скорее ответ на вопрос, "Могу ли я найти решение и таким способом?", а не "Могу ли я найти решение?".

И, наконец, код и таблицы, которые я создал (перелинкованные в тексте, а также доступные на GitHub), не очень-то чисты. Я думал о том, чтобы их почистить, но не сделал этого по двум причинам – во-первых, я ленив, а во-вторых, так они дают более честную картину того, что я делал.

Получение всех комбинаций для загадки 31

API загадки 31 описан здесь. Вы можете пользоваться им через браузер, добавляя параметры запроса для всех кнопок:

http://blackboxpuzzles.workroomprds.com:8002/puzzle31?buttonA1=up&buttonA2=up&buttonA3=up&buttonB1=up&buttonB2=up&buttonB3=up&buttonC1=up&buttonC2=up&buttonC3=up

Такой запрос вернет ответ {"lamp1":"on","lamp2":"off","lamp3":"off","lamp4":"off"}.

С этим разобрались. Следующий вопрос – как проверить все возможные варианты ввода через АПИ-запросы. Оказывается, в библиотеке Python – itertools – есть функция product, которая делает именно это:

product(('up', 'down'), repeat=9).

Я раньше уже посылал АПИ-запросы через Python (да здравствует библиотека запросов!). Записью данных в csv я тоже занимался. Поэтому я написал вот такой скрипт на Python, и получил вот такой csv-файл.

Ретроспективно – я бы кое-что изменил в этом скрипте. Значения “down”/”up” и “on”/”off” усложняют анализ данных. Позднее я создал другой csv-файл, заменив down/up и on/off на 0/1.

Анализ данных при помощи таблицы

Прежде чем приступить к анализу с Python (см. следующий раздел), я воспользовался для этого таблицей. Я раньше анализировал данные и манипулировал ими при помощи таблиц, и поэтому решил, что при помощи фильтров, формул, условного форматирования и, возможно, сводной таблицы, мне удастся решить загадку.

Таблицу можно найти здесь. В норме я пользуюсь Excel, но мне было любопытно, смогу ли я сделать то же самое при помощи LibreOffice Calc. Оказалось, что смогу.

Решение для лампы 1

Я начал с того, что проверил, какое количество комбинаций включит или выключит каждую лампу. Для лампы 1 таких комбинаций всего 2 – для прочих 510 комбинаций она будет выключена. Лампа 2 включается при 337 комбинациях и выключена при 175. У 3 и 4 ламп соотношение одинаковое – 169 для включения и 343 для выключения.

Эти результаты предполагают, что несмотря на четыре лампы, мы наблюдаем всего три типа поведения (ну или просто три поведения). Поэтому я проверил, а не делают ли лампы 3 и 4 одно и то же, но оказалось, что это не так. В 91 случае обе они включены, для 2*78 случаев одна включена и одна выключена, а для 265 выключены обе.

Вернемся к лампе 1. Так как всего две комбинации включают эту лампу, рассмотреть их и разобраться, как это работает, должно быть несложно.


(скриншот сделан после того, как я добавил условное форматирование для решений ламп 3 и 4).

Эврика: лампа 1 включается, когда все кнопки или наверху, или внизу. Первая лампа решена.

Решение для ламп 3 и 4

У ламп 2, 3 и 4 множество комбинаций, включающих и выключающих их. Я добавил колонку в таблице, которая подсчитывала количество кнопок в положении "нажаты" для каждой комбинации. Она показала мне, что включение лампы 2 требует как минимум двух "включенных" кнопок ". Включение 3 или 4 лампы требовало как минимум трех "нажатых" кнопок (лампы 3 и 4 все же сильно похожи).

Еще я добавил условное форматирование, похожее на интерфейс загадки. Нажатые кнопки загораются синим, а включенные лампы – красным. Так мне проще отслеживать закономерности, изучая данные.

Я решил сначала разобраться с лампами 3 и 4. Изучение комбинаций ввода с минимальным количеством нажатых кнопок (три), включающих лампы, показывает явную закономерность:


Третья лампа: кнопки с одинаковым номером.


Четвертая лампа: кнопки с одинаковой буквой.

Третья лампа включается, если нажаты три кнопки с одинаковым номером. Четвертая лампа включается, если нажаты три кнопки с одинаковой буквой.

Конечно, остается вопрос, а все ли мы знаем про лампы 3 и 4. Я провел быструю визуальную проверку для лампы 4 и комбинаций, в которых нажато больше трех кнопок. Это была формальность, так как я уже решал эту загадку через интерфейс и знал, что мое решение верно.

Однако мне стоило добавить в таблицу формулу, высчитывающую состояние ламп 1, 3 и 4 на