Rotación de Chebyshev


36

Considere una cuadrícula regular, donde cada celda tiene coordenadas enteras. Podemos agrupar las células en "anillos" (de forma cuadrada) donde las células en cada anillo tienen la misma distancia de Chebyshev (o distancia del tablero de ajedrez) desde el origen. Su tarea es tomar dicha coordenada de celda y rotar esa celda una posición en sentido antihorario dentro de su anillo. Esto implementa la siguiente asignación:

ingrese la descripción de la imagen aquí

Entonces, por ejemplo, si la entrada es (3, -2), debe salir (3, -1). Tenga en cuenta que (0, 0)es la única entrada que debe asignarse a sí misma.

Reglas

El formato de E / S es bastante flexible. Puede usar dos números individuales, un par / lista / matriz / tupla de números, un único número complejo, una cadena que contiene dos números, etc.

Puedes suponer eso -128 < x,y < 128.

Puede escribir un programa o una función y utilizar cualquiera de nuestros métodos estándar para recibir entradas y proporcionar salidas.

Puede usar cualquier lenguaje de programación , pero tenga en cuenta que estas lagunas están prohibidas de forma predeterminada.

Este es el , por lo que gana la respuesta válida más corta, medida en bytes .

Casos de prueba

(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)

¿Podemos mezclar el formato de entrada y salida, por ejemplo, tomar una tupla y generar un número complejo?
Dennis

@ Dennis sí, está bien.
Martin Ender

Respuestas:


16

JavaScript (ES6), 60 59 bytes

Toma datos con la sintaxis de curry (x)(y)y devuelve una matriz [new_x, new_y].

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

Cómo funciona

Nuestra tarea principal es determinar en qué cuadrante estamos, para saber en qué dirección debemos movernos.

Podemos usar esta fórmula como primera aproximación:

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

Esto es lo que obtenemos:

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

Casi ahi. Pero las esquinas inferiores izquierda e inferior derecha de los anillos no son válidas. Necesitamos desplazar la mitad inferior de la matriz una posición hacia la izquierda, por lo que definimos zcomo:

z = y < 0 ? x + 1 : x

Y reemplazamos xcon zen nuestra fórmula:

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

Lo que lleva a:

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 

Ahora toda la matriz es correcta, excepto el caso especial [0, 0](sin movimiento) que debe abordarse por separado.

Casos de prueba


13

Jalea , 20 14 12 bytes

S;IṠN0n/¦Ạ¡+

La entrada y la salida están en forma de matrices. Pruébalo en línea! o verificar todos los casos de prueba .

Fondo

Para determinar en qué dirección tenemos que movernos, podemos observar la posición relativa del punto de inicio de los bisectores del cuadrante x + y = 0 (azul) y x - y = 0 (rojo).

diagrama

  • El origen es fijo. Avanzamos agregando [0, 0] al punto de inicio.

  • Los puntos en el triángulo superior, incluida la bisectriz del primer cuadrante, tienen una suma positiva y un delta no negativo ( y - x ). Avanzamos agregando [-1, 0] al punto de inicio.

  • Los puntos en el triángulo más a la izquierda, incluida la bisectriz del segundo cuadrante, tienen una suma no positiva y un delta positivo. Avanzamos agregando [0, -1] al punto de inicio.

  • Los puntos en el triángulo inferior, incluida la bisectriz del tercer cuadrante, tienen una suma negativa y un delta no positivo. Avanzamos agregando [1, 0] al punto de inicio.

  • Los puntos en el triángulo más a la derecha, incluida la bisectriz del cuarto cuadrante, tienen una suma no negativa y un delta negativo. Avanzamos agregando [0, 1] al punto de inicio.

Para determinar la dirección correcta, calculamos [-sign (x + y), -sign (y - x)] , que tiene solo nueve resultados posibles.

La siguiente tabla ilustra qué resultados deben asignarse a qué direcciones.

    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

Esto deja tres casos.

  • Si al menos uno de los signos es 0 , [Δx, Δy] = [-sign (x + y), -sign (yx)] .

  • Si los signos son iguales y distintos de cero, [Δx, Δy] = [-sign (x + y), 0] .

  • Si los signos son diferentes y no son cero, [Δx, Δy] = [0, -sign (yx)] .

Cómo funciona

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].


5

Python, 55 bytes

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

Detecta los cuatro cuadrantes diagonales y desplaza la coordenada adecuada.


4

Haskell, 77 71 69 bytes

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)

Esto es solo verificar cada uno de esos cuadrantes inclinados y modificar la entrada en consecuencia. Tenga en cuenta que los espacios son necesarios, de lo contrario >-, se entendería como un operador (que no está definido).

¡Gracias @nimi por eliminar algunos bytes más!


,en lugar de&& dentro del primer guardia guarda un byte. Y luego puede cambiar la segunda comparación a -x<yotro byte.
nimi

¡Gracias, no estaba al tanto ,!
falla

4

Rubí, 68

La función Lambda toma un número complejo como argumento, devuelve un número complejo.

