green_fr: (Default)
[personal profile] green_fr
На новый год [livejournal.com profile] sasmok подарил мне календарь-головоломку. Нужно уложить вот эти 8 деталей вот в эту форму, чтобы в оставшихся клеточках была видна текущая дата. Справа — решение для сегодняшней даты.



Какое-то время я пытался решить для 1 января — нужно же всё делать по порядку! Потом для текущей даты — нужно же сделать хотя бы что-то! Затем просто складывал детали в надежде, что когда-нибудь они улягутся, и записывал получавшиеся даты впрок. Ну а потом вспомнил про MatLab.

1. Первая версия, тупой брутфорс
Написал класс Piece с матрицей, описывающей каждую деталь. Пара пространственных методов — flip и rotate, преобразующих матрицу. Служебный класс-структура Placement с номером детали, координатами на поле и информацией о том, как именно повёрнута деталь. Класс Plateau с матрицей игрового поля. Метод поиска всех возможных положений детали на поле (Placement). Методы put и remove, которые отражают на матрице поля тот факт, что мы положили или убрали деталь.

И рекурсивный метод решения задачи:
* Метод принимает список деталей, которые нужно уложить
* Если список пустой — значит мы уже уложили всё необходимое => сохраняем в файле найденное решение
* Иначе берём первую деталь из списка и ищем все возможные положения её на поле
* Пробегаем по полученному списку положений
** Кладём деталь на поле
** Вызываем этот же метод со списком без первой детали — её мы только что уложили
** (мы вернёмся сюда, когда обработаем все возможные последствия уложенной детали) Убираем деталь с поля
** Переходим к следующему возможному положению

Отличная программа. Гарантированно решает всё. Запустил, проверил первое найденное решение, проверил второе найденное решение. Поставил считать. Прикинул, сколько времени понадобится для полного прохода — порядка 10 лет. Надо что-то делать.

2. Косметические улучшения
Прекращаю вызывать flip и remove в этих бесконечных циклах. Для каждой детали можно с самого начала просчитать все её возможные положения. Более того, не у всех деталей все 8 положений отличаются друг от друга — есть и симметричные детали. Сразу же выкидываю повторяющиеся картинки. На глазок прикидываю ускорение — задача должна решиться примерно за пол года.

Одновременно написал скрипт, который пробегает по уже найденным решениям и идентифицирует их. Скрипт смотрит, какие именно клеточки остались свободными, и если они складываются в дату — помечает эту дату как «решённую».

3. Нужно решать чётко поставленную задачу

Только что написанный скрипт чётко показывает, что не все найденные варианты меня интересуют. Некоторые не соответствуют никакой дате (например, остались видимыми клеточки 1, 8 и 19). А некоторые дают альтернативное решение для уже найденной даты. Это наводит меня на мысль: а чем, собственно, я тут занимаюсь? Я решаю задачу «найти все возможные варианты укладки 8 деталей в указанный шаблон». А какая задача передо мной стояла? Совсем другая — «для каждой даты найти хотя бы одну укладку». Это же существенно более простая задача!

Пишу цикл по всем дням года (для простоты полагаю, что у нас во всех месяцах есть 31 день). Сразу помечаю эти клеточки как занятые — количество доступных положений резко падает!

4. Прозрачные матрицы

Одновременно в голову приходит идея для упрощения поиска всех доступных положений детали на поле. Моё первое «интуитивное» решение — перебирать все варианты для верхней левой точки каждой детали (точнее, верхней левой точки описывающей её матрицы), накладывать матрицу поля на матрицу детали и смотреть, есть ли пересечения — стандартная операция «и». Если есть — деталь положить нельзя. Если нет — запомнили, переходим к следующий координатам / варианту поворота детали. Долго, нудно, качественно.

Но есть вариант и без перебора, который сразу даёт все возможные положения. Представим для начала, что у нас есть некоторое положение деталей на поле. Сделаем «прозрачку» — на прозрачной плёнке нарисуем поле и эти детали. Оставшиеся прозрачными клеточки показывают нам, куда можно положить деталь 1×1. Пока что ничего сверхъестественного.



Возьмём теперь две одинаковые прозрачки (на картинке я их сделал разыми цветами). Наложим их друг на друга со сдвигом на 1 клеточку по горизонтали. Что теперь символизируют оставшиеся прозрачными клеточки? Те места, куда можно положить деталь, состоящую из двух расположенных горизонтально клеточек!



На всякий случай ещё одна картинка для детали из 3 клеточек «уголком». Легко проверить, что на изначальном поле этот уголок можно уложить именно указанными 16 способами.



Обобщение для более сложных деталей тривиальное: делаем столько копий поля, сколько клеточек у детали, располагаем их со сдвигами, соответствующими клеточкам детали, записываем все просветы — всё та же операция «и». Только она даёт нам не проверку одного положения, а сразу список всех возможных положений.

Всё, с этим улучшением задача поиска укладки для одного дня решается за ~1 минуту. Наверняка можно и ещё улучшить — а можно запустить на ночь, и утром у меня будут все решения :-)


Сделал и завис. Сказать Анюте, что вместо того, чтобы получать тактильное удовольствие (деревянный пазл, детали из бамбука!) каждый день — я взял всё удовольствие за один раз, но в виртуальном мире? Это может оказаться обидным. Ещё пару дней отсылал ей решения (на самом деле, она подсмотрела идею подарка на работе, и у них там образовался чатик, где все хвастались, кто решил сегодняшнюю задачу), а потом она мне возмущённо говорит: представляешь? Jean-Hervé вместо того, чтобы самому решать — написал какую-то приблуду на Excel! — Ты не поверишь, говорю...

Вчера Жан-Эрве приходил в гости, сравнивали наши методы. Ну, помимо того, что не надо на Excel ничего серьёзного считать, у меня метод, наверное, эффективнее. Но и у него интересно. Он сделал сначала для каждой детали список всех возможных положений на доске. Потом скрестил их: проверил, какие положения первой детали совместимы (не пересекаются) с какими положениями второй детали — и так далее, для всех возможных пар. Потом сделал виртуальную деталь «1+2» — у её положения определяются совместимыми положениями из предыдущего этапа. А следующий этап — построение детали «1+2+3» — существенно проще. Потому что совместимость определённого положения «1+2» с положением «3» определяется через совместимость «1» и «3» умноженную на совместимость «2» и «3». То есть всё делается практически без кода, одними формулами Excel. Даже поворот на 90° он делал через комплексные числа, умножением на мнимую единицу. Проблема лишь в объёме данных — он вынужден хранить всё, и в какой-то момент файл вырастал до 2GB и падал. Ну и во времени расчётов — по его прикидкам машина сама решает одну задачу примерно за один день. Поэтому он работал в режиме «киборга», проверяя какие-то варианты ручками.

Date: 2022-02-01 11:45 am (UTC)
From: [identity profile] r00kie.livejournal.com
немного не понял, на последнем шаге с прозрачными матрицами, вы все еще решаете общую задачу? Ведь конкретная задача дня — она не для плато в виде квадрата без клетки, а для плато в виде квадрата без трех секций (включая текущий день и месяц) — и эти секции должны оставаться закрашенными для каждой такой матрицы. Это еще должно уменьшить число возможных положений.
Французу респект (наверное), мне бы в голову не пришло использовать Эксель для такой задачи. Могу только сказать, что в Office 64-bit нет ограничений на размер памяти для экселевского файла, так что 2Гб — не предел. Возможно, он сидит на 32-битном, тогда пусть попробует на другой машине.

Date: 2022-02-01 12:29 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Да, точно, я ещё думал закрасить клеточки для "1 февраля", но оставил это на последний день (пост не за один присест написался), в итоге забыл :-)

А Excel падал не столько из-за размера 32 или 64 бит (хотя, я сам на 32 бита, и про 64 бита на работе страшные ужасы рассказывали), сколько из-за миллионов друг на друга завязанных формул. То есть ну вот совершенно не по назначению им пользовался товарищ!

Date: 2022-02-01 01:26 pm (UTC)
From: [identity profile] anjey.livejournal.com
У Жана-Эрве фамилия "рыба"?

Date: 2022-02-01 01:41 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Пилять. А ты откуда его знаешь?

Date: 2022-02-01 01:42 pm (UTC)
From: [identity profile] anjey.livejournal.com
Гугл: имя + название компании.

Date: 2022-02-01 02:09 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Я уж испугался, что это как с Настей Кокоревой — мир настолько тесен :-)
И что характерно, из этой компании он как раз-то уже ушёл. Но гугл помнит всё.

Date: 2022-02-01 02:20 pm (UTC)
From: [identity profile] anjey.livejournal.com
Просто у меня какая-то профдеформация. Бывают какие-то смешные ситуации связанные с больными\их именами-жизненными ситуациями, но невозможно рассказать, потому что по ключевой информации можно как-то даже отдаленно идентифицировать человека, что нельзя делать.
Поэтому сразу полез проверять твою рыбу.

Date: 2022-02-01 05:38 pm (UTC)
From: [identity profile] monetochka.livejournal.com
Интересно, а как гарантируется, что для всех дней вообще будет решение? Тут такой особой формы детальки, что кажется, это было как-то специально посчитано.

В инторнетах нашла вот такие календари, но они сильно попроще выглядят:
https://www.dragonfjord.com/product/a-puzzle-a-day
https://www.amazon.com/gp/aw/d/B09PFPYYVM/

И кажется это очень подойдёт для мобильной игры типа, Wordle — по загадке на каждый день

Date: 2022-02-01 06:01 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Хороший вопрос. Я не знаю, как авторы гарантировали, что есть решение. Я просто проверил — оно есть :-)
Мы ещё потом разговаривали о других возможных вопросах. Например — есть ли даты, для которых есть только одно решение? Или наоборот, для каких дат разных решений больше всего?

А "по загадке каждый день" — так так оно изначально и задумывалось. А дальше — кто как предпочитает относиться к задачкам. Кто-то каждый день решает независимо от других. А кто-то вот пытается найти общее решение, пусть и на компьютере :-)

Date: 2022-02-01 07:08 pm (UTC)
From: [identity profile] aneta.livejournal.com
А почему это отменяет тактильное удовольствие? Никто ж не мешает взять готовое решение и деревяшечки выложить...

Date: 2022-02-02 07:44 am (UTC)
From: [identity profile] green-fr.livejournal.com
Если оно есть — не отменяет, конечно. Просто я как-то вот спокойно отношусь конкретно к этому тактильному.

Date: 2022-02-01 08:15 pm (UTC)
From: [identity profile] bogdanovandrey.livejournal.com
У меня "продвинутая" версия этого календаря. Там ещё и дни недели есть. Так что всего получается не 366, а 366*7 различных задач. Неделю считаться будет?

Date: 2022-02-02 07:47 am (UTC)
From: [identity profile] green-fr.livejournal.com
Пришли схему, проверим?
Потому что там же главное не в увеличении всемеро количества задач, а в том, что для каждой задачи остаётся на 6 клеточек больше (неиспользованные дни недели). Разве только если взамен у тебя месяца не двумя, а одной клеточкой — тогда наоборот, твоя версия проще.

Date: 2022-02-07 02:26 pm (UTC)
From: [identity profile] bogdanovandrey.livejournal.com
С телефона картинку загрузить не удалось. Добрался до компьютера

Про 7 раз дольше я имел ввиду, что в в твоем варианте есть 366 (ну или 12*31=372) разных целевых картинок. А в моём для каждой даты ещё есть 7 разных дней недели и всего надо решить не 366 задач а в семь раз больше.
Понятно, что для каждого конкретного дня (сегодня понедельник 7 февраля, например) сложность примерно та же (завист, конечно, от числа деталей).

Date: 2022-02-07 04:25 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Не, эта гораздо проще, мне кажется. Как минимум для компьютера проще. Потому что для каждой задачи остаётся 47 клеточек, тогда как у меня 52. Это явно больше чем всемеро дольше перебирать. Плюс, у меня детали сложнее — у тебя скорее тетрис-пентикс, тогда как у меня детали по 6-7 клеточек. То есть, твою головоломку сложнее придумать (мне кажется), а мою — перебирать. Какую сложнее решать ручками — это уже к тебе вопрос :-)

Date: 2022-02-07 08:27 pm (UTC)
From: [identity profile] bogdanovandrey.livejournal.com
Мою решать руками проще, так как элементы маленькие и свободы больше. А вот для компьютера сложность может зависеть от алгоритма. Для больших деталей меньше возможных вариантов расположения, да и самих деталей меньше. То есть перебор с большими деталями должен быть короче.
В предельном случае если рассмотреть задачу с двумя большими деталями, то там вариантов для перебора всего десяток.

Date: 2022-02-07 09:13 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Да ты прав. С другой стороны, в твоих деталях симметрии больше :-) В сумме у меня 50 разных деталей с поворотами, у тебя 54. Точно, то на то выходит.

Date: 2022-02-09 10:21 am (UTC)
From: [identity profile] sasmok.livejournal.com
опубликуй фотку, пожалуйста.

Date: 2022-02-09 10:35 am (UTC)
From: [identity profile] green-fr.livejournal.com
Так вот же (https://green-fr.livejournal.com/930989.html?thread=11792557#t11792557), уже.

Date: 2022-02-01 08:45 pm (UTC)
From: [identity profile] kruzzik.livejournal.com
Класс )

Date: 2022-02-02 07:48 am (UTC)
From: [identity profile] green-fr.livejournal.com
Ты понимаешь, да, о чём я думал после каждой задачки, которые ты описываешь? Первая мысль — "&#$!!!", а потому — интересно было бы написать программу, которая решала бы такие задачки вместо тебя на экзамене.

off: ты долго ещё томить будешь? прошёл экзамен-то? :-)

Date: 2022-02-02 08:35 am (UTC)
From: [identity profile] kruzzik.livejournal.com
Прекрасно тебя понимаю, не знаю, видел ли ты, как я играл в симулятор для авиадиспетчеров ))
https://kruzzik.livejournal.com/474753.html

А по поводу экзаменов — там еще не все круги ада закончились. Следите за рекламой.

Date: 2022-02-02 09:25 am (UTC)
From: [identity profile] green-fr.livejournal.com
Видел, но ещё раз с удовольствием перечитал. У тебя всё-таки прекрасное чувство юмора :-)))

Date: 2022-02-02 10:02 am (UTC)
From: [identity profile] och.livejournal.com
Вы оба молодцы!! (с) :)
И чсх, ни один из двух не работает программистом, а выделывают такое, что вовсю развивается комплекс профнепригодности.

Date: 2022-02-02 12:59 pm (UTC)
From: [identity profile] green-fr.livejournal.com
Это потому что у нас нет отвращения "станки, станки"? :-)))

Profile

green_fr: (Default)
green_fr

July 2025

S M T W T F S
   1 2 345
6789101112
13141516171819
20212223242526
2728293031  

Most Popular Tags

Style Credit

Expand Cut Tags

No cut tags
Page generated Jul. 3rd, 2025 04:33 pm
Powered by Dreamwidth Studios