Rotação Chebyshev

36

Considere uma grade regular, onde cada célula possui coordenadas inteiras. Podemos agrupar as células em "anéis" (em forma de quadrado), onde as células em cada anel têm a mesma distância Chebyshev (ou distância do tabuleiro de xadrez) da origem. Sua tarefa é pegar essa coordenada de célula e girá-la em uma posição no sentido anti-horário dentro de seu anel. Isso implementa o seguinte mapeamento:

insira a descrição da imagem aqui

Então, por exemplo, se a entrada for (3, -2)você deve enviar (3, -1). Observe que (0, 0)é a única entrada que deve mapear para si mesma.

Regras

O formato de E / S é bastante flexível. Você pode usar dois números individuais, um par / lista / matriz / tupla de números, um único número complexo, uma sequência contendo dois números etc.

Você pode assumir isso -128 < x,y < 128.

Você pode escrever um programa ou uma função e usar qualquer um dos nossos métodos padrão de recebimento de entrada e saída.

Você pode usar qualquer linguagem de programação , mas observe que essas brechas são proibidas por padrão.

Isso é , então a resposta mais curta e válida - medida em bytes - vence.

Casos de teste

(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
fonte
Podemos misturar os formatos de entrada e saída, por exemplo, pegar uma tupla e gerar um número complexo?
Dennis
@ Dennis sim, tudo bem.
Martin Ender

Respostas:

16

JavaScript (ES6), 60 59 bytes

Recebe entrada com sintaxe de curry (x)(y)e retorna uma matriz [new_x, new_y].

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

Como funciona

Nossa principal tarefa é determinar em que quadrante estamos, para sabermos em que direção devemos nos mover.

Podemos usar esta fórmula como uma primeira aproximação:

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

Aqui está o que temos:

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

Quase lá. Mas os cantos inferior esquerdo e inferior direito dos anéis são inválidos. Precisamos mudar a metade inferior da matriz em uma posição para a esquerda, para definir zcomo:

z = y < 0 ? x + 1 : x

E substituímos xpor znossa fórmula:

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

O que leva 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 

A matriz inteira agora está correta, exceto no caso especial [0, 0](sem movimento) que deve ser tratado separadamente.

Casos de teste

Arnauld
fonte
13

Geléia , 20 14 12 bytes

S;IṠN0n/¦Ạ¡+

Entrada e saída estão na forma de matrizes. Experimente online! ou verifique todos os casos de teste .

fundo

Para descobrir em que direção devemos nos mover, podemos observar a posição relativa do ponto inicial dos bissetores do quadrante x + y = 0 (azul) e x - y = 0 (vermelho).

diagrama

  • A origem é fixa. Avançamos adicionando [0, 0] ao ponto inicial.

  • Os pontos no triângulo superior - incluindo a bissetriz do primeiro quadrante - têm soma positiva e delta não negativo ( y - x ). Avançamos adicionando [-1, 0] ao ponto inicial.

  • Os pontos no triângulo mais à esquerda - incluindo a bissetriz do segundo quadrante - têm soma não positiva e delta positivo. Avançamos adicionando [0, -1] ao ponto inicial.

  • Os pontos no triângulo mais baixo - incluindo a bissetriz do terceiro quadrante - têm soma negativa e delta não positivo. Avançamos adicionando [1, 0] ao ponto inicial.

  • Os pontos no triângulo mais à direita - incluindo a bissetriz do quarto quadrante - têm soma não-negativa e delta negativo. Avançamos adicionando [0, 1] ao ponto inicial.

Para descobrir a direção correta, calculamos [-sign (x + y), -sign (y - x)] , que possui apenas nove resultados possíveis.

A tabela a seguir ilustra quais resultados devem ser mapeados para quais direções.

    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

Isso deixa três casos.

  • Se pelo menos um dos sinais for 0 , [Δx, Δy] = [-sinal (x + y), -sinal (yx)] .

  • Se os sinais forem iguais e diferentes de zero, [Δx, Δy] = [-sinal (x + y), 0] .

  • Se os sinais forem diferentes e diferentes de zero, [Δx, Δy] = [0, -sinal (yx)] .

Como 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].
Dennis
fonte
5

Pitão , 19 bytes

&Q+^.jZ1.RhycPQ.n0Z

Experimente online!

Tradução da minha resposta 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
fonte
Resposta parábola agradável!
tomsmeding
5

Python, 55 bytes

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

Detecta os quatro quadrantes diagonais e muda a coordenada apropriada.

xnor
fonte
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)

Isso é apenas verificar cada um desses quadrantes inclinados e modificar a entrada de acordo. Observe que os espaços são necessários, caso contrário, por exemplo, >-seria entendido como um operador (que não está definido).

Obrigado @nimi por remover mais alguns bytes!

flawr
fonte
,em vez de&& dentro do primeiro guarda, salva um byte. E então você pode mudar a segunda comparação -x<ypara outro byte.
N /
Obrigado, eu não estava ciente do ,!
flawr
4

