Rotation Chebyshev

36

Considérons une grille régulière, où chaque cellule a des coordonnées entières. Nous pouvons regrouper les cellules en "anneaux" (de forme carrée) où les cellules de chaque anneau ont la même distance de Chebyshev (ou distance de l'échiquier) par rapport à l'origine. Votre tâche consiste à prendre une telle coordonnée de cellule et à la faire pivoter d’une position dans le sens contraire des aiguilles d’une montre dans son anneau. Cela implémente le mappage suivant:

entrez la description de l'image ici

Ainsi, par exemple, si l'entrée est, (3, -2)vous devez afficher (3, -1). Notez que (0, 0)c'est la seule entrée qui devrait correspondre à elle-même.

Règles

Le format I / O est assez flexible. Vous pouvez utiliser deux nombres individuels, une paire / liste / tableau / tuple de nombres, un seul nombre complexe, une chaîne contenant deux nombres, etc.

Vous pouvez supposer que -128 < x,y < 128.

Vous pouvez écrire un programme ou une fonction et utiliser l’une quelconque de nos méthodes standard de réception d’entrée et de sortie.

Vous pouvez utiliser n'importe quel langage de programmation , mais notez que ces failles sont interdites par défaut.

C'est du , donc la réponse valide la plus courte - mesurée en octets - est gagnante.

Cas de test

(0, 0)       => (0, 0)
(1, 0)       => (1, 1)
(1, 1)       => (0, 1)
(0, 1)       => (-1, 1)
(-1, 1)      => (-1, 0)
(-1, 0)      => (-1, -1)
(-1, -1)     => (0, -1)
(0, -1)      => (1, -1)
(1, -1)      => (1, 0)
(95, -12)    => (95, -11)
(127, 127)   => (126, 127)
(-2, 101)    => (-3, 101)
(-65, 65)    => (-65, 64)
(-127, 42)   => (-127, 41)
(-9, -9)     => (-8, -9)
(126, -127)  => (127, -127)
(105, -105)  => (105, -104)
Martin Ender
la source
Pouvons-nous mélanger les formats d’entrée et de sortie, par exemple prendre un tuple et sortir un nombre complexe?
Dennis
@ Dennis oui c'est bien.
Martin Ender

Réponses:

16

JavaScript (ES6), 60 59 octets

Prend les entrées avec la syntaxe de currying (x)(y)et retourne un tableau [new_x, new_y].

x=>y=>(x|y&&((z=x+(y<0))>-y?z>y?y++:x--:z>y?x++:y--),[x,y])

Comment ça marche

Notre tâche principale est de déterminer dans quel quadrant nous sommes, afin de savoir dans quelle direction nous déplacer.

Nous pouvons utiliser cette formule en première approximation:

x > -y ? (x > y ? 0 : 1) : (x > y ? 2 : 3)

Voici ce que nous obtenons:

3 1 1 1 1 1 1 1 1
3 3 1 1 1 1 1 1 0
3 3 3 1 1 1 1 0 0
3 3 3 3 1 1 0 0 0
3 3 3 3 3 0 0 0 0
3 3 3 3 2 2 0 0 0
3 3 3 2 2 2 2 0 0
3 3 2 2 2 2 2 2 0
3 2 2 2 2 2 2 2 2

Presque là. Mais les coins inférieur gauche et inférieur droit des anneaux ne sont pas valides. Nous devons déplacer la moitié inférieure de la matrice d'une position vers la gauche, nous définissons donc z:

z = y < 0 ? x + 1 : x

Et nous remplaçons xpar zdans notre formule:

z > -y ? (z > y ? 0 : 1) : (z > y ? 2 : 3)

Qui conduit à:

3 1 1 1 1 1 1 1 1 
3 3 1 1 1 1 1 1 0 
3 3 3 1 1 1 1 0 0 
3 3 3 3 1 1 0 0 0 
3 3 3 3 3 0 0 0 0 
3 3 3 2 2 0 0 0 0 
3 3 2 2 2 2 0 0 0 
3 2 2 2 2 2 2 0 0 
2 2 2 2 2 2 2 2 0 

Toute la matrice est maintenant correcte, sauf le cas particulier [0, 0](pas de déménagement du tout) qui doit être traité séparément.

Cas de test

Arnauld
la source
13

Jelly , 20 14 12 octets

S;IṠN0n/¦Ạ¡+

L'entrée et la sortie sont sous forme de tableaux. Essayez-le en ligne! ou vérifier tous les cas de test .

Contexte

Pour déterminer dans quelle direction nous devons nous déplacer, nous pouvons observer la position relative du point de départ par rapport aux bissectrices du quadrant x + y = 0 (bleu) et x - y = 0 (rouge).

diagramme

  • L'origine est fixée. Nous avançons en ajoutant [0, 0] au point de départ.

  • Les points dans le triangle le plus haut - y compris la bissectrice du premier quadrant - ont une somme positive et un delta non négatif ( y - x ). Nous avançons en ajoutant [-1, 0] au point de départ.

  • Les points dans le triangle le plus à gauche - y compris la bissectrice du deuxième quadrant - ont une somme non positive et un delta positif. Nous avançons en ajoutant [0, -1] au point de départ.

  • Les points dans le triangle le plus bas - y compris la bissectrice du troisième quadrant - ont une somme négative et un delta non positif. Nous avançons en ajoutant [1, 0] au point de départ.

  • Les points dans le triangle le plus à droite - y compris la bissectrice du quatrième quadrant - ont une somme non négative et un delta négatif. Nous avançons en ajoutant [0, 1] au point de départ.

Pour déterminer la bonne direction, nous calculons [-sign (x + y), -sign (y - x)] , qui n'a que neuf résultats possibles.

Le tableau suivant montre quels résultats doivent être associés à quelles directions.

    sign(x+y) |  sign(y-x) | -sign(x+y) | -sign(y-x) |     Δx     |     Δy
  ------------+------------+------------+------------+------------+------------
        0     |      0     |      0     |      0     |      0     |      0
        1     |      0     |     -1     |      0     |     -1     |      0
        1     |      1     |     -1     |     -1     |     -1     |      0
        0     |      1     |      0     |     -1     |      0     |     -1
       -1     |      1     |      1     |     -1     |      0     |     -1
       -1     |      0     |      1     |      0     |      1     |      0
       -1     |     -1     |      1     |      1     |      1     |      0
        0     |     -1     |      0     |      1     |      0     |      1
        1     |     -1     |     -1     |      1     |      0     |      1

Cela laisse trois cas.

  • Si au moins un des signes est 0 , [Δx, Δy] = [-sign (x + y), -sign (yx)] .

  • Si les signes sont égaux et non nuls, [Δx, Δy] = [-sign (x + y), 0] .

  • Si les signes sont différents et non nuls, [Δx, Δy] = [0, -sign (yx)] .

Comment ça marche

S;IṠN0n/¦Ạ¡+  Main link. Argument: [x, y] (pair of integers)

S             Sum; compute x + y.
  I           Increments; compute [y - x].
 ;            Concatenate; yield [x + y, y - x].
   Ṡ          Sign; compute [sign(x + y), sign(y - x)].
    N         Negate; yield [-sign(x + y), -sign(y - x)].
          ¡   Do n times:
         Ạ      Set n to all([-sign(x + y), -sign(y - x)]), i.e., 1 if the signs
                are both non-zero and 0 otherwise.
        ¦       Conditional application:
      n/          Yield 1 if the signs are not equal, 0 if they are.
     0            Replace the coordinate at 1 or 0 with a 0.
              This returns [Δx, Δy].
           +  Add; yield  [Δx + x, Δy + y].
Dennis
la source
5

Pyth , 19 octets

&Q+^.jZ1.RhycPQ.n0Z

Essayez-le en ligne!

Traduction de ma réponse Julia :

&Q                    If input is 0, then 0, else:
             PQ         Get phase of input
            c  .n0      Divide by π
           y            Double
          h             Add one
        .R        Z     Round to integer
   ^.jZ1                Raise i to this power
  +                     Add to input
Lynn
la source
Belle réponse en parabole!
Tomsmeding
5

Python, 55 octets

lambda x,y:(x-(-y<x<=y)+(y<=x<-y),y+(~x<y<x)-(x<y<=-x))

Détecte les quatre quadrants diagonaux et décale la coordonnée appropriée.

Xnor
la source
4

Haskell, 77 71 69 octets

x#y|y>=x,-x<y=(x-1,y)|y>x=(x,y-1)|y< -x=(x+1,y)|y<x=(x,y+1)|1>0=(0,0)

Cela consiste simplement à vérifier chacun de ces quadrants inclinés et à modifier l'entrée en conséquence. Notez que les espaces sont nécessaires, sinon, par exemple, >-serait compris comme un opérateur (non défini).

Merci @nimi d'avoir supprimé quelques octets de plus!

flawr
la source
,au lieu de&& dans la première garde enregistre un octet. Ensuite, vous pouvez basculer la deuxième comparaison sur -x<yun autre octet.
nimi
Merci, je n'étais pas au courant ,!
mardi
4

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 zquand 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.absen comparant les carrés de xet 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=yqui appartient au quadrant "supérieur"). Nous ajoutons ià cela lorsque cela est vrai z.

