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


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)

Чи можемо ми змішати вхідний і вихідний формати, наприклад, взяти кортеж і вивести складне число?
Денніс

@Dennis так, це добре.
Мартін Ендер

Відповіді:


16

JavaScript (ES6), 60 59 байт

Бере введення з синтаксисом currying (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](зовсім не рухається), який слід вирішувати окремо.

Тестові справи


13

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

S;IṠN0n/¦Ạ¡+

Вхід і вихід у вигляді масивів. Спробуйте в Інтернеті! або перевірити всі тестові випадки .

Фон

Щоб зрозуміти, в якому напрямку ми повинні рухатись, ми можемо спостерігати відносне положення вихідної точки до бісектрис квадрату x + y = 0 (синій) та x - y = 0 (червоний).

diagram

  • Походження фіксовано. Заздалегідь додаємо [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] = [-знак (x + y), -sign (yx)] .

  • Якщо знаки рівні і не нульові, [Δx, Δy] = [-знак (x + y), 0] .

  • Якщо знаки різні і не нульові, [Δx, Δy] = [0, -знак (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

Пітон, 55 байт

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

Виявляє чотири діагональні квадранти і зміщує відповідну координату.


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 за видалення ще кількох байтів!


,замість того, щоб у&& межах першого охоронця зберігається байт. І тоді ви можете переключити друге порівняння на -x<yінший байт.
німі

Дякую, я не знав про це ,!
невдача

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.

enter image description here


1
Вибачте, я не стежу за поясненнями. Ви не проти додати приклад чи діаграму?
Мартін Ендер

@Martin додано пояснення. Це був цікавий підхід, але через необхідність придушити подвійний рух точок, які змінюють квадрант в перший раз, коли вони рухаються, він не вийшов настільки елегантним, як я сподівався.
Рівень річки Св.

4

Пітон, 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

3

Математика, 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, на жаль, не тому, що тоді мені доведеться використовувати кодування 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)

Чи dдоручення варто? Схоже, ви можете просто порівняти x*x>y*y.
xnor

@Xnor, на жаль, Ruby потрібен пробіл між собою, y*yі ?тому він точно такої ж довжини. Я включив це, як я думаю, ваш шлях в чомусь охайніший. Я думаю, що Рубі намагається передати це так, як y?це було б юридичною назвою функції.
Рівень річки Св

3

Джулія, 38 34 байт

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

Денніс врятував чотири байти. Спасибі!

Спробуйте в Інтернеті!


Схоже , я змішалися Int «s поведінку в різних версіях Юлі (яка, в свою захист, є дуже непослідовно). Julia 0.4 (версія на TIO) округляє половини до рівних, тому це не працюватиме так, як є. У Джулії 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;

Безголівки:

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

Спробуйте в Інтернеті


Я майже впевнений, що це (x>0?x:-(x))може бути (x>0?x:-x).
Yytsi

На жаль, ні, оскільки маркер x буде замінений, наприклад, x + .5, який просто отримає -x + .5.
Анедар

Добре. У мене був розум, коли заперечення без дужок перевертало знак: D
Yytsi

Власне кажучи, ви використовували C препроцесор (який, правда, є частиною C ++, але він також поділяється з іншими C-варіантами та нащадками)
tucuxi

2

R, 131 110 байт

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

EDIT: оновлений код на основі пропозицій @ 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)}

Безумовно

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
Я думаю, що деякі логічні умови можна скоротити: 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( x ).

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

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 градусів, викликаючи функцію на ній, а потім обертаючи назад.


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)

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.

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

Безголівки:

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
}
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.