Ruby, 68

A função Lambda recebe um número complexo como argumento, retorna um número complexo.

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

Giramos o ponto 90 graus 4 vezes multiplicando por i. Portanto, ele passa por todos os quatro quadrantes e seria devolvido inalterado - exceto pelo fato de modificá-lo quando estiver em um deles específico. O fato de sempre ser modificado no mesmo quadrante simplifica a modificação.

É mais fácil segui-lo se o alterarmos zquando estiver no quadrante do lado direito. neste caso, precisamos aumentar a coordenada y em 1 (por exemplo, adicionar ia z.)

Verificamos x.abs>=y.abscomparando os quadrados de xe y. Isso nos diz que o ponto está no quadrante direito ou esquerdo, não em cima ou em baixo. Para verificar se, de fato, está no quadrante do lado direito, verificamos ainda mais x>y(estritamente maior porque queremos excluir o caso x=yque pertence ao quadrante "superior".) Onde isso é verdade, adicionamos ia z.

Por razões de golfe, a adição inão é desejável. Em vez disso, modificamos o número quando ele está no quadrante inferior; nesse caso, temos que adicionar 1 à xcoordenada (adicionar 1 a z.) Nesse caso, testamos se y*y>=x*xa verificação está no quadrante superior ou inferior. Para garantir ainda mais que ele esteja no quadrante inferior, precisamos verificar y<-x(excluindo estritamente o caso do canto inferior direito, onde y=-x.)

Uma vantagem dessa verificação é que não há um caso especial para a coordenada 0,0. Infelizmente, verificou-se que mover o ponto pode deslocá-lo para um quadrante diferente e isso significa que um segundo movimento deve ser suprimido, caso esse quadrante seja verificado novamente, o que provavelmente nega a vantagem.

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

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

No programa de teste

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

A imagem a seguir mostra (azul) a área onde x*x>=y*y, (amarelo) a área onde y<-xe (verde) a interseção dessas, que é a região em que a transformação correta é a adição de 1 a z.

insira a descrição da imagem aqui

Level River St
fonte
1
Desculpe, não estou seguindo a explicação. Você se importaria de adicionar um exemplo ou um diagrama?
Martin Ender
Adicionada a explicação de Martin. Essa foi uma abordagem interessante, mas devido à necessidade de suprimir o movimento duplo de pontos que mudam de quadrante na primeira vez em que se movem, não ficou tão elegante quanto eu esperava.
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 e saída complexas. Para testar o ponto no quadrante diagonal inferior, primeiro gire-o 135 no sentido anti-horário para mover esse quadrante para o quadrante padrão (x> 0, y> 0) e teste se o resultado não possui símbolo de menos na representação da string. Subtrair 1 primeiro cuida da condição de contorno.

Se não estiver nesse quadrante, gire o problema inteiro 90 graus. A entrada é zero e é manipulada especialmente para a própria saída.

Outras tentativas com números complexos:

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

Mathematica, 34 bytes

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

Isso define um operador unário ±que pega e retorna um número complexo cujos componentes representam xe y.

Agora que Lynn revelou a solução complexa de números e Dennis superou minha pontuação, não me sinto tão mal por postar minha implementação referenciada no golfe. :) (Ele é praticamente idêntico à resposta de Lynn.)

Martin Ender
fonte
Isso ajudaria? ± 0 = 0 ⁢ ± z_: = z + I ^ ⌊ 2 ⁢ Arg @ z / Pi + 3/2 ⌋ (talvez com um carácter diferente para os suportes de chão)
DavidC
@DavidC infelizmente não, porque então eu teria que usar a codificação UTF-8 e, em seguida, o ± custaria 2 bytes cada.
Martin Ender
Isso não seria 4 bytes em vez de 7, dando assim uma economia de 3 bytes?
DavidC 16/10
@ DavidD não, os colchetes seriam de 3 bytes cada.
Martin Ender
Eu não estava ciente disso. Mas, mesmo assim, você ainda deve economizar 1 byte.
DavidC 16/10
3

MATL , 19 17 bytes

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

Isso usa números complexos como entrada e saída.

Experimente online! Ou verifique todos os casos de teste .

Explicação

Vamos dar -127+42jum exemplo como exemplo.

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
fonte
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 pelo comentário de Xnor

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

Usa o mesmo tipo de desigualdade que minha outra resposta, mas de uma maneira diferente.

No programa de teste

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
fonte
A dtarefa vale a pena? Parece que você pode apenas comparar x*x>y*y.
Xnor
@Xnor, infelizmente, Ruby requer um espaço entre y*ye, ?portanto, é exatamente o mesmo comprimento. Eu o incluí porque acho que seu caminho é, de certa forma, mais ordenado. Eu acho que Ruby está tentando passar como y?qual seria um nome de função legal.
Level River St
3