->z{k=1
4.times{z*=?i.to_c
x,y=z.rect
y*y>=x*x&&y<-x&&(z+=k;k=0)}
z} 

Rotamos el punto 90 grados 4 veces multiplicando por i. Por lo tanto, pasa a través de los 4 cuadrantes, y se devolvería sin cambios, excepto por el hecho de que lo modificamos cuando está en uno específico de ellos. El hecho de que siempre se modifique en el mismo cuadrante simplifica la modificación.

Es más fácil de seguir si lo modificamos zcuando está en el cuadrante derecho. en este caso, necesitamos aumentar la coordenada y en 1 (es decir, agregar ia z).

Verificamos x.abs>=y.abscomparando los cuadrados de xy y. Esto nos dice que el punto está en el cuadrante derecho o izquierdo, no arriba o abajo. Para comprobar que es, de hecho, en el cuadrante derecha, comprobamos también que x>y(estrictamente mayor porque queremos excluir el caso x=yque pertenece al cuadrante "top".) Cuando esto es cierto añadimos ia z.

Por razones de golf, agregar ino es deseable. En su lugar, modificamos el número cuando está en el cuadrante inferior, en cuyo caso tenemos que agregar 1 a la xcoordenada (agregar 1 a z). En este caso, comprobamos que y*y>=x*xpara verificar que esté en el cuadrante superior o inferior. Para asegurarnos de que esté en el cuadrante inferior, debemos verificar y<-x(excluyendo estrictamente el caso de la esquina inferior derecha donde y=-x).

Una ventaja de esta comprobación es que no hay un caso especial para la coordenada 0,0. Desafortunadamente, se descubrió que mover el punto puede desplazarlo a un cuadrante diferente y esto significa que se debe suprimir un segundo movimiento en caso de que se vuelva a verificar ese cuadrante, lo que probablemente niega la ventaja.

Ejemplo 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.

Ejemplo 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.

En programa de prueba

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)

Diagrama

La siguiente imagen muestra (azul) el área donde x*x>=y*y, (amarillo) el área donde y<-xy (verde) la intersección de estos, que es la región donde la transformación correcta es la suma de 1 a z.

ingrese la descripción de la imagen aquí


1
Lo siento, no estoy siguiendo la explicación. ¿Te importaría agregar un ejemplo o un diagrama?
Martin Ender

Se agregó la explicación de @Martin. Este fue un enfoque interesante, pero debido a la necesidad de suprimir el doble movimiento de puntos que cambian de cuadrante la primera vez que se mueven, no resultó tan elegante como esperaba.
Level River St

4

Python, 52 bytes

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

Entrada y salida complejas. Para probar que el punto se encuentra en el cuadrante diagonal inferior, primero gírelo 135 en sentido antihorario para mover ese cuadrante al cuadrante estándar (x> 0, y> 0), y pruebe si el resultado no tiene un símbolo menos en la representación de la cadena. Restar 1 primero se ocupa de la condición de contorno.

Si no está en ese cuadrante, gire todo el problema 90 grados. La entrada es cero, se maneja especialmente para salir.

Otros intentos con números complejos:

## 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

3

Mathematica, 34 bytes

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

Esto define un operador unario ± que toma y devuelve un número complejo cuyos componentes representan xy y.

Ahora que Lynn ha revelado la solución de números complejos y Dennis ha superado mi puntaje, no me siento tan mal por publicar mi implementación referenciada de golf. :) (Resulta ser prácticamente idéntico a la respuesta de Lynn).


¿Esto ayudaría? ± 0 = 0 ⁢ ± z_: = z + I ^ ⌊ 2 ⁢ Arg @ z / Pi + 3/2 ⌋ (quizás con un carácter diferente para los soportes de piso)
DavidC

@DavidC desafortunadamente no porque entonces tendría que usar la codificación UTF-8 y luego el ± costaría 2 bytes cada uno.
Martin Ender

¿No serían 4 bytes en lugar de 7, lo que daría una economía de 3 bytes?
DavidC

@DavidC no, los corchetes serían de 3 bytes cada uno.
Martin Ender

No estaba al tanto de eso. Pero, aun así, aún debería estar guardando 1 byte.
DavidC

3

MATL , 19 17 bytes

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

Esto usa números complejos como entrada y salida.

Pruébalo en línea! O verificar todos los casos de prueba .

Explicación

Tomemos la entrada -127+42jcomo un ejemplo.

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

3

Ruby, 51 bytes

Forma original

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

Forma alternativa por comentario de Xnor

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

Utiliza el mismo tipo de desigualdades que mi otra respuesta, pero de una manera diferente.

En programa de prueba

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)

¿ dVale la pena la tarea? Parece que solo puedes comparar x*x>y*y.
xnor

@Xnor lamentablemente rubí requiere un espacio entre y*yy ?lo que es exactamente la misma longitud. Lo he incluido ya que creo que tu manera es más ordenada. Creo que Ruby está tratando de pasarlo, ya y?que sería un nombre de función legal.
Level River St el

3

Julia, 38 34 bytes

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

