Ruby, 68
Lambda işlevi karmaşık sayıyı argüman olarak alır, karmaşık sayıyı döndürür.
->z{k=1
4.times{z*=?i.to_c
x,y=z.rect
y*y>=x*x&&y<-x&&(z+=k;k=0)}
z}
Noktayı çarparak 90 derece 4 kez döndürüyoruz i
. Bu nedenle, 4 kadranın hepsinden de geçer ve değişmeden geri gönderilir - belirli bir tanedeyken değiştirdiğimiz gerçeği dışında. Aynı kadranda her zaman değiştirilmiş olması, değişikliği kolaylaştırır.
z
Sağ kadrandayken değiştirirsek takip etmek en kolay yoldur . bu durumda biz y, 1 ile koordine artırmak gerekir (yani, ekleme i
için z
).
Biz kontrol x.abs>=y.abs
karelerini karşılaştırarak x
ve y
. Bu bize, noktanın yukarı ya da aşağı değil, sağ ya da sol kadranda olduğunu söyler. O sağ taraftaki kadranda aslında kontrol etmek daha ileri kontrol x>y
(biz davayı dışlamak istiyorum, çünkü kesinlikle daha x=y
"üst" kadranda aittir.) Bu Eklemek doğrudur Nerede i
etmek z
.
Golf nedeniyle, ekleme i
arzu edilmez. Bunun yerine, sayıyı alt kadrandayken değiştiriyoruz, bu durumda x
koordinata 1 eklemeliyiz (1 ila z
.). Bu durumda y*y>=x*x
kontrol etmek için üst veya alt kadranda olup olmadığını test ediyoruz . Alt kadranda olduğundan emin olmak için kontrol etmemiz gerekir y<-x
(kesinlikle sağ alt köşedeki durum hariç y=-x
.)
Bu kontrolün bir avantajı 0,0 koordinatı için özel bir durum olmamasıdır. Maalesef, noktayı hareket ettirmenin onu farklı bir kadranda değiştirebileceği bulundu ve bu, ikinci kademe hareketinin bastırılması gerektiği anlamına geliyor, ki bu da, kadranın tekrar kontrol edilmesi durumunda, ki bu da muhtemelen avantajı engelliyor.
örnek 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.
Örnek 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.
Test programında
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)
Diyagram
Aşağıdaki resimde (mavi) x*x>=y*y
, (sarı) alanların y<-x
ve (yeşil) bunların kesiştiği alan gösterilmektedir, bu da doğru dönüşümün 1 ila 5 eklenmiş olduğu bölgedir z
.