Rotasi Chebyshev

36

Pertimbangkan kisi biasa, di mana setiap sel memiliki koordinat bilangan bulat. Kita dapat mengelompokkan sel menjadi "cincin" (berbentuk persegi) di mana sel-sel di setiap cincin memiliki jarak Chebyshev yang sama (atau jarak papan catur) dari titik asalnya. Tugas Anda adalah untuk mengambil sel yang terkoordinasi dan memutar sel itu dengan satu posisi berlawanan arah jarum jam di dalam cincinnya. Ini mengimplementasikan pemetaan berikut:

masukkan deskripsi gambar di sini

Jadi misalnya jika inputnya adalah (3, -2)Anda harus output (3, -1). Perhatikan bahwa (0, 0)hanya input yang harus dipetakan ke dirinya sendiri.

Aturan

Format I / O cukup fleksibel. Anda dapat menggunakan dua angka individual, pasangan / daftar / larik / tupel angka, satu angka kompleks, string yang berisi dua angka, dll.

Anda mungkin menganggap itu -128 < x,y < 128.

Anda dapat menulis sebuah program atau fungsi dan menggunakan salah satu metode standar kami untuk menerima input dan memberikan output.

Anda dapat menggunakan bahasa pemrograman apa pun , tetapi perhatikan bahwa celah ini dilarang secara default.

Ini adalah , sehingga jawaban terpendek yang valid - diukur dalam byte - menang.

Uji Kasus

(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
sumber
Bisakah kita mencampur format input dan output, misalnya, mengambil tuple dan mengeluarkan bilangan kompleks?
Dennis
@ Dennis ya tidak apa-apa.
Martin Ender

Jawaban:

16

JavaScript (ES6), 60 59 byte

Mengambil input dengan sintaks currying (x)(y)dan mengembalikan array [new_x, new_y].

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

Bagaimana itu bekerja

Tugas utama kita adalah menentukan kuadran mana kita berada, sehingga kita tahu ke arah mana kita akan bergerak.

Kita bisa menggunakan rumus ini sebagai perkiraan pertama:

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

Inilah yang kami dapatkan:

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

Hampir sampai. Tetapi sudut kiri bawah dan kanan bawah cincin tidak valid. Kita perlu menggeser bagian bawah matriks dengan satu posisi ke kiri, jadi kami mendefinisikan zsebagai:

z = y < 0 ? x + 1 : x

Dan kami ganti xdengan zdalam rumus kami:

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

Yang mengarah ke:

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 

Seluruh matriks sekarang benar, kecuali untuk kasus khusus [0, 0](tidak bergerak sama sekali) yang harus ditangani secara terpisah.

Uji kasus

Arnauld
sumber
13

Jelly , 20 14 12 byte

S;IṠN0n/¦Ạ¡+

Input dan output dalam bentuk array. Cobalah online! atau verifikasi semua kasus uji .

Latar Belakang

Untuk mengetahui ke arah mana kita harus bergerak, kita dapat mengamati posisi relatif dari titik awal ke kuadran kuadrat x + y = 0 (biru) dan x - y = 0 (merah).

diagram

  • Asal sudah pasti. Kami maju dengan menambahkan [0, 0] ke titik awal.

  • Poin dalam segitiga paling atas - termasuk garis-bagi kuadran pertama - memiliki jumlah positif dan delta non-negatif ( y - x ). Kami maju dengan menambahkan [-1, 0] ke titik awal.

  • Poin dalam segitiga paling kiri - termasuk garis-bagi kuadran kedua - memiliki jumlah non-positif dan delta positif. Kami maju dengan menambahkan [0, -1] ke titik awal.

  • Poin dalam segitiga paling bawah - termasuk garis-empat kuadran ketiga - memiliki jumlah negatif dan delta tidak positif. Kami maju dengan menambahkan [1, 0] ke titik awal.

  • Poin di segitiga paling kanan - termasuk garis-empat kuadran keempat - memiliki jumlah non-negatif dan delta negatif. Kami maju dengan menambahkan [0, 1] ke titik awal.

Untuk mengetahui arah yang benar, kami menghitung [-sign (x + y), -sign (y - x)] , yang hanya memiliki sembilan kemungkinan hasil.

Tabel berikut menggambarkan hasil mana yang harus dipetakan ke arah mana.

    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

Ini menyisakan tiga kasus.

  • Jika setidaknya salah satu tanda adalah 0 , [Δx, Δy] = [-sign (x + y), -sign (yx)] .

  • Jika tanda-tandanya sama dan tidak nol, [Δx, Δy] = [-sign (x + y), 0] .

  • Jika tanda-tandanya berbeda dan bukan nol, [Δx, Δy] = [0, -sign (yx)] .

Bagaimana itu bekerja

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
sumber
5

Pyth , 19 byte

&Q+^.jZ1.RhycPQ.n0Z

Cobalah online!

Terjemahan dari jawaban Julia saya :

&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
sumber
Jawaban parabola yang bagus!
mulai
5

Python, 55 byte

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

Mendeteksi empat kuadran diagonal, dan menggeser koordinat yang sesuai.

Tidak
sumber
4

Haskell, 77 71 69 byte

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)