Pour des raisons de golf, l'ajout in'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 xcoordonnée (ajouter 1 à z.) Dans ce cas, nous testons le fait y*y>=x*xde 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<-xet (en vert) leur intersection, c'est-à-dire la région où la transformation correcte est l'ajout de 1 à z.

entrez la description de l'image ici

Level River St
la source
1
Désolé, je ne suis pas l'explication. Souhaitez-vous ajouter un exemple ou un diagramme?
Martin Ender
Explication @Martin ajoutée. C’était une approche intéressante, mais en raison de la nécessité de supprimer le double mouvement des points qui changent de quadrant lors de leur premier déplacement, cela ne s’est pas révélé aussi élégant que je l’espérais.
Level River St
4

Python, 52 octets

h=lambda z:z and 1j*h(z/1j)if'-'in`z*1j-z-1`else z+1

Entrées et sorties complexes. Pour tester le point situé dans le quadrant inférieur de la diagonale, faites-le d'abord pivoter dans le sens inverse des aiguilles d'une montre pour le déplacer dans le quadrant standard (x> 0, y> 0), puis testez si le résultat ne contient pas de signe moins dans la représentation sous forme de chaîne. Soustraire 1 en premier tient compte de la condition limite.

Si ce n’est pas dans ce quadrant, faites pivoter l’ensemble du problème de 90 degrés. L'entrée est zéro est spécialement gérée pour sortir elle-même.

