Ruby, 68 ans
La fonction Lambda prend un nombre complexe en argument, renvoie un nombre complexe.
->z{k=1
4.times{z*=?i.to_c
x,y=z.rect
y*y>=x*x&&y<-x&&(z+=k;k=0)}
z}
Nous faisons pivoter le point de 90 degrés 4 fois en le multipliant par i
. Il passe donc par les 4 quadrants et sera renvoyé sous forme inchangée, à l'exception du fait que nous le modifions lorsqu'il se trouve dans l'un d'eux. Le fait qu'il soit toujours modifié dans le même quadrant simplifie la modification.
Il est plus facile de suivre si nous le modifions z
quand il se trouve dans le quadrant de droite. dans ce cas, nous devons augmenter la coordonnée y de 1 (c'est- i
à- dire ajouter à z
.)
Nous vérifions x.abs>=y.abs
en comparant les carrés de x
et y
. Cela nous indique que le point est dans le quadrant droit ou gauche, et non en haut ou en bas. Pour vérifier que cela se trouve en fait dans le quadrant de droite, nous vérifions également que x>y
(strictement plus important car nous voulons exclure le cas x=y
qui appartient au quadrant "supérieur"). Nous ajoutons i
à cela lorsque cela est vrai z
.
Pour des raisons de golf, l'ajout i
n'est pas souhaitable. Au lieu de cela, nous modifions le nombre lorsqu'il se trouve dans le quadrant inférieur, auquel cas nous devons ajouter 1 à la x
coordonnée (ajouter 1 à z
.) Dans ce cas, nous testons le fait y*y>=x*x
de vérifier qu'il se trouve bien dans le quadrant supérieur ou inférieur. Pour nous assurer qu'il se trouve bien dans le quadrant inférieur, nous devons vérifier y<-x
(en excluant strictement le cas du coin inférieur droit où y=-x
.)
Un avantage de cette vérification est qu'il n'y a pas de cas particulier pour la coordonnée 0,0. Malheureusement, il a été constaté que déplacer le point peut le déplacer dans un quadrant différent, ce qui signifie qu'un deuxième mouvement doit être supprimé si ce quadrant est à nouveau vérifié, ce qui annule probablement l'avantage.
Exemple 1
Input 95,-12
Rotate 90deg 12,95
Rotate 90deg -95,12
Rotate 90deg -12,-95
Rotate 90deg 95,-12
y.abs>=x.abs=TRUE, y<-x=TRUE, increase x 95,-11
The check and alteration of the coordinate is done AFTER the rotation.
Thus in this case it gets done in the 4th iteration of the loop, not the 1st.
If the code were rewritten to do the check and alteration BEFORE the rotation,
it would be done in the 1st iteration instead of the 4th.
Exemple 2
Input -1,0
Rotate 90deg 0,-1
y.abs>=x.abs=TRUE, y<-x=TRUE, increase x 1,-1
Rotate 90deg 1,1
Rotate 90deg 1,-1
Rotate 90deg -1,-1
y.abs>=x.abs?=TRUE, y<-x=TRUE but DO NOT CHANGE x!
This is an unusual situation due to the fact that the first move caused the
point to advance by one quadrant. We do NOT want to move it again, for this
reason we need to set k to 0 the first time it is moved.
Dans le programme de test
f=->z{k=1 #amount to be added to coordinate
4.times{z*=?i.to_c #iterate 4 times, rotating point by 90deg till it reaches the original orientation
x,y=z.rect #separate out x and y for testing
y*y>=x*x&&y<-x&&(z+=k;k=0)} #if y.abs>=x.abs and y negative and not equal -x, move the point and zero k.
z} #return z
puts f[Complex(0, 0)] # (0, 0)
puts f[Complex(1, 0)] # (1, 1)
puts f[Complex(1, 1)] # (0, 1)
puts f[Complex(0, 1)] # (-1, 1)
puts f[Complex(-1, 1)] # (-1, 0)
puts
puts f[Complex(-1, 0)] # (-1, -1)
puts f[Complex(-1, -1)] # (0, -1)
puts f[Complex(0, -1)] # (1, -1)
puts f[Complex(1, -1)] # (1, 0)
puts f[Complex(95, -12)] # (95, -11)
puts f[Complex(127, 127)] # (126, 127)
puts
puts f[Complex(-2, 101)] # (-3, 101)
puts f[Complex(-65, 65)] # (-65, 64)
puts f[Complex(-127, 42)] # (-127, 41)
puts f[Complex(-9, -9)] # (-8, -9)
puts f[Complex(126, -127)] # (127, -127)
puts f[Complex(105, -105)] # (105, -104)
Diagramme
L'image suivante montre (en bleu) la zone où x*x>=y*y
, (en jaune) la zone où y<-x
et (en vert) leur intersection, c'est-à-dire la région où la transformation correcte est l'ajout de 1 à z
.