Julia, 38 34 bytes

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

Dennis salvou quatro bytes. Obrigado!

Experimente online!

Lynn
fonte
Parece que eu misturei o comportamento do int em diferentes versões da Julia (que, em minha defesa, é terrivelmente inconsistente). Julia 0.4 (a versão no TIO) arredonda as metades para o par, então isso não funcionará como está. Na Julia 0.3, você pode usar int(2angle(z)/pi+5)a mesma contagem de bytes (potências negativas causam um erro por qualquer motivo).
Dennis
Além disso, você pode salvar um byte !z=z+(z!=0)im^...em todas as versões.
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;

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

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

Experimente online

Anedar
fonte
Tenho certeza de que (x>0?x:-(x))pode ser (x>0?x:-x).
Yytsi 17/10/2016
Infelizmente, não, pois o token x será substituído por, por exemplo, x + .5, que obteria -x + .5.
Anedar
Bem. Eu tinha uma mentalidade em que a negação sem parênteses girava o sinal: D
Yytsi 17/10/16
Estritamente falando, você usou o C pré-processador (que é reconhecidamente uma parte do C ++, mas também é compartilhada com outro C variantes e descendentes)
tucuxi
2

R, 131 110 bytes

Uma função que pega os dois números inteiros, x,ycomo entradas e grava a saída em stdout. A solução segue o esquema de controle de fluxo da @Dennis, mas provavelmente poderia ser jogada no golfe.

EDIT: Código atualizado com base nas sugestões do @ JDL e salvou um monte 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)}

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
fonte
1
Eu acho que algumas das condições lógicas podem ser reduzidas: as.logical(-1)é TRUE, X==0|Y==0pode se tornar !X|!Ye a condição if(X!=Y...)pode se tornar if(X-Y). Além disso, se X==Ye X!=0então Y!=0for redundante. Na verdade, todas as !=0partes são redundantes; if(X!=0)é equivalente a if(X).
JDL
1
Além disso, como "o formato de E / S é bastante flexível", provavelmente é um jogo justo produzir implicitamente com e c(x,y)não cat(x,y).
JDL
@JDL Essas são algumas dicas muito úteis sobre golfe em que nunca pensei, muito obrigado! Atualizado a resposta.
21416 Billywob
2

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

Aceita uma matriz [x, y], modifica-a no local e retorna-a.

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

Como funciona

c=>(

Esta é uma função de seta de parâmetro único com um returncorpo conciso e gratuito.

[x,y]=c

O parâmetro é imediatamente desestruturado em xe yvariáveis.

,

O operador vírgula combina várias expressões em uma, usando o resultado da última.

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

ié usado para diferenciar casos de incremento e decremento. Quando xé maior que y, estamos no quadrante inferior ou direito e precisamos avançar em uma dimensão ( i=1por coerção entre booleanos e números). Da mesma forma, quando estamos na parte negativa da divisão x = y diagonal. Em todos os outros casos - incluindo a origem - nenhum incremento é necessário ( i=0).

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

Usamos uma expressão um pouco semelhante para controlar qual índice de matriz ajustar. Quando estamos incrementando e não nos quadrantes para a esquerda ou inferior (ou quando são não incrementando e no lado esquerdo ou inferior), em seguida, o XOR bit a bit vai produzir 1e que irá ajustar o y valor. Da mesma forma, quando estamos dividindo a diagonal x = -y (incluindo a origem). Em todos os outros casos, o índice será 0( x ).

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

Quando ifor 1, adicionaremos ao valor especificado. Quando ié 0, subtrairemos 1 do valor se e somente se não estivermos na origem. O último é detectado x|yproduzindo um valor diferente de zero, recortado em {0, 1} por coerção booleana, e a negação de inos permite usar OR bit a bit em vez de lógico (já -1que não tem zero bits, ele está protegido contra modificações).

c

A matriz é a última e, portanto, será retornada.

Teste

† Variações

Nós podemos salvar mais dois bytes saltando um valor de retorno significativo e utilizando unicamente a mutação de entrada:

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

… Ou podemos pular a mutação de entrada e tornar todas as variáveis ​​locais para uma função pura, ao custo 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)
gibson042
fonte
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])
Neil
fonte
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 dois números, gera uma tupla. Se o ponto estiver na seção leste -x<=y<x, aumente a segunda coordenada em 1. Caso contrário, circule os quadrantes girando o ponto de entrada 90 graus, chamando a função nele e depois girando para trás.

xnor
fonte
1

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

Ungolfed (traduzindo diretamente as direções das figuras para o código sem usar nenhuma fórmula intermediária):

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

Teste:

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

Saída:

'(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
fonte
1

Na verdade , 16 bytes

Isso recebe um número complexo como entrada e gera outro número complexo. Sugestões de golfe são bem-vindas! Experimente online!

;`₧╦@/τ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
fonte
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)}

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

Explicação:

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
fonte