Autres tentatives avec des nombres complexes:

## 56 bytes
## Coordinate input, complex output
q=lambda x,y:(y<=x<-y)*(1j*y-~x)or x+1j*y and 1j*q(y,-x)

## 60 bytes
h=lambda z:(z+1)*(z.imag<=z.real<-z.imag)or z and 1j*h(z/1j)

## 63 bytes
from cmath import*
h=lambda z:z and 1j**(phase(z*1j-z)*2//pi)+z
Xnor
la source
3

Mathematica, 34 octets

±0=0
±z_:=z+I^Floor[2Arg@z/Pi+3/2]

Ceci définit un opérateur unaire ±qui prend et retourne un nombre complexe dont les composantes représentent xet y.

Maintenant que Lynn a révélé la solution de numérotation complexe et que Dennis a battu mon score, je ne me sens pas si mal pour avoir posté ma mise en œuvre référencée au golf. :) (Il s'avère être pratiquement identique à la réponse de Lynn.)

Martin Ender
la source
Cela aiderait-il? ± 0 = 0 ⁢ ± z_: = z + I ^ 2 Arg @ z / Pi + 3/2 (peut-être avec un caractère différent pour les supports de plancher)
DavidC
@DavidC malheureusement pas, car je devrais alors utiliser le codage UTF-8, puis le ± coûterait 2 octets chacun.
Martin Ender
Ne serait-ce pas 4 octets au lieu de 7, donnant ainsi une économie de 3 octets?
DavidC
@DavidC non, les supports au sol seraient de 3 octets chacun.
Martin Ender
Je n'étais pas au courant de ça. Mais même dans ce cas, vous devriez toujours économiser 1 octet.
DavidC
3

MATL , 19 17 octets

t|?JGJq*X/EYP/k^+

Ceci utilise des nombres complexes en entrée et en sortie.

Essayez-le en ligne! Ou vérifiez tous les cas de test .

Explication

Prenons l'entrée -127+42jcomme exemple.

t|       % Implicit input. Duplicate and take absolute value
         % STACK: -127+42j, 133.764718816286
?        % If nonzero
         % STACK: -127+42j
  J      %   Push j (imaginary unit)
         %   STACK: -127+42j, j
  GJq*   %   Push input multiplied by -1+j. This adds 3*pi/4 to the phase of the input
         %   STACK: -127+42j, j, 85-169i
  X/     %   Phase of complex number
         %   STACK: -127+42j, j, -1.10478465600433
  EYP/   %   Divide by pi/2
         %   STACK: -127+42j, j, -0.703327756220671
  k      %   Round towards minus infinity
         %   STACK: -127+42j, j, -1
  ^      %   Power
         %   STACK: -127+42j, -j
  +      %   Add
         %   STACK: -127+41j
         % Implicit end
         % Implicit display
Luis Mendo
la source
3

Ruby, 51 octets

Forme originale

->x,y{d=x*x-y*y
[x+(d>0?0:-y<=>x),y+(d<0?0:x<=>y)]}

Forme alternative pour le commentaire de Xnor

->x,y{[x+(x*x>y*y ?0:-y<=>x),y+(x*x<y*y ?0:x<=>y)]}

Utilise le même type d'inégalités que mon autre réponse, mais d'une manière différente.

Dans le programme de test

f=->x,y{d=x*x-y*y
[x+(d>0?0:-y<=>x), #if y.abs>=x.abs: x+=1 if -y>x, x-=1 if -y<x 
y+(d<0?0:x<=>y)]}  #if x.abs>=y.abs: y+=1 if  x>y, y-=1 if  x<y

p f[0, 0]       # (0, 0)
p f[1, 0]       # (1, 1)
p f[1, 1]       # (0, 1)
p f[0, 1]       # (-1, 1)
p f[-1, 1]      # (-1, 0)
puts
p f[-1, 0]      # (-1, -1)
p f[-1, -1]     # (0, -1)
p f[0, -1]      # (1, -1)
p f[1, -1]      # (1, 0)
p f[95, -12]    # (95, -11)
p f[127, 127]   # (126, 127)
puts
p f[-2, 101]    # (-3, 101)
p f[-65, 65]    # (-65, 64)
p f[-127, 42]   # (-127, 41)
p f[-9, -9]     # (-8, -9)
p f[126, -12]   # (127, -127)
p f[105, -105]  # (105, -104)
Level River St
la source
La dmission en vaut-elle la peine? On dirait que vous pouvez simplement comparer x*x>y*y.
xnor
@Xnor, malheureusement, Ruby a besoin d'un espace entre les deux y*yet a ?donc exactement la même longueur. Je l'ai inclus car je pense que votre façon de faire est, à certains égards, plus ordonnée. Je pense que Ruby essaie de passer cela comme y?un nom de fonction légal.
Level River St
3

Julia, 38 34 octets

!z=z==0?0:z+im^int(2angle(z)/pi+1)

Dennis a sauvé quatre octets. Merci!

Essayez-le en ligne!

Lynn
la source
On dirait que j'ai confondu le comportement de int avec différentes versions de Julia (ce qui, pour ma défense, est terriblement incohérent). Julia 0.4 (la version sur TIO) arrondit les moitiés au niveau égal, ainsi cela ne fonctionnera pas tel quel. Dans Julia 0.3, vous pouvez utiliser int(2angle(z)/pi+5)le même nombre d'octets (les puissances négatives provoquent une erreur pour une raison quelconque).
Dennis
En outre, vous pouvez enregistrer un octet !z=z+(z!=0)im^...dans toutes les versions.
Dennis
2

C ++, 94 octets

#define a(x) (x>0?x:-(x))
#define f(x,y) y>a(x-.5)?x--:-y>a(x+.5)?x++:x>a(y+.5)?y++:x|y?y--:x;

Ungolfed:

#define a(x) (x>0?x:-(x))  //shorter than std::abs from <cmath>
#define f(x,y) 
    y>a(x-.5)?      // shift absolute value function by 0.5 to the right to get upper fourth
        x--:
        -y>a(x+.5)? //same for lower fourth
            x++:
            x>a(y+.5)? //same for right fourth
                y++:
                x|y? //only left fourth and 0 are left
                    y--:
                    x; //can't be empty, just does nothing

Usage:

#include <iostream>
void test(int x, int y, int rx, int ry){
    std::cout << "(" << x << ", " << y << ")=>";
    f(x,y);
    std::cout << "(" << x << ", " << y << ") - " << ((x==rx&&y==ry)?"OK":"FAILURE") << std::endl;
}

//Using the test cases from the question
int main() {
    test(0, 0, 0, 0);
    test(1, 0, 1, 1);
    test(1, 1, 0, 1);
    test(0, 1, -1, 1);
    test(-1, 1, -1, 0);
    test(-1, 0, -1, -1);
    test(-1, -1, 0, -1);
    test(0, -1, 1, -1);
    test(1, -1, 1, 0);
    test(95, -12, 95, -11);
    test(127, 127, 126, 127);
    test(-2, 101, -3, 101);
    test(-65, 65, -65, 64);
    test(-127, 42, -127, 41);
    test(-9, -9, -8, -9);
    test(126, -127, 127, -127);
    test(105, -105, 105, -104);

    return 0;
}

Essayez-le en ligne

Anedar
la source
Je suis à peu près sûr que ça (x>0?x:-(x))peut l'être (x>0?x:-x).
Yytsi
Malheureusement non, puisque le jeton x sera remplacé par exemple par x + .5 qui obtiendrait simplement -x + .5.
Anedar
Bien. J'avais un état d'esprit où la négation sans parenthèses renversait le signe: D
Yytsi
À proprement parler, vous avez utilisé le préprocesseur C (qui fait certes partie du C ++, mais qui est également partagé avec d'autres variantes et descendants du C)
tucuxi
2

R, 131 110 octets

Une fonction qui prend les deux entiers, x,yen entrée et écrit la sortie sur stdout. La solution suit le schéma de contrôle de @Dennis mais pourrait probablement être jouée au golf.

EDIT: code mis à jour basé sur les suggestions de @ JDL et sauvegardé de nombreux octets.

function(x,y){X=sign(x+y);Y=sign(y-x);if(!X|!Y){x=x-X;y=y-Y}else if(X==Y&X&Y)x=x-X else if(X-Y&X)y=y-Y;c(x,y)}

Ungolfed

f=function(x,y){
    X=sign(x+y)                 # calculate sign 
    Y=sign(y-x)                 #  =||=
    if(!X|!Y){x=x-X;y=y-Y}      # if at least one is 0: subtract sign
    else if(X==Y&X&Y)x=x-X      # if signs are equal and non-zero: add sign to x
    else if(X-Y&X)y=y-Y         # if signs are not equal and non-zero: add sign to y
    c(x,y)                      # print to stdout
}
Billywob
la source
1
Je pense que certaines conditions logiques peuvent être abrégées: as.logical(-1)est TRUE, X==0|Y==0peut donc devenir !X|!Yet la condition if(X!=Y...)peut devenir if(X-Y). Aussi, si X==Yet X!=0ensuite Y!=0est redondant. En fait, toutes les !=0parties sont redondantes. if(X!=0)est équivalent à if(X).
JDL
1
En outre, étant donné que « le format d' E / S est assez flexible », il est probablement juste de jeu sortie implicitement au c(x,y)lieu de cat(x,y).
JDL
@JDL Voilà quelques astuces très utiles pour le golf auxquelles je n’avais jamais pensé, merci beaucoup! Mise à jour de la réponse.
Billywob
2

JavaScript (ES6), 57 octets (55–63 †)

Accepte un tableau [x, y], le modifie sur place et le renvoie.

c=>([x,y]=c,i=x>y|x==y&x<0,c[i^x<-y|x==-y]-=-i|!!(x|y),c)

Comment ça marche

c=>(

Il s’agit d’une fonction fléchée à un seul paramètre avec un returncorps concis sans-frais.

[x,y]=c

Le paramètre est immédiatement déstructuré en xet yvariables.

,

L'opérateur de virgule combine plusieurs expressions en une, en utilisant le résultat de la dernière.

i=x>y|x==y&x<0

iest utilisé pour différencier les cas d'incrémentation et de décrémentation. Quand xest supérieur à y, nous nous situons dans le quadrant inférieur ou le quadrant inférieur droit et devons avancer dans une dimension ( i=1par la contrainte booléenne au nombre). De même lorsque nous sommes sur la partie négative de la diagonale x = y en division . Dans tous les autres cas, y compris l'origine, aucune augmentation n'est requise ( i=0).

c[i^x<-y|x==-y]

Nous utilisons une expression assez similaire pour contrôler l’index de tableau à ajuster. Lorsque nous incrémentons et non dans les quadrants de gauche ou du bas (ou lorsque nous n'incrémentons pas et dans le gauche ou le bas), le XOR au niveau du bit produira 1et nous ajusterons la valeur y . De même pour quand nous sommes sur la division x = -y diagonale (y compris l'origine). Dans tous les autres cas, l'indice sera 0( x ).

-=-i|!!(x|y)

Quand iest 1-ce que nous allons l'ajouter à la valeur spécifiée. Quand iest 0, nous soustrayons 1 de la valeur si et seulement si nous ne sommes pas à l'origine. Ce dernier est détecté en x|yrenvoyant non nul, découpé en {0, 1} par une contrainte booléenne, et la négation de inous permet d'utiliser un bit OU au lieu de logique (puisqu'il -1n'a pas de bit zéro, il est protégé contre la modification).

c

Le tableau est le dernier, il sera donc retourné.

Essai

† Variations

Nous pouvons économiser deux octets supplémentaires en ignorant une valeur de retour significative et en utilisant uniquement la mutation d'entrée:

c=>([x,y]=c,i=x>y|x==y&x<0,c[i^x<-y|x==-y]-=-i|!!(x|y))

… Ou nous pouvons ignorer la mutation d'entrée et rendre toutes les variables locales pour une fonction pure, au prix de six octets:

([x,y],i=x>y|x==y&x<0,c=[x,y])=>(c[i^x<-y|x==-y]-=-i|!!(x|y),c)
gibson042
la source
1

JavaScript (ES6), 80 76 octets

(x,y,s=Math.max(x,y,-x,-y))=>(s?x+s?y-s?x-s?x++:y++:x--:y+s?y--:x++:0,[x,y])
Neil
la source
1

Haskell, 53 octets

0%0=(0,0)
x%y|y>=0-x,y<x=(x,y+1)|(p,q)<-(-y)%x=(q,-p)

Prend deux nombres, sort un tuple. Si le point est dans la section est -x<=y<x, augmentez la seconde coordonnée de 1. Sinon, faites défiler les quadrants en faisant pivoter le point d’entrée de 90 degrés, en appelant la fonction dessus, puis en revenant en arrière.

Xnor
la source
1

Raquette 191 octets

(cond[(= 0 x y)(list x y)][(= x y)(if(> x 0)(list(sub1 x)y)(list(add1 x)y))][(> x y)(if(>= x(abs y))
(list x(add1 y))(list(add1 x)y))][(< x y)(if(> y(abs x))(list(sub1 x)y)(list x(sub1 y)))])

Ungolfed (traduction directe des instructions de la figure en code sans utiliser de formule intermédiaire):

(define(f x y)
  (cond
    [(= 0 x y) (list x y)]
    [(= x y)
     (if (> x 0)
         (list (sub1 x) y)   ; left
         (list (add1 x) y))] ; right
    [(> x y)
     (if (>= x (abs y))
         (list x (add1 y))   ; up
         (list (add1 x) y))] ; right
    [(< x y)
     (if (> y (abs x))
         (list (sub1 x) y)   ; left
         (list x (sub1 y)))] ; down
    ))

Essai:

(f 0  0)      
(f 1  0)     
(f 1  1)     
(f 0  1)     
(f -1  1)    
(f -1  0)    
(f -1  -1)   
(f 0  -1)    
(f 1  -1)    
(f 95  -12)  
(f 127  127) 
(f -2  101)  
(f -65  65)  
(f -127  42) 
(f -9  -9)    
(f 126  -127) 
(f 105  -105) 

Sortie:

'(0 0)
'(1 1)
'(0 1)
'(-1 1)
'(-1 0)
'(-1 -1)
'(0 -1)
'(1 -1)
'(1 0)
'(95 -11)
'(126 127)
'(-3 101)
'(-65 64)
'(-127 41)
'(-8 -9)
'(127 -127)
'(105 -104)
rnso
la source
1

En fait , 16 octets

Ceci prend un nombre complexe en entrée et génère un autre nombre complexe. Suggestions de golf bienvenues! Essayez-le en ligne!

;`₧╦@/τuLïⁿ+0`╬X

Ungolfing

         Implicit input z.
;        Duplicate z.
`...`╬   If z is non-zero (any a+bi except 0+0j), run the following function.
           Stack: z, z
  ₧        Get phase(z).
  ╦@/      Divide phase(z) by pi.
  τuL      Push floor(2*phase(z)/pi + 1).
  ïⁿ       Push 1j ** floor(2*phase(z)/pi + 1).
  +        And add it to z. This is our rotated z.
  0        Push 0 to end the function.
X        Discard either the duplicate (0+0j) or the 0 from the end of function.
         Implicit return.
Sherlock9
la source
0

Scala, 184 octets

val s=math.signum _
(x:Int,y:Int)=>{val m=x.abs max y.abs
if(x.abs==y.abs)if(s(x)==s(y))(x-s(x),y)else(x,y-s(y))else
if(x.abs==m)(x,y+Seq(0,x).indexOf(m))else(x-Seq(0,y).indexOf(m),y)}

Ungolfed:

import math._

(x: Int, y: Int) => {
  val max = max(x.abs, y.abs)
  if (x.abs == y.abs)
    if (signum(x) == signum(y))
      (x - signum(x), y)
    else
      (x, y - signum(y))
  else
    if (x.abs == max)
      (x, y + Seq(0, x).indexOf(max))
    else
      (x - Seq(0, y).indexOf(max), y)
}

Explication:

val s=math.signum _             //define s as an alias to math.signum
(x:Int,y:Int)=>{                //define an anonymous function
  val m=x.abs max y.abs           //calculate the maximum of the absolute values,
                                  //which is 1 for the innermost circle and so on.
  if(x.abs==y.abs)                //if we have a cell at a corner of a circle
    if(s(x)==s(y))                  //if it's at the top-left or bottom-right, we need to
                                    //modify the x value
      (x-s(x),y)                      //if x is positive (bottom-right),
                                      //we need to return (x+1,y),
                                      //(x-1,y) If it's at the top-left.
                                      //This can be simplified to (x-s(x),y)
    else                            //for top-right and bottom-left, 
      (x,y-s(y))                      //modify y in the same way.
  else                            //we don't have a corner piece
    if(x.abs==m)                    //if we're at the left or right edge of the square
      (x,y+Seq(0,x).indexOf(m))       //if it's a piece from the right edge, add one
                                      //to y, else subtract 1
    else                            //it's a piece from the top or bottm edge
      (x-Seq(0,y).indexOf(m),y)       //subtract 1 from x if it's from the top edge,
                                      //else subtract -1
}
corvus_192
la source