Défi
Étant donné une image raster couleur * avec la même largeur et la même hauteur, sortez l'image transformée sous la carte de chat d'Arnold . (* détails voir ci-dessous)
Définition
Étant donné la taille de l'image, N
nous supposons que les coordonnées d'un pixel sont données sous forme de nombres entre 0
et N-1
.
La carte du chat d'Arnold est alors définie comme suit:
Un pixel aux coordonnées [x,y]
est déplacé vers [(2*x + y) mod N, (x + y) mod N]
.
Ce n'est rien d'autre qu'une transformation linéaire sur le tore: les parties jaune, violette et verte sont remappées sur le carré initial en raison de la mod N
.
Cette carte (appelons-la f
) a les propriétés suivantes:
C'est bijectif , c'est-à-dire réversible: c'est une transformation linéaire avec la matrice
[[2,1],[1,1]]
. Comme il a un déterminant1
et qu'il n'a que des entrées entières, l'inverse n'a également que des entrées entières et est donné par[[1,-1],[-1,2]]
, cela signifie qu'il est également bijectif sur les coordonnées entières.Il s'agit d'un élément de torsion du groupe de cartes d'
N x N
images bijectives , ce qui signifie que si vous l'appliquez suffisamment de fois, vous récupérerez l'image d'origine:f(f(...f(x)...)) = x
le nombre de fois où la carte appliquée à elle-même se traduit par l'identité est garanti inférieur ou égal à3*N
. Dans ce qui suit, vous pouvez voir l'image d'un chat après un nombre donné d'applications itérées de la carte de chat d' Arnold , et une animation de ce à quoi ressemble une application répétée:
Détails
Votre programme ne doit pas nécessairement traiter d'images, mais les matrices / matrices 2D, les chaînes ou les structures 2D similaires sont également acceptables.
Peu importe que votre
(0,0)
point soit en bas à gauche ou en haut à gauche. (Ou dans tout autre coin, si cela est plus pratique dans votre langue.) Veuillez spécifier la convention que vous utilisez dans votre soumission.
Cas de test
Sous forme matricielle ( [1,2,3,4]
est la ligne supérieure, 1
a un index (0,0)
, 2
a un index (1,0)
, 5
a un index (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
Comme image (en bas à gauche (0,0)
):
Réponses:
Gelée , 9 octets
Essayez-le en ligne! Les coordonnées sont comme dans la réponse.
Explication
Cela enveloppe la matrice dans un sens, puis dans l'autre.
la source
MATL , 23 octets
Le
(0,0)
point est en haut à gauche, comme dans les exemples du texte du défi.Essayez-le en ligne!
Explication
Une matrice en MATL peut être indexée avec un seul index au lieu de deux. C'est ce qu'on appelle l'indexation linéaire et utilise l'ordre des colonnes principales . Ceci est illustré par la matrice 4 × 4 suivante, dans laquelle la valeur à chaque entrée coïncide avec son indice linéaire:
Il existe deux approches similaires pour implémenter la cartographie dans le défi:
Créez une matrice d'indexation qui représente le mappage inverse d'Arnold sur des indices linéaires et utilisez-la pour sélectionner les valeurs dans la matrice d'origine. Pour le cas 4 × 4, la matrice d'indexation serait
dire que par exemple l'original
5
à x = 2, y = 1 va à x = 3, y = 2. Cette opération est appelée indexation de référence : utilisez la matrice d'indexation pour dire quel élément choisir dans la matrice d'origine. C'est functon)
, qui prend deux entrées (dans sa configuration par défaut).Créez une matrice d'indexation qui représente le mappage direct d'Arnold sur des indices linéaires et utilisez-la pour écrire les valeurs dans la matrice d'origine. Pour le cas 4 × 4, la matrice d'indexation serait
indiquant que l'entrée x = 2, y = 1 de la nouvelle matrice sera écrasée sur l'entrée avec un index linéaire
10
, c'est-à-dire x = 3, y = 2. C'est ce qu'on appelle l' indexation d'affectation : utilisez la matrice d'indexation, une matrice de données et la matrice d'origine, et écrivez les données sur la matrice d'origine aux indices spécifiés. C'est la fonction(
, qui prend trois entrées (dans sa configuration par défaut).La méthode 1 est plus simple, mais la méthode 2 s'est avérée plus courte.
la source
Mathematica, 44 octets
Un port de l'algorithme fantastique de Lynn . Il y a un caractère invisible de 3 octets, U + F3C7 dans l'encodage UTF-8, avant le dernier
]
; Mathematica le rend en exposantT
et prend la transposition d'une matrice.Mathematica, 54 octets
Fonction sans nom prenant deux arguments, un entier positif
#
et un tableau 2D#2
de dimensions#
x#
, et renvoyant un tableau 2D de forme similaire. Comme dans le cas de test donné, le point avec les coordonnées {0,0} est en haut à gauche et l'axe x est horizontal. Implémentation simple utilisant l'inverse[[1,-1],[-1,2]]
mentionné dans la question, avec un-1
dans la première coordonnée pour tenir compte du fait que les tableaux sont intrinsèquement 1-indexés dans Mathematica. Si nous ne sommes pas autorisés à prendre la dimension de la matrice comme argument supplémentaire, alors cette solution devient plus longue de neuf octets (remplacez le premier#
- pas le#2
- para=Length@#
et tous les#
s suivants para
s).la source
Python 2,
89827773 octetsL'entrée est une liste de listes
La chaîne à l'intérieur de l'exécutif transpose la liste des listes et fait tourner cycliquement chaque liste par l'index de la ligne (base 0 - la 3ème ligne est tournée 2 fois vers la droite).
Ce processus est effectué 2 fois sur l'entrée.
+4 octets qui feront la transformation N fois
la source
Haskell, 55 octets
Exemple d'utilisation:
[[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
est le coin supérieur gauche. Cela utilise la transformation inverse.la source
Python, 69 octets
Une amélioration de la méthode de transposition et de décalage deux fois de Rod . Applique l'opération
M -> [r[-i:]+r[:-i]for i,r in enumerate(zip(*M))]
deux fois en créant et en évaluant la chaîneCela bat de justesse une transformation directe (70 octets), en supposant que l'image est carrée et que sa longueur peut être prise en entrée:
la source
Macro ImageJ, 29 octets
la source
v=getPixel((2*y-x)%w,(x-y)%h)
.2*x+y
changé en2*y+x
f(x,y) = (2x+y, x+y)
cette transformation inverse est décrite parf^(-1) = (x-y, 2y-x)
. (Mon autre commentaire était faux.) Donc votre code doit êtrev=getPixel((x-y)%w,(2*y-x)%h)
.Java, 160
Golfé:
Non golfé:
la source