Вызов
Учитывая цветное растровое изображение * с той же шириной и высотой, выведите изображение, преобразованное под карту кота Арнольда . (* подробности см. ниже)
Определение
Учитывая размер изображения, N
мы предполагаем, что координаты пикселя даны как числа между 0
и N-1
.
Карта кота Арнольда определяется следующим образом:
Пиксель с координатами [x,y]
перемещен в [(2*x + y) mod N, (x + y) mod N]
.
Это не что иное, как линейное преобразование на торе: желтая, фиолетовая и зеленая части возвращаются на начальный квадрат благодаря mod N
.
Эта карта (назовем ее f
) имеет следующие свойства:
Это биективно , что означает обратимость: это линейное преобразование с матрицей
[[2,1],[1,1]]
. Поскольку он имеет определитель1
и имеет только целочисленные записи, обратное также имеет только целочисленные записи и определяется как[[1,-1],[-1,2]]
, это означает, что он также является биективным по целочисленным координатам.Это элемент кручения группы биективных карт
N x N
изображений, что означает, что если вы примените его достаточно много раз, вы вернете исходное изображение:f(f(...f(x)...)) = x
количество раз, когда карта, примененная к себе, приводит к идентичности, гарантированно будет меньше или равно3*N
. Далее вы можете увидеть изображение кота после заданного числа повторяющихся приложений карты кота Арнольда и анимацию того, как выглядит повторяющееся приложение:
Детали
Ваша программа не обязательно должна иметь дело с изображениями, но 2D-массивы / матрицы, строки или аналогичные 2D-структуры также приемлемы.
Неважно, находится ли ваша
(0,0)
точка слева внизу или слева вверху. (Или в любом другом углу, если это более удобно на вашем языке.) Пожалуйста, укажите, какое соглашение вы используете в своем представлении.
Testcases
В матричной форме ( [1,2,3,4]
верхний ряд, 1
индекс (0,0)
, 2
индекс (1,0)
, 5
индекс (0,1)
)
1 2 3 4
5 6 7 8
9 10 11 12
13 14 15 16
maps to:
1 14 11 8
12 5 2 15
3 16 9 6
10 7 4 13
--------------------
1 2 3
4 5 6
7 8 9
map to:
1 8 6
9 4 2
5 3 7
Как изображение (внизу слева (0,0)
):
Ответы:
Желе , 9 байт
Попробуйте онлайн! Координаты как в ответе.
объяснение
Это обернуть-сдвинуть матрицу в одном направлении, затем в другом.
источник
MATL , 23 байта
(0,0)
Точка вверху слева, как и в примерах , приведенных в тексте вызова.Попробуйте онлайн!
объяснение
Матрица в MATL может быть проиндексирована с одним индексом вместо двух. Это называется линейным индексированием и использует основной порядок столбцов . Это иллюстрируется следующей матрицей 4 × 4, в которой значение в каждой записи совпадает с ее линейным индексом:
Существует два похожих подхода для реализации сопоставления в задаче:
Постройте индексную матрицу, которая представляет обратное отображение Арнольда на линейные индексы, и используйте ее для выбора значений из исходной матрицы. Для случая 4 × 4 индексная матрица будет
сообщая, что, например, оригинал
5
при x = 2, y = 1 переходит к x = 3, y = 2. Эта операция называется индексированием ссылок : используйте матрицу индексирования, чтобы указать, какой элемент выбрать из исходной матрицы. Это функция)
, которая принимает два входа (в конфигурации по умолчанию).Постройте индексную матрицу, которая представляет прямое отображение Арнольда на линейные индексы, и используйте ее, чтобы записать значения в исходную матрицу. Для случая 4 × 4 индексная матрица будет
сообщая, что запись x = 2, y = 1 новой матрицы будет перезаписана на запись с линейным индексом
10
, то есть x = 3, y = 2. Это называется индексацией присваивания : используйте матрицу индексации, матрицу данных и исходную матрицу и запишите данные в исходную матрицу по указанным индексам. Это функция(
, которая принимает три входа (в конфигурации по умолчанию).Метод 1 более прост, но метод 2 оказался короче.
источник
Mathematica, 44 байта
Порт фантастического алгоритма Линн . Перед последним есть невидимый 3-байтовый символ U + F3C7 в кодировке UTF-8
]
; Mathematica отображает его как верхний индексT
, и он принимает транспонирование матрицы.Mathematica, 54 байта
Безымянная функция, принимающая два аргумента: положительное целое число
#
и двумерный массив#2
измерений#
x#
и возвращающая двумерный массив аналогичной формы. Как и в данном тестовом примере, точка с координатами {0,0} находится в верхнем левом углу, а ось x - горизонтальная. Простая реализация, использующая обратное,[[1,-1],[-1,2]]
упомянутое в вопросе, с-1
первой координатой, чтобы учесть тот факт, что массивы по своей природе индексируются 1 в Mathematica. Если мы не позволили взять размерность матрицы в качестве дополнительного аргумента, то это решение будет девять байт больше (заменить первый#
-не на#2
-сa=Length@#
и все последующие#
с сa
е).источник
Python 2,
89827773 байтаВвод - это список списков
. Строка внутри exec транспонирует список списков и циклически поворачивает каждый список на индекс строки (на основе 0 - 3-я строка поворачивается 2 раза вправо).
Этот процесс делается 2 раза для ввода.
+4 байта, которые сделают преобразование N раз
источник
Haskell, 55 байтов
Пример использования:
[[1,2,3,4],[5,6,7,8],[9,10,11,12],[13,14,15,16]] # 4
->[[1,14,11,8],[12,5,2,15],[3,16,9,6],[10,7,4,13]]
.0,0
это верхний левый угол. Это использует обратное преобразование.источник
Python, 69 байт
Усовершенствование метода транспонирования и сдвига в два раза . Применяет операцию
M -> [r[-i:]+r[:-i]for i,r in enumerate(zip(*M))]
дважды, создавая и оценивая строкуЭто узко выбивает прямое преобразование (70 байт), предполагая, что изображение квадратное и его длина может быть взята в качестве входного:
источник
Макрос ImageJ, 29 байт
источник
v=getPixel((2*y-x)%w,(x-y)%h)
.2*x+y
изменился на2*y+x
f(x,y) = (2x+y, x+y)
этого обратное преобразование описываетсяf^(-1) = (x-y, 2y-x)
. (Мой другой комментарий был неверным.) Так что ваш код должен бытьv=getPixel((x-y)%w,(2*y-x)%h)
.Ява, 160
Golfed:
Ungolfed:
источник