Desafio
Dada uma imagem raster colorida * com a mesma largura e altura, produza a imagem transformada no mapa de gatos de Arnold . (* detalhes veja abaixo)
Definição
Dado o tamanho da imagem N
, assumimos que as coordenadas de um pixel são dadas como números entre 0
e N-1
.
O mapa de gatos de Arnold é então definido da seguinte forma:
Um pixel nas coordenadas [x,y]
é movido para [(2*x + y) mod N, (x + y) mod N]
.
Isso não passa de uma transformação linear no toro: a parte amarela, violeta e verde é mapeada de volta para o quadrado inicial devido ao mod N
.
Este mapa (vamos chamá-lo f
) possui as seguintes propriedades:
É bijetivo , isso significa reversível: é uma transformação linear com a matriz
[[2,1],[1,1]]
. Como tem determinante1
ee possui apenas entradas inteiras, o inverso também possui apenas entradas inteiras e é dado por[[1,-1],[-1,2]]
, isso significa que também é bijetivo nas coordenadas inteiras.É um elemento de torção do grupo de mapas de
N x N
imagens bijetivos , ou seja, se você o aplicar o suficiente, você receberá a imagem original de volta:f(f(...f(x)...)) = x
A quantidade de vezes que o mapa aplicado a si próprio resulta na identidade é garantida como menor ou igual a3*N
. A seguir, é possível ver a imagem de um gato após um determinado número de aplicativos iterados do mapa de gatos de Arnold e uma animação de como é um aplicativo repetido:
Detalhes
Seu programa não precisa necessariamente lidar com imagens, mas matrizes / matrizes 2D, strings ou estruturas 2D similares também são aceitáveis.
Não importa se o seu
(0,0)
ponto está no canto inferior esquerdo ou no canto superior esquerdo. (Ou em qualquer outro canto, se isso for mais conveniente no seu idioma.) Especifique qual convenção você usa ao enviar.
Casos de teste
Em forma de matriz ( [1,2,3,4]
é a linha superior, 1
tem índice (0,0)
, 2
tem índice (1,0)
, 5
tem índice (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
Como imagem (canto inferior esquerdo (0,0)
):
Respostas:
Geléia , 9 bytes
Experimente online! As coordenadas são como na resposta.
Explicação
Isso envolve a matriz em uma direção e depois na outra.
fonte
MATL , 23 bytes
O
(0,0)
ponto está no canto superior esquerdo, como nos exemplos no texto do desafio.Experimente online!
Explicação
Uma matriz em MATL pode ser indexada com um único índice em vez de dois. Isso é chamado de indexação linear e usa a ordem principal da coluna . Isso é ilustrado pela seguinte matriz 4 × 4, na qual o valor em cada entrada coincide com seu índice linear:
Existem duas abordagens semelhantes para implementar o mapeamento no desafio:
Crie uma matriz de indexação que represente o mapeamento inverso de Arnold em índices lineares e use-a para selecionar os valores da matriz original. Para o caso 4 × 4, a matriz de indexação seria
dizendo que, por exemplo, o original
5
em x = 2, y = 1 vai para x = 3, y = 2. Essa operação é chamada de indexação de referência : use a matriz de indexação para dizer qual elemento escolher da matriz original. Este é o functon)
, que recebe duas entradas (em sua configuração padrão).Crie uma matriz de indexação que represente o mapeamento direto de Arnold em índices lineares e use-a para gravar os valores na matriz original. Para o caso 4 × 4, a matriz de indexação seria
informando que a entrada x = 2, y = 1 da nova matriz será substituída na entrada com índice linear
10
, ou seja, x = 3, y = 2. Isso é chamado de indexação de atribuição : use a matriz de indexação, uma matriz de dados e a matriz original e escreva os dados na matriz original nos índices especificados. Essa é a função(
, que recebe três entradas (em sua configuração padrão).O método 1 é mais direto, mas o método 2 acabou sendo mais curto.
fonte
Mathematica, 44 bytes
Uma porta do fantástico algoritmo de Lynn . Há um caractere invisível de 3 bytes, U + F3C7 na codificação UTF-8, antes da última
]
; O Mathematica o processa como um sobrescritoT
e leva a transposição de uma matriz.Mathematica, 54 bytes
Função sem nome, recebendo dois argumentos, um número inteiro positivo
#
e uma matriz 2D#2
de dimensões#
xe#
retornando uma matriz 2D de forma semelhante. Como no caso de teste fornecido, o ponto com coordenadas {0,0} está no canto superior esquerdo e o eixo x é horizontal. Implementação direta usando o inverso[[1,-1],[-1,2]]
mencionado na pergunta, com um-1
na primeira coordenada para explicar o fato de que as matrizes são inerentemente indexadas 1 no Mathematica. Se não pudermos considerar a dimensão da matriz como um argumento adicional, essa solução se tornará nove bytes mais longa (substitua o primeiro#
- não o#2
- coma=Length@#
e todos os#
s subsequentes pora
s).fonte
Python 2,
89827773 bytesEntrada é uma lista de listas
A sequência dentro do exec transpõe a lista de listas e gira ciclicamente cada lista pelo índice de linhas (com base em 0 - a terceira linha é girada 2 vezes para a direita).
Este processo é realizado 2 vezes na entrada.
+4 bytes que farão a transformação N vezes
fonte
Haskell, 55 bytes
Exemplo de uso:
[[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
é o canto superior esquerdo. Isso usa a transformação inversa.fonte
Python, 69 bytes
Uma melhoria no método de transposição e deslocamento duas vezes de Rod . Aplica a operação
M -> [r[-i:]+r[:-i]for i,r in enumerate(zip(*M))]
duas vezes criando e avaliando a sequênciaIsso supera uma transformação direta (70 bytes), assumindo que a imagem é quadrada e seu comprimento pode ser tomado como entrada:
fonte
Macro ImageJ, 29 bytes
fonte
v=getPixel((2*y-x)%w,(x-y)%h)
.2*x+y
alterado para2*y+x
f(x,y) = (2x+y, x+y)
esta transformação inversa é descrito porf^(-1) = (x-y, 2y-x)
. (Meu outro comentário estava errado.) Portanto, seu código deve estarv=getPixel((x-y)%w,(2*y-x)%h)
.Java, 160
Golfe:
Ungolfed:
fonte