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 z
ketika berada di kuadran kanan. dalam hal ini kita perlu meningkatkan y koordinat oleh 1 (yaitu menambahkan i
ke z
.)
Kami memeriksa x.abs>=y.abs
dengan membandingkan kuadrat dari x
dan 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=y
yang berada di kuadran "atas"). Di mana hal ini benar, kami tambahkan i
kez
.
Untuk alasan bermain golf, menambahkan i
tidak diinginkan. Alih-alih, kami memodifikasi nomor ketika berada di kuadran bawah, dalam hal ini kami harus menambahkan 1 ke x
koordinat (tambahkan 1 ke z
.) Dalam hal ini kami menguji bahwa y*y>=x*x
untuk 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<-x
dan (hijau) persimpangan ini, yang merupakan wilayah di mana transformasi yang benar adalah penambahan 1 ke z
.