Этот вопрос вдохновлен обложкой книги «Годель, Эшер, Бах»:
Задача состоит в том, чтобы написать функцию, которая сообщает, могут ли три заданные буквы создать трехмерную скульптуру, которую можно прочитать с трех сторон.
В этом упражнении вы можете использовать только буквы размером 5 на 5 * 5 пикселей:
Или в двоичном (от А до Я):
01110 11110 01111 11110 11111 11111 11111 10001 11111 11111 10001 10000 10001 10001 01110 11110 01110 11110 01111 11111 10001 10001 10001 10001 10001 11111
10001 10001 10000 10001 10000 10000 10000 10001 00100 00100 10010 10000 11011 11001 10001 10001 10001 10001 10000 00100 10001 10001 10001 01010 01010 00010
10001 11110 10000 10001 11100 11110 10011 11111 00100 00100 11100 10000 10101 10101 10001 10001 10001 11111 01110 00100 10001 01010 10001 00100 00100 00100
11111 10001 10000 10001 10000 10000 10001 10001 00100 10100 10010 10000 10001 10011 10001 11110 10011 10010 00001 00100 10001 01010 10101 01010 00100 01000
10001 11110 01111 11110 11111 10000 11111 10001 11111 11100 10001 11111 10001 10001 01110 10000 01111 10001 11110 00100 01110 00100 01010 10001 00100 11111
Скульптура состоит из трех букв в следующем порядке:
- буква одна сверху,
- буква вторая слева
- буква три справа
- нижняя часть буквы один связана с верхней частью буквы два.
Пример:
Ваша функция может принимать в качестве входных данных три заглавные буквы (три символа или три строки одной буквы) и выводить логическое значение (true / false или 0/1), указывающее, может ли существовать соответствующая скульптура.
Пример:
f("B","E","G") // true (because if you "sculpt out" B on top + E on the left + G on the right, and watch the three sides of the sculpture, you'll see exactly B, E and G as they are defined)
f("B","G","E") // false (because if you "sculpt out" B on top + G on the left + E on the right, and watch the three sides of the sculpture, you won't see a complete G and a complete E. Their shapes bother each other)
NB: вы можете вернуть true, даже если скульптура содержит «летающие пиксели» (кубы или группы кубов, которые ни к чему не прикреплены).
Применяются стандартные лазейки.
Точнее, вы не можете использовать внешний ввод кроме трех букв, и вы не можете жестко закодировать 17576 возможных ответов в вашем исходном коде
Самый короткий ответ в символах на любом языке выигрывает!
Повеселись :)
Ответы:
Mathematica 423
Я добавил раздел «Как работает блокировка».
Ungolfed
(* Двоичные данные алфавита хранятся в виде одной строки
s
.vars
Импортирует их и преобразует в массив.)пример
Куб
{"B", "G", "E"}
действителен? (т.е. будут ли три буквы правильно проецироваться на стены?)иллюстрации
На рисунках ниже показано, как отображается BGE. Верхний ряд фигур принимает ортогональные перспективы, как если бы зритель располагался на бесконечном расстоянии от куба. Нижний ряд показывает, как блоки будут выглядеть с близкого расстояния. Трехмерные фигуры можно вращать вручную, чтобы точно определить, где расположены отдельные кубики.
Проблема возникает с буквой "G". Ничто не связывает засечку с остальной частью письма.
BEG, однако, должен работать нормально.
Как работает блокировка?
Пожалуйста, извините, если это кажется очевидным, но, возможно, некоторые люди захотят визуализировать, как буквы мешают друг другу, устраняя свои трехмерные пиксели.
Давайте проследим, что происходит с буквой G в рендеринге куба BGE.
Мы будем уделять особое внимание вокселю (трехмерный пиксель или единичный куб) ниже. Это пиксель, который исчезает в кубе BGE. Это пиксель, соответствующий строке 4, столбцу 5 в массиве битов и на соответствующем графике массива.
В плоскости xy пиксель соответствует серому диску в точке (5,2). Но поскольку мы собираемся работать в 3D, нам нужно рассмотреть 5 позиций в шахте от (5,1,2) до (5,5,2). Если какой-либо из этих пикселей выживет, создавая буквы B и E, мы сможем увидеть интересующий пиксель в 3D-проекции на стене.
Буквы мешают, когда пиксели удаляются из сплошного блока. Слева черная стрелка представляет вырезание пикселей, соответствующее биту внизу справа; для буквы B она имеет значение 0. Вырезание удаляет пиксель в точке (5,1,2), а также пиксели, расположенные непосредственно над и под ним. Четыре пикселя еще предстоит учесть.
Но, как показывает правая панель, буква E выделяет интересующие пиксели (5,2,2) (5,3,2), (5,4,2) и (5,5,2). (Это связано с тем, что буква E имеет биты, равные 0, в четвертом ряду, от столбца 2 до столбца 5.) В результате ни один пиксель не остается среди тех, которые были необходимы для обеспечения затенения в точке (5 , 2) на дальней стене (для буквы G). Вместо этого будет яркое пятно, соответствующее отверстию в букве G! Куб BGE не годится, потому что он неправильно отображает G.
Гольф 423 символа
Функция
h
выполняла ту же роль, что иvalidQ
в коде unGolfed. Функция рендеринга,perspective
не включена, потому что она не вносит свой вклад и не является обязательной для задачи.источник
Пролог,
440, 414Программа называется так:
Prolog
Казалось бы, хороший выбор, так как проблему легко представить в логике первого порядка. ТакжеProlog
предоставляет мощную функциональность для решения такого рода проблем.Тем не менее, так как в коде нет ничего плохого, думаю, мне следует добавить некоторые пояснения
Мягко играемая в гольф версия
Координаты, соответствующие пикселям на каждой стороне кости, могут быть легко преобразованы в трехмерную систему координат. Я использую
T
,L
иR
для верхней части (1), влево (2) и вправо (3) стороны.u
иv
используются для координат на изображениях:(u,v) -> (4-v, ?, u)
(u,v) -> (?, v, u)
(u,v) -> (u, v, ?)
Результаты для каждого активного (т.е. черного) пикселя объединяются в набор «3D-пикселей», которые можно активировать, не изменяя внешний вид объекта с этой стороны. Все точки пересечения наборов для каждой стороны - это трехмерные пиксели, которые можно активировать без добавления пикселей, что затруднит вид (т.е. если смотреть по крайней мере с одной стороны, то там будет пиксель, которого не должно быть).
Осталось только проверить для каждой стороны, есть ли на пересечении пиксель, который блокирует вид, где это необходимо.
Это приводит к предикатам в программе:
c : проверяет пиксель в изображении буквы. Строка там может выглядеть немного странно, но это только компактный способ хранения данных изображения. Это просто последовательность символов со следующими значениями (шестнадцатеричная запись):
Каждый из этих символов хранит данные для строк размером 3 пикселя в буквенном изображении (ях) (= 15 пикселей). Пиксели также переупорядочиваются так, что данные хранятся в одном месте и не разделяются на несколько строк, как данные OP.
Математическая формулировка
Входные данные
Преобразование из пикселя в одном символе в набор 3D-пикселей, которые затрудняют вид для этого пикселя
Пиксели, которые можно безопасно добавлять (не мешая обзору в неправильном месте)
Проверяет для каждой стороны, что пиксели, которые должны быть перекрыты, могут быть надежно закрыты
Комбинат чеков для каждой стороны
источник
J -
223197191 символФункция, принимающая список из трех символов в качестве аргумента.
Этот гольф в значительной степени опирается на мощную особенность J под названием ранга , которая дает нам возможность «ваять» и «наблюдать за» операциями практически бесплатно. Чтобы упростить это немного, ранг относится к размерности существительного или естественных аргументов глагола.
J имеет многомерные массивы, и очевидно, что, скажем, трехмерный массив можно интерпретировать как отдельный трехмерный массив, или как список матриц, или двумерный массив векторов, или трехмерный массив скаляров. Таким образом, каждая операция в J может иметь свое приложение, контролируемое по отношению к аргументу. Ранг 0 означает применение к скалярам, ранг 1 означает применение к векторам и так далее.
Это становится очень мощным, когда вы вводите двоичные функции (с двумя аргументами), потому что, если формы двух аргументов (после учета ранга) приемлемы, J выполнит неявный цикл:
Когда все ваши формы приемлемы и вы можете сами указать ранг, есть много способов объединить аргументы. Здесь мы покажем некоторые способы умножения 2D-матрицы и 3D-массива.
Вы заметите, что на самом деле это не вписывается в буквы в той ориентации, о которой спрашивает вопрос, а просто записывает их, однако это удобно для логики рангов. Если мы не перевернем или не повернем буквы, прежде чем применить их, это не будет работать правильно. Но для исправления подобных вещей потребовались бы драгоценные символы, поэтому вместо этого мы закодируем буквы так, что, когда J вырезает их естественным образом, некоторая тройка граней будет иметь правильную ориентацию и относительное положение. Оказывается, самое короткое решение - повернуть все буквы на четверть оборота против часовой стрелки. Учитывая, что третье измерение J представляет ось спереди назад, грубая диаграмма ниже показывает, почему эта схема работает.
Рисунок A: Три стороны куба, на которые вырезан J Рисунок B: Три стороны, буквы которых ориентированы так, как задает вопрос.
Этот выбор в кодировке сохраняет 12 символов по сравнению с предыдущим методом и делает все это более аккуратным. Фактический гольф создает куб из
"1
и"2
вырезает с некоторой причудливой логикой, из-за несвязанной оптимизации.Тогда мы должны проверить лица. Так как мы закодировать блок как 1 и 0, мы можем просто суммировать вдоль каждой оси , как мы хотим (они являются
+/"1
,+/"2
и+/
битами), приспосабливаются к булевым (0<
), а затем сравнить их все непосредственно к исходным 90 ° - превратился-буква.Схема сжатия кодирует каждую строку 5px каждой буквы как представление 32 двоичного числа. Используя ряд синтаксических сахаров и перегрузок операторов,
".'1b',"#:
это самый короткий способ превратить список символов в базовые 36 чисел. Ну, технически, база 32, но J думает, что это унарно, так кто же считает?Использование ниже. Обратите внимание, что строки являются символьными массивами в J, поэтому список из трех пунктов
'A','B','C'
можно написать'ABC'
для краткости. Кроме того, логические значения равны 1/0.источник
Питон,
687682671Позвонить с
v
:Все, что ниже, взято из моей предыдущей версии, в которой есть полезные функции рисования. Не стесняйтесь использовать его как отправную точку.
Вызов
valid
чтобы запустить его:Прямо сейчас код настроен для проверки правильности
B E G
и распечатки полученных граней:Запустив его,
B G E
мы видим, что G неверен:источник
g=[[0 for j in s]for i in s]
можно сократить доg=map(list,[[0]*5]*5)
. Кроме того, вы можете избежать отступы блоков , если они одно заявление:if c[e]:g[e[a]][e[a-2]]=1
.Python 3 + NumPy, 327C
Для этого гольф-решения нужна внешняя библиотека numpy, которая довольно популярна, поэтому я думаю, что ее можно использовать.
Строка Unicode состоит из 41 символа, а то же самое в ответе пролога @ fabian - 44.
Здесь самое интересное, что индексация массива numpy. В
a[ix]
,ix
может быть логическим массивом с той же формой, что иa
. Это то же самое, что сказатьa[i, j, k] where ix[i, j, k] == True
.Безголовая версия
Скрипт для сжатия таблицы
источник