Чебышевская ротация

36

Рассмотрим регулярную сетку, где каждая ячейка имеет целочисленные координаты. Мы можем сгруппировать ячейки в (квадратные) «кольца», где ячейки в каждом кольце имеют одинаковое расстояние Чебышева (или расстояние шахматной доски) от начала координат. Ваша задача - взять такую ​​координату ячейки и повернуть эту ячейку на одну позицию против часовой стрелки внутри своего кольца. Это реализует следующее отображение:

введите описание изображения здесь

Так, например, если ввод, (3, -2)вы должны вывести (3, -1). Обратите внимание, что (0, 0)это единственный вход, который должен отображаться на себя.

правила

Формат ввода / вывода довольно гибкий. Вы можете использовать два отдельных числа: пара / список / массив / кортеж чисел, одно комплексное число, строка, содержащая два числа и т. Д.

Вы можете предположить это -128 < x,y < 128.

Вы можете написать программу или функцию и использовать любой из наших стандартных методов получения ввода и предоставления вывода.

Вы можете использовать любой язык программирования , но учтите, что эти лазейки по умолчанию запрещены.

Это , поэтому самый короткий действительный ответ - измеренный в байтах - выигрывает.

Тестовые случаи

(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)
Мартин Эндер
источник
Можем ли мы смешать формат ввода и вывода, например, взять кортеж и вывести комплексное число?
Деннис
@ Денис, да, все в порядке.
Мартин Эндер

Ответы:

16

JavaScript (ES6), 60 59 байт

Принимает ввод с синтаксисом карри (x)(y)и возвращает массив [new_x, new_y].

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

Как это работает

Наша главная задача - определить, в каком квадранте мы находимся, чтобы мы знали, в каком направлении двигаться.

Мы можем использовать эту формулу в первом приближении:

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

Вот что мы получаем:

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

Почти готово. Но нижний левый и правый нижний углы колец недействительны. Нам нужно сместить нижнюю половину матрицы на одну позицию влево, поэтому мы определяем zкак:

z = y < 0 ? x + 1 : x

И мы заменим xс zнашей формулой:

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

Что приводит к:

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 

Теперь вся матрица верна, за исключением особого случая [0, 0](вообще без движения), который должен рассматриваться отдельно.

Контрольные примеры

Arnauld
источник
13

Желе , 20 14 12 байт

S;IṠN0n/¦Ạ¡+

Ввод и вывод в виде массивов. Попробуйте онлайн! или проверьте все контрольные примеры .

Задний план

Чтобы выяснить, в каком направлении мы должны двигаться, мы можем наблюдать относительное положение начальной точки к биссектрисам квадранта x + y = 0 (синий) и x - y = 0 (красный).

диаграмма

  • Происхождение исправлено. Мы продвигаемся, добавляя [0, 0] к начальной точке.

  • Точки в самом верхнем треугольнике - включая биссектрису первого квадранта - имеют положительную сумму и неотрицательную дельту ( y - x ). Мы продвигаемся, добавляя [-1, 0] к начальной точке.

  • Точки в крайнем левом треугольнике, включая биссектрису второго квадранта, имеют неположительную сумму и положительную дельту. Продвигаемся, добавляя [0, -1] к начальной точке.

  • Точки в самом нижнем треугольнике - включая биссектрису третьего квадранта - имеют отрицательную сумму и неположительную дельту. Мы добавляем [1, 0] к начальной точке.

  • Точки в самом правом треугольнике, включая биссектрису четвертого квадранта, имеют неотрицательную сумму и отрицательную дельту. Мы продвигаемся, добавляя [0, 1] к начальной точке.

Чтобы выяснить правильное направление, мы вычисляем [-sign (x + y), -sign (y - x)] , который имеет только девять возможных результатов.

В следующей таблице показано, какие результаты должны быть сопоставлены с какими направлениями.

    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

Это оставляет три случая.

  • Если хотя бы один из знаков равен 0 , [Δx, Δy] = [-sign (x + y), -sign (yx)] .

  • Если знаки равны и отличны от нуля, [Δx, Δy] = [-sign (x + y), 0] .

  • Если знаки разные и отличны от нуля, [Δx, Δy] = [0, -sign (yx)] .

Как это работает

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

Pyth , 19 байт

&Q+^.jZ1.RhycPQ.n0Z

Попробуйте онлайн!

Перевод моего ответа Юлии :

&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
Линн
источник
Хороший ответ на параболу!
Томсминг
5

Python, 55 байт

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

Обнаруживает четыре диагональных квадранта и сдвигает соответствующую координату.

XNOR
источник
4

Haskell, 77 71 69 байт

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)

Это просто проверка каждого из этих наклоненных квадрантов и изменение входа соответственно. Обратите внимание, что пробелы необходимы, в противном случае, например, >-будет рассматриваться как оператор (который не определен).

Спасибо @nimi за удаление еще нескольких байтов!

flawr
источник
,вместо того, чтобы в&& пределах первого охранника сохраняет байт. И тогда вы можете переключить второе сравнение -x<yна другой байт.
Ними
Спасибо, я не знал об этом ,!
flawr
4

Руби, 68

Лямбда-функция принимает комплексное число в качестве аргумента, возвращает комплексное число.

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

Мы поворачиваем точку на 90 градусов 4 раза, умножая на i. Поэтому он проходит через все 4 квадранта и будет возвращен без изменений - за исключением того факта, что мы изменяем его, когда он входит в конкретный из них. Тот факт, что он всегда изменяется в одном и том же квадранте, упрощает модификацию.

Проще всего следовать, если мы изменим его, zкогда оно находится в правом квадранте. в этом случае нам нужно увеличить координату y на 1 (т.е. добавить iк z.)

Мы проверяем x.abs>=y.abs, сравнивая квадраты xи y. Это говорит нам о том, что точка находится в правом или левом квадранте, а не сверху или снизу. Чтобы проверить это на самом деле в правом квадранте мы дополнительно проверить , что x>y(строго больше , потому что мы хотим , чтобы исключить случай , x=yкоторый относится к «верхнему» квадранту.) Если это верно , мы добавим iк z.

По причинам, связанным с игрой в гольф, добавление iнежелательно. Вместо этого мы модифицируем число, когда оно находится в нижнем квадранте, и в этом случае мы должны добавить 1 к xкоординате (добавить 1 к z.). В этом случае мы проверяем, y*y>=x*xчтобы убедиться, что оно находится в верхнем или нижнем квадранте. Чтобы в дальнейшем убедиться, что он находится в нижнем квадранте, нам нужно проверить y<-x(строго исключая случай с правым нижним углом, где y=-x.)

Преимущество этой проверки в том, что для координаты 0,0 нет особого случая. К сожалению, было обнаружено, что перемещение точки может сместить ее в другой квадрант, и это означает, что второе движение должно быть подавлено, если этот квадрант будет проверен снова, что, вероятно, сводит на нет преимущество.

Пример 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.

Пример 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.

В тестовой программе

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)

схема

На следующем изображении показана (синяя) область, где x*x>=y*y(желтая) - область, где y<-xи (зеленая) - пересечение этих областей, то есть область, где правильное преобразование представляет собой сложение 1 с z.

введите описание изображения здесь

Уровень реки St
источник
1
Извините, я не следую объяснениям. Не могли бы вы добавить пример или диаграмму?
Мартин Эндер
Добавлено объяснение @Martin. Это был интересный подход, но из-за необходимости подавлять двойное движение точек, которые меняют квадрант при первом перемещении, это оказалось не так элегантно, как я надеялся.
Уровень Ривер-Стрит
4

Python, 52 байта

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

Комплексный ввод и вывод. Чтобы проверить, находится ли точка в нижнем диагональном квадранте, сначала поверните ее на 135 против часовой стрелки, чтобы переместить этот квадрант в (x> 0, y> 0) стандартный квадрант, и проверьте, нет ли в результате символа минус в строковом представлении. Вычитание 1 сначала учитывает граничное условие.

Если это не в том квадранте, поверните всю проблему на 90 градусов. Ввод нуля специально обрабатывается для вывода самого себя.

Другие попытки с комплексными числами:

## 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
источник
3

Mathematica, 34 байта

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

Это определяет унарный оператор, ±который принимает и возвращает комплексное число, компоненты которого представляют xи y.

Теперь, когда Линн представила решение для комплексных чисел, а Деннис побил мой счет, я не чувствую себя так плохо, разместив свою реализацию с привязкой к гольфу. :) (Оказывается, он практически идентичен ответу Линн.)

Мартин Эндер
источник
Это поможет? ± 0 = 0 ⁢ ± z_: = z + I ^ ⌊ 2 ⁢ Arg @ z / Pi + 3/2 ⌋ (возможно, с другим символом для скобок пола)
DavidC
@DavidC, к сожалению, не потому, что тогда мне пришлось бы использовать кодировку UTF-8, и тогда ± будет стоить 2 байта каждый.
Мартин Эндер
Разве это не 4 байта вместо 7, что дает экономию в 3 байта?
DavidC
@DavidC нет, напольные скобки будут по 3 байта каждый.
Мартин Эндер
Я не знал об этом. Но даже в этом случае вы все равно должны сохранять 1 байт.
DavidC
3

MATL , 19 17 байт

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

Это использует комплексные числа в качестве ввода и вывода.

Попробуйте онлайн! Или проверьте все тестовые случаи .

объяснение

Давайте возьмем входные данные -127+42jв качестве примера.

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

Рубин, 51 байт

Оригинальная форма

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

Альтернативная форма для комментария Xnor

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

Используется тот же тип неравенства, что и в моем другом ответе, но по-другому.

В тестовой программе

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)
Уровень реки St
источник
Стоит ли это dназначение? Похоже, вы можете просто сравнить x*x>y*y.
xnor
@Xnor К сожалению, Ruby требуется пробел между ними, y*yи ?поэтому он точно такой же длины. Я включил это, поскольку я думаю, что ваш путь в некотором смысле аккуратнее. Я думаю, что Ruby пытается передать его как правильное y?имя функции.
Уровень River St
3

Юлия, 38 34 байта

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

Деннис спас четыре байта. Благодарность!

Попробуйте онлайн!

Линн
источник
Похоже, я перепутал поведение int в разных версиях Julia (что, в мою защиту, крайне противоречиво). Юлия 0.4 (версия на TIO) округляет половину до четного, так что это не будет работать как есть. В Julia 0.3 вы можете использовать int(2angle(z)/pi+5)для одного и того же числа байтов (отрицательные силы вызывают ошибку по любой причине).
Деннис
Кроме того, вы можете сохранить байт !z=z+(z!=0)im^...во всех версиях.
Деннис
2

C ++, 94 байта

#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

Использование:

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

Попробуйте онлайн

Anedar
источник
Я уверен, что это (x>0?x:-(x))может быть (x>0?x:-x).
Yytsi
К сожалению, нет, поскольку токен x будет заменен, например, x + .5, который просто получит -x + .5.
Анедар
Хорошо. У меня было мышление, где отрицание без скобок перевернуло знак: D
Yytsi
Строго говоря, вы использовали препроцессор C (который по общему признанию является частью C ++, но также используется совместно с другими вариантами и потомками C)
tucuxi
2

R 131 131 байт

Функция, которая принимает два целых числа в x,yкачестве входных данных и записывает выходные данные в стандартный вывод. Решение соответствует схеме управления потоком @Dennis, но, вероятно, может быть в гольфе.

РЕДАКТИРОВАТЬ: Обновил код на основе предложений @ JDL и сохранил кучу байтов.

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
источник
1
Я думаю, что некоторые из логических условий могут быть сокращены: as.logical(-1)есть TRUE, X==0|Y==0может стать !X|!Y, и условие if(X!=Y...)может стать if(X-Y). Кроме того, если X==Yи X!=0тогда Y!=0является избыточным. На самом деле, все !=0части являются избыточными; if(X!=0)эквивалентно if(X).
JDL
1
Кроме того, учитывая, что «формат ввода / вывода довольно гибкий», вероятно, будет справедливо выводить неявно с помощью c(x,y)вместо cat(x,y).
JDL
@JDL Вот некоторые очень полезные советы по гольфу, о которых я никогда не думал, спасибо большое! Обновил ответ.
Billywob
2

JavaScript (ES6), 57 байт (55–63 †)

Принимает массив [x, y], изменяет его на месте и возвращает его.

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

Как это работает

c=>(

Это функция стрелок с одним параметром и returnсвободным кратким телом.

[x,y]=c

Параметр немедленно деструктурированный в xи yпеременные.

,

Оператор запятой объединяет несколько выражений в одно, используя результат последнего.

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

iиспользуется для различения случаев приращения и уменьшения. Когда xбольше чем y, мы находимся либо в нижнем, либо в правом квадранте, и нам нужно продвинуться в одном измерении ( i=1путем принуждения булево-числовое). Точно так же, когда мы находимся на отрицательной части делительной диагонали x = y . Во всех других случаях, включая происхождение, увеличение не требуется ( i=0).

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

Мы используем несколько похожее выражение для управления тем, какой индекс массива настраивать. Когда мы увеличиваем, а не в левом или нижнем квадрантах (или когда мы не увеличиваем, а в левом или нижнем), то получится побитовое XOR, 1и мы отрегулируем значение y . Аналогично, когда мы находимся на делительной диагонали x = -y (включая начало координат). Во всех остальных случаях индекс будет 0( х ).

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

Когда iесть 1, мы добавим его к указанному значению. Когда iесть 0, мы вычтем 1 из значения тогда и только тогда, когда мы не в источнике. Последнее обнаруживается путем x|yвыдачи ненулевого значения, обрезается до {0, 1} с помощью логического принуждения, и отрицание iпозволяет нам использовать побитовое ИЛИ вместо логического (так -1как не имеет нулевых битов, оно безопасно для модификации).

c

Массив является последним, поэтому он будет возвращен.

тестирование

† Вариации

Мы можем сохранить еще два байта, пропуская содержательное возвращаемое значение и использование только мутации ввода:

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

… Или мы можем пропустить входную мутацию и сделать все переменные локальными для чистой функции ценой шести байтов:

([x,y],i=x>y|x==y&x<0,c=[x,y])=>(c[i^x<-y|x==-y]-=-i|!!(x|y),c)
gibson042
источник
1

JavaScript (ES6), 80 76 байт

(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 байта

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

Принимает два числа, выводит кортеж. Если точка находится в восточной части -x<=y<x, увеличьте вторую координату на 1. В противном случае циклически переключайте квадранты, поворачивая входную точку на 90 градусов, вызывая функцию на ней, затем поворачивая назад.

XNOR
источник
1

Ракетка 191 байт

(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 (прямой перевод указания рисунка в код без использования какой-либо промежуточной формулы):

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

Тестирование:

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

Выход:

'(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
источник
1

На самом деле , 16 байтов

Это берет комплексное число как ввод и выводит другое комплексное число. Предложения по игре в гольф приветствуются! Попробуйте онлайн!

;`₧╦@/τ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
источник
0

Scala, 184 байта

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

Объяснение:

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
источник