Dennis ahorró cuatro bytes. ¡Gracias!

Pruébalo en línea!


Parece que mezclé el comportamiento de int en diferentes versiones de Julia (que, en mi defensa, es terriblemente inconsistente). Julia 0.4 (la versión en TIO) redondea mitades hacia pares, por lo que esto no funcionará como está. En Julia 0.3, puede usar int(2angle(z)/pi+5)el mismo número de bytes (las potencias negativas causan un error por cualquier motivo).
Dennis

Además, puede guardar un byte con !z=z+(z!=0)im^...en todas las versiones.
Dennis

2

C ++, 94 bytes

#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;

Sin golf:

#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

Uso:

#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;
}

Pruébalo en línea


Estoy bastante seguro de que (x>0?x:-(x))puede ser (x>0?x:-x).
Yytsi

Lamentablemente no, ya que el token x será reemplazado por, por ejemplo, x + .5 que solo obtendría -x + .5.
Anedar

Bien. Tenía una mentalidad donde la negación sin paréntesis volteó el letrero: D
Yytsi

Estrictamente hablando, ha utilizado el preprocesador C (que ciertamente es parte de C ++, pero también se comparte con otras variantes y descendientes C)
tucuxi

2

R, 131 110 bytes

Una función que toma los dos enteros, x,y como entradas y escribe la salida en stdout. La solución sigue el esquema de flujo de control de @Dennis, pero probablemente podría jugar golf.

EDITAR: Código actualizado basado en las sugerencias de @ JDL y guardado un montón de bytes.

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)}

Sin golf

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
}

1
Creo que algunas de las condiciones lógicas pueden acortarse: as.logical(-1)es TRUE, entonces X==0|Y==0puede volverse !X|!Y, y la condición if(X!=Y...)puede volverse if(X-Y). Además, si X==Yy X!=0luego Y!=0es redundante. En realidad, todas las !=0partes son redundantes; if(X!=0)es equivalente a if(X).
JDL

1
Además, dado que "el formato de E / S es bastante flexible", probablemente sea un juego justo con el que salga implícitamente en c(x,y)lugar de cat(x,y).
JDL

@JDL Esos son algunos consejos de golf muy útiles en los que nunca pensé, ¡muchas gracias! Se actualizó la respuesta.
Billywob

2

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

Acepta una matriz [x, y], la modifica in situ y la devuelve.

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

Cómo funciona

c=>(

Esta es una función de flecha de un solo parámetro con un returncuerpo conciso libre.

[x,y]=c

El parámetro se desestructura de inmediato en x y yvariables.

,

El operador de coma combina múltiples expresiones en una, utilizando el resultado de la última.

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

ise usa para diferenciar casos de incremento y decremento. Cuando xes mayor que y, estamos en el cuadrante inferior o derecho, y necesitamos avanzar en una dimensión ( i=1por coerción booleana a número). Del mismo modo, cuando estamos en la parte negativa de la división x = y diagonal. En todos los demás casos, incluido el origen, no se requiere ningún incremento ( i=0).

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

Usamos una expresión algo similar para controlar qué índice de matriz ajustar. Cuando estamos incrementar y no en los cuadrantes izquierdo o inferiores (o cuando estamos no incrementar y en la izquierda o la parte inferior), entonces el XOR bit a bit producirá 1y ajustará la y valor. Del mismo modo para cuando estamos en la división x = -y diagonal (incluido el origen). En todos los demás casos, el índice será 0( x ).

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

Cuando ies así 1, lo agregaremos al valor especificado. Cuando ies así 0, restaremos 1 del valor si y solo si no estamos en el origen. Este último se detecta al x|yproducir un valor distinto de cero, recortado a {0, 1} por coerción booleana, y la negación de inos permite utilizar OR bit a bit en lugar de lógico (ya que -1no tiene bits cero, está a salvo de modificaciones).

c

La matriz es la última, por lo que se devolverá.

Pruebas

† Variaciones

Podemos guardar dos bytes más omitiendo un valor de retorno significativo y usando solo la mutación de entrada:

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

… O podemos omitir la mutación de entrada y hacer que todas las variables sean locales para una función pura, al costo de seis bytes:

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

1

JavaScript (ES6), 80 76 bytes

(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])

1

Haskell, 53 bytes

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

Toma dos números, emite una tupla. Si el punto está en la sección este -x<=y<x, aumente la segunda coordenada en 1. De lo contrario, realice un ciclo de los cuadrantes girando el punto de entrada 90 grados, llamando a la función en él y luego girando hacia atrás.


1

Raqueta 191 bytes

(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)))])

Sin golf (traduciendo directamente las direcciones de las figuras al código sin usar ninguna fórmula intermedia):

(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
    ))

Pruebas:

(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) 

Salida:

'(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)

1

Actualmente , 16 bytes

Esto toma un número complejo como entrada y genera otro número complejo. Sugerencias de golf bienvenidas! Pruébalo en línea!

;`₧╦@/τ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.

0

Scala, 184 bytes

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)}

Sin golf:

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)
}

Explicación:

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
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.