В этом вызове вы будете считать «существ» в игре-плитке Palago.
Существо - это любая замкнутая форма, которая может быть сформирована из плиток Palago соответствующего цвета в шестиугольной сетке.
Игра Palago состоит из таких плиток:
Эти плитки могут вращаться на , или вообще не вращаться и размещаться в любом месте на шестиугольной сетке. Например, вот (красное) существо, которое требует 12 плиток.
Вызов
Цель этой задачи - написать программу, которая принимает целое число n
в качестве входных данных и вычисляет количество существ (до вращения и отражения), которым требуются n
плитки. Программа должна быть в состоянии обрабатывать до n=10
на TIO . Это код-гольф , поэтому побеждает меньше байтов.
Пример данных
Значения должны соответствовать данным, найденным в разделе «Подсчет и оценка существ» на веб-сайте создателя . а именно
n | output
---+-------
1 | 0
2 | 0
3 | 1
4 | 0
5 | 1
6 | 1
7 | 2
8 | 2
9 | 9
10 | 13
11 | 37
12 | 81
источник
n=10
TIO». - если это требование скорости выполнения, пожалуйста, используйте code-challenge вместо code-golf , последнее относится к задаче оптимизации чисто байтов.Ответы:
JavaScript (Node.js) ,
480417 байт-63 байта благодаря @Arnauld. Вау.
Попробуйте онлайн!
Во-первых, респект Арно, чей ответ дал мне вдохновение копать глубже. Я изо всех сил старался быть оригинальным с моими алгоритмами, хотя я намеренно изменил часть своего кода, чтобы использовать те же переменные, что и Арно, чтобы было проще сравнивать код.
Поиск пустых гексов
Поиск существ - это:
Поиск пустых гексов открыл интересную симметрию. Арно обнаружил, что одно из шести направлений можно игнорировать, но на самом деле три из шести можно игнорировать!
Вот оригинальное направление Арнаулда и ключ тайла:
Представьте, что мы начинаем с плитки типа 1 с синей точки. Кажется, что мы должны вычеркнуть в d = 0 и d = 5. Однако, какой бы тайл не был размещен в d = 0, он обязательно будет иметь выход в d = 4, который посетит тот же гекс, что и выход из тайла A в d = 5. Это открытие Арно, и именно это заставило меня задуматься.
Заметить, что:
Каждая плитка, у которой есть выход в d = 4, имеет выход в d = 3
Каждая плитка, которую можно ввести с d = 0, имеет выход в d = 4
Это означает, что нам нужно учитывать только направления 0,2,4. Любые выходы в направлениях 1,3,5 могут быть проигнорированы, потому что гексы, достижимые в направлениях 1,3,5, могут быть достигнуты из соседнего гекса, используя направления 0,2 или 4.
Как это круто!?
Перемаркированные направления
Таким образом, я перемаркирую направления и тайлы вот так (отредактированное изображение Арно):
Теперь у нас есть следующие отношения между плитками, входами и выходами:
Итак, выходы: d + t == 2? (4-т)% 3: 2-т и 2 * т% 3
Гексагональные вращения и отражения
Для поворотов и отражений я решил использовать шестиугольные осевые координаты x, y вместо координат куба x, y, z.
В этой системе вращение и отражение были проще, чем я ожидал:
Чтобы получить все комбинации, которые я выполнил: гнить, гнить, гнить, отражать, гнить, гнить
Код (оригинальный 480 байт)
Код (Арно, 417 байт)
Арно любезно предоставил 63-байтовое сохранение, в котором использовались трюки, на которые у меня ушло довольно много времени, чтобы обернуть голову. Поскольку в нем много интересных правок, я решил поместить его код ниже (я добавил свои комментарии), чтобы его можно было противопоставить моей версии.
источник
JavaScript (Node.js) ,
578 ... 433431 байтКак?
Направления и плитки
Мы используем следующие коды для компаса с 6 направлениями и плиток:
Мы предполагаем, что существо синее.
связи
Нам нужна таблица, чтобы знать, какие части существа должны быть связаны с другими плитками, когда мы входим в данную плитку в заданном направлении:
Пример:
После выравнивания это дает:
Координаты
Кредиты: www.redblobgames.com
Это облегчит обработку поворотов и отражений на последнем шаге алгоритма.
Кодировка плитки
Плитки хранятся в списке без определенного порядка. Это означает, что нам не нужно беспокоиться о некотором динамическом распределении 2D, и мы можем легко перебирать существующие плитки. Недостатком является то, что с учетом конкретных координат нам нужна
find()
соответствующая плитка в списке.Алгоритм
Следовательно, этот фрагмент закодирован как
[0,0,0,1,1]
.На каждой итерации мы ищем:
Плитки с отсутствующими соединениями: в этом случае мы последовательно пытаемся завершить соединение с каждым типом плиток.
Плитки, которые уже подключены, но для которых необходимо добавить новые подключения, поскольку они были достигнуты в другом направлении: в этом случае мы обновляем маску направления (с помощью побитового ИЛИ) и запускаем новую итерацию.
Если все соединения действительны, и мы достигли запрошенного числа плиток, нам все еще нужно проверить, является ли это новое существо или просто измененной версией существующего:
Мы применяем следующие преобразования:
Мы сортируем плитки по их координатам и типам. (Этот вид обрабатывается в лексикографическом порядке, что нормально.)
Наконец, мы приводим полученный список к ключевой строке, которую можно сравнить с другими ключами.
Мы прекращаем работу, как только сопоставляется известный ключ, или сохраняем новый ключ и увеличиваем конечный результат, если ни одно из преобразований не приводит к известному ключу.
комментарии
источник