Ini hanya memeriksa setiap kuadran yang dimiringkan, dan memodifikasi input yang sesuai. Perhatikan bahwa spasi diperlukan, jika tidak mis >-akan dipahami sebagai operator (yang tidak didefinisikan).

Terima kasih @nimi karena telah menghapus beberapa byte lagi!

cacat
sumber
,bukannya&& dalam penjaga pertama menyimpan byte. Dan kemudian Anda dapat mengganti perbandingan kedua ke -x<ybyte lain.
nimi
Terima kasih, saya tidak tahu ,!
flawr
4

Ruby, 68

Fungsi Lambda mengambil bilangan kompleks sebagai argumen, mengembalikan bilangan kompleks.

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

Kami memutar titik melalui 90 derajat 4 kali dengan mengalikannya dengan i. Karena itu ia melewati keempat kuadran, dan akan dikembalikan tidak berubah - kecuali untuk fakta kami memodifikasinya ketika berada di salah satu kuadran tertentu. Fakta bahwa selalu dimodifikasi di kuadran yang sama menyederhanakan modifikasi.

Paling mudah untuk diikuti jika kita mengubahnya zketika berada di kuadran kanan. dalam hal ini kita perlu meningkatkan y koordinat oleh 1 (yaitu menambahkan ike z.)

Kami memeriksa x.abs>=y.absdengan membandingkan kuadrat dari xdan y. Ini memberitahu kita bahwa masalahnya ada di kuadran kanan atau kiri, bukan atas atau bawah. Untuk memeriksanya sebenarnya di kuadran kanan, kami selanjutnya memeriksa bahwa x>y(benar-benar lebih besar karena kami ingin mengecualikan kasing x=yyang berada di kuadran "atas"). Di mana hal ini benar, kami tambahkan ikez .

Untuk alasan bermain golf, menambahkan itidak diinginkan. Alih-alih, kami memodifikasi nomor ketika berada di kuadran bawah, dalam hal ini kami harus menambahkan 1 ke xkoordinat (tambahkan 1 ke z.) Dalam hal ini kami menguji bahwa y*y>=x*xuntuk memeriksa itu di kuadran atas atau bawah. Untuk lebih memastikannya di kuadran bawah kita perlu memeriksa y<-x(tidak termasuk kasus sudut kanan bawah mana y=-x.)

Keuntungan dari pemeriksaan ini adalah tidak ada kasus khusus untuk koordinat 0,0. Sayangnya ditemukan bahwa memindahkan titik dapat menggesernya ke kuadran yang berbeda dan ini berarti bahwa gerakan kedua harus ditekan jika kuadran itu diperiksa lagi, yang mungkin meniadakan keuntungan.

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

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

Dalam program uji

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)

Diagram

Gambar berikut menunjukkan (biru) area di mana x*x>=y*y, (kuning) area di mana y<-xdan (hijau) persimpangan ini, yang merupakan wilayah di mana transformasi yang benar adalah penambahan 1 ke z.

masukkan deskripsi gambar di sini

Level River St
sumber
1
Maaf, saya tidak mengikuti penjelasan. Maukah Anda menambahkan contoh atau diagram?
Martin Ender
Penjelasan @Martin ditambahkan. Ini adalah pendekatan yang menarik tetapi karena kebutuhan untuk menekan gerakan ganda poin yang mengubah kuadran saat pertama kali mereka pindah, itu tidak menjadi elegan seperti yang saya harapkan.
Level River St
4

Python, 52 byte

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

Input dan output yang kompleks. Untuk menguji titik berada di kuadran diagonal bawah, pertama putar 135 berlawanan arah jarum jam untuk memindahkan kuadran itu ke kuadran standar (x> 0, y> 0), dan uji jika hasilnya tidak memiliki simbol minus dalam representasi string. Mengurangkan 1 pertama merawat kondisi batas.

Jika tidak ada di kuadran itu, putar seluruh masalah 90 derajat. Input nol ditangani khusus untuk output itu sendiri.

Upaya lain dengan bilangan kompleks:

## 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
Tidak
sumber
3

Mathematica, 34 byte

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

Ini mendefinisikan operator unary ±yang mengambil dan mengembalikan bilangan kompleks yang komponennya mewakili xdan y.

Sekarang Lynn telah mengungkapkan solusi bilangan kompleks dan Dennis telah mengalahkan skor saya, saya tidak merasa begitu buruk untuk memposting implementasi referensi golf saya. :) (Ternyata hampir identik dengan jawaban Lynn.)

Martin Ender
sumber
Apakah ini membantu? ± 0 = 0 ⁢ ± z_: = z + I ^ ⌊ 2 ⁢ Arg @ z / Pi + 3/2 ⌋ (mungkin dengan arang yang berbeda untuk kurung lantai)
DavidC
@ DavidvidC sayangnya bukan karena saya harus menggunakan pengkodean UTF-8 dan kemudian ± akan dikenakan biaya masing-masing 2 byte.
Martin Ender
Bukankah itu 4 byte, bukan 7, sehingga memberikan ekonomi 3 byte?
DavidC
@ Davidc tidak, kurung lantai akan masing-masing 3 byte.
Martin Ender
Saya tidak menyadarinya. Tapi, meski begitu, Anda masih harus menyimpan 1 byte.
DavidC
3

MATL , 19 17 byte

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

Ini menggunakan bilangan kompleks sebagai input dan output.

Cobalah online! Atau verifikasi semua kasus uji .

Penjelasan

Mari kita ambil input -127+42jsebagai contoh.

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
sumber
3

Ruby, 51 byte

Bentuk asli

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

Formulir alternatif per komentar Xnor

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

Menggunakan jenis ketidaksetaraan yang sama dengan jawaban saya yang lain, tetapi dengan cara yang berbeda.

Dalam program uji

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
sumber
Apakah dtugas itu sepadan? Sepertinya Anda bisa membandingkan x*x>y*y.
xnor
@Xnor, sayangnya, Ruby membutuhkan ruang di antara y*ydan ?jadi panjangnya persis sama. Saya sudah memasukkannya karena saya pikir cara Anda dalam beberapa hal lebih rapi. Saya pikir Ruby sedang mencoba untuk melewatinya sebagai y?nama fungsi hukum.
Level River St
3

Julia, 38 34 byte

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

Dennis menyimpan empat byte. Terima kasih!

Cobalah online!

Lynn
sumber
Sepertinya saya mencampuradukkan perilaku int di berbagai versi Julia (yang, dalam pembelaan saya, sangat tidak konsisten). Julia 0.4 (versi pada TIO) putaran menjadi setengah bahkan, jadi ini tidak akan berfungsi sebagaimana mestinya. Di Julia 0.3, Anda dapat menggunakan int(2angle(z)/pi+5)untuk jumlah byte yang sama (kekuatan negatif menyebabkan kesalahan untuk alasan apa pun).
Dennis
Anda juga dapat menyimpan byte dengan !z=z+(z!=0)im^...semua versi.
Dennis
2

C ++, 94 byte

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

Tidak Disatukan:

#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

Pemakaian:

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

Cobalah online

Anedar
sumber
Saya cukup yakin itu (x>0?x:-(x))bisa terjadi (x>0?x:-x).
Yytsi
Sayangnya tidak, karena token x akan diganti dengan misalnya x + .5 yang hanya akan mendapatkan -x + .5.
Anedar
Baik. Saya memiliki pola pikir di mana negasi tanpa tanda kurung membalik tanda: D
Yytsi
Sebenarnya, Anda telah menggunakan preprocessor C (yang diakui sebagai bagian dari C ++, tetapi juga dibagikan dengan varian dan keturunan C lainnya)
tucuxi
2

R, 131 110 byte

Fungsi yang mengambil dua bilangan bulat, x,y sebagai input dan menulis output ke stdout. Solusinya mengikuti skema aliran kontrol @Dennis 'tetapi mungkin bisa golf.

EDIT: Kode yang diperbarui berdasarkan pada saran @ JDL dan menyimpan banyak byte.

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

Tidak disatukan

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
sumber
1
Saya pikir beberapa kondisi logis dapat dipersingkat: as.logical(-1)adalah TRUE, jadi X==0|Y==0dapat menjadi !X|!Y, dan kondisi if(X!=Y...)dapat menjadi if(X-Y). Juga, jika X==Ydan X!=0kemudian Y!=0berlebihan. Sebenarnya, semua !=0bagiannya mubazir; if(X!=0)setara dengan if(X).
JDL
1
Juga, mengingat bahwa "format I / O cukup fleksibel", itu mungkin permainan yang adil untuk keluaran secara implisit dengan c(x,y)bukan cat(x,y).
JDL
@JDL Itulah beberapa tips golf yang sangat berguna yang tidak pernah saya pikirkan, terima kasih banyak! Diperbarui jawabannya.
Billywob
2

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

Menerima larik [x, y], mengubahnya di tempat, dan mengembalikannya.

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

Bagaimana itu bekerja

c=>(

Ini adalah fungsi panah parameter tunggal dengan returnbadan ringkas -gratis.

[x,y]=c

Parameter segera dirubah menjadi xdan yvariabel.

,

Operator koma menggabungkan beberapa ekspresi menjadi satu, menggunakan hasil dari yang terakhir.

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

idigunakan untuk membedakan kasus kenaikan dan penurunan. Ketika xlebih besar dari y, kita berada di kuadran bawah atau kanan, dan perlu maju dalam satu dimensi ( i=1dengan paksaan boolean-ke-angka). Demikian juga ketika kita berada pada bagian negatif dari pembagian x = y diagonal. Dalam semua kasus lain — termasuk asal — tidak diperlukan penambahan ( i=0).

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

Kami menggunakan ekspresi yang agak mirip untuk mengendalikan indeks array mana yang akan disesuaikan. Ketika kita bertambah dan tidak di kuadran kiri atau bawah (atau ketika kita tidak naik dan di kiri atau bawah), maka bitor XOR akan menghasilkan 1dan kami akan menyesuaikan nilai y . Demikian juga ketika kita berada di diagonal x = -y (termasuk asal). Dalam semua kasus lain, indeksnya adalah 0( x ).

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

Ketika iadalah 1, kami akan menambahkannya ke nilai tertentu. Ketika iadalah 0, kami akan mengurangkan 1 dari nilai jika dan hanya jika kita tidak pada titik asal. Yang terakhir dideteksi dengan x|ymenghasilkan bukan nol, dijepit ke {0, 1} oleh paksaan boolean, dan negasi dari imemungkinkan kita untuk menggunakan bitwise ATAU bukannya logis (karena -1tidak memiliki nol bit, aman dari modifikasi).

c

Array adalah yang terakhir, jadi itu akan dikembalikan.

Pengujian

† Variasi

Kita dapat menyimpan dua byte lagi dengan melewatkan nilai balik yang bermakna dan hanya menggunakan mutasi input:

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

... atau kita dapat melewati mutasi input dan membuat semua variabel lokal untuk fungsi murni, dengan biaya enam byte:

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

JavaScript (ES6), 80 76 byte

(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
sumber
1

Haskell, 53 byte

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

Membawa dua angka, menghasilkan tupel. Jika titik ada di bagian timur -x<=y<x, tambah koordinat kedua dengan 1. Kalau tidak, siklus kuadran dengan memutar titik input 90 derajat, memanggil fungsi di atasnya, lalu memutar kembali.

Tidak
sumber
1

Racket 191 byte

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

Tidak Digubah (langsung menerjemahkan petunjuk gambar ke kode tanpa menggunakan rumus perantara):

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

Pengujian:

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

Keluaran:

'(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)
juga
sumber
1

Sebenarnya , 16 byte

Ini membutuhkan bilangan kompleks sebagai input dan menghasilkan bilangan kompleks lainnya. Selamat datang saran bermain golf!Cobalah online!

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

Tidak melakukanolf

         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
sumber
0

Scala, 184 byte

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

Tidak Disatukan:

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

Penjelasan:

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
sumber