การหมุนของ Chebyshev


36

พิจารณากริดปกติที่แต่ละเซลล์มีพิกัดจำนวนเต็ม เราสามารถจัดกลุ่มเซลล์ให้เป็น "วงแหวน" ที่มีรูปทรงสี่เหลี่ยมโดยที่เซลล์ในแต่ละวงแหวนมีระยะทาง Chebyshevเท่ากัน(หรือระยะทางกระดานหมากรุก) จากจุดกำเนิด งานของคุณคือการประสานงานเซลล์ดังกล่าวและหมุนเซลล์นั้นโดยตำแหน่งหนึ่งทวนเข็มนาฬิกาภายในแหวนของมัน ใช้การแมปต่อไปนี้:

ป้อนคำอธิบายรูปภาพที่นี่

ดังนั้นสำหรับตัวอย่างเช่นถ้าใส่เป็นคุณควรเอาท์พุท(3, -2) (3, -1)โปรดทราบว่า(0, 0)เป็นอินพุตเดียวที่ควรจับคู่กับตัวเอง

กฎระเบียบ

รูปแบบ I / O นั้นค่อนข้างยืดหยุ่น คุณสามารถใช้ตัวเลขสองตัว, คู่ / รายการ / อาร์เรย์ / ทูเปิลของตัวเลข, จำนวนเชิงซ้อนเดียว, สตริงที่มีตัวเลขสองตัวเป็นต้น

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

เราสามารถผสมรูปแบบอินพุตและเอาต์พุตเช่นนำ tuple และเอาท์พุทเป็นจำนวนเชิงซ้อนได้หรือไม่?
Dennis

@ เดนนิสใช่แล้วไม่เป็นไร
Martin Ender

คำตอบ:


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 (สีแดง)

แผนภาพ

  • แหล่งกำเนิดได้รับการแก้ไข เราก้าวหน้าโดยการเพิ่ม[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), ลงชื่อ (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

Python ขนาด 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ไบต์อื่นได้
nimi

ขอบคุณฉันไม่ได้ตระหนักถึง,!
ข้อบกพร่อง

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ครั้งโดยคูณด้วย ดังนั้นจึงจะผ่านทั้งสี่จตุภาคและจะถูกส่งคืนไม่เปลี่ยนแปลง - ยกเว้นความจริงที่ว่าเราได้ทำการดัดแปลงเมื่อมันอยู่ในหนึ่งในนั้น ๆ ความจริงมันถูกแก้ไขเสมอในจตุภาคเดียวกันทำให้การแก้ไขง่ายขึ้น

มันง่ายที่สุดที่จะติดตามถ้าเราเปลี่ยนแปลงมันzเมื่อมันอยู่ในจตุภาคทางขวา ในกรณีนี้เราต้องเพิ่มพิกัด y ด้วย 1 (เช่นเพิ่มiไปz)

เราตรวจสอบx.abs>=y.absโดยการเปรียบเทียบสี่เหลี่ยมของและx yสิ่งนี้บอกเราว่าจุดนั้นอยู่ทางด้านขวาหรือด้านซ้ายและไม่ใช่ด้านบนหรือด้านล่าง ในการตรวจสอบในความเป็นจริงในวอดขวาที่เราตรวจสอบว่าต่อไป x>y(อย่างเคร่งครัดมากขึ้นเพราะเราต้องการที่จะไม่รวมกรณีx=yซึ่งเป็นของ "top" วอด.) ในกรณีนี้เป็นความจริงที่เราเพิ่มไปiz

สำหรับเหตุผลในการตีกอล์ฟการเพิ่มiนั้นไม่เป็นที่ต้องการ แต่เราปรับเปลี่ยนจำนวนเมื่ออยู่ในจตุภาคล่างซึ่งในกรณีนี้เราต้องเพิ่ม 1 ลงในxพิกัด (บวก 1 ถึงz) ในกรณีนี้เราทดสอบว่าy*y>=x*xเพื่อตรวจสอบว่ามันอยู่ในจตุภาคบนหรือล่าง เพื่อให้มั่นใจว่าอยู่ใน Quadrant ด้านล่างเราจำเป็นต้องตรวจสอบ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ไป

ป้อนคำอธิบายรูปภาพที่นี่


1
ขออภัยฉันไม่ได้ทำตามคำอธิบาย คุณคิดจะเพิ่มตัวอย่างหรือแผนภาพหรือไม่
Martin Ender

@ เพิ่มคำอธิบายของมาร์ตินแล้ว นี่เป็นวิธีการที่น่าสนใจ แต่เนื่องจากต้องระงับการเคลื่อนไหวสองจุดที่เปลี่ยนควอดเรนท์เป็นครั้งแรกที่พวกมันเคลื่อนไหวมันไม่ได้ดูสง่างามอย่างที่ฉันหวังไว้
เลเวลริเวอร์เซนต์

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

3

Mathematica, 34 ไบต์

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

นี้กำหนดผู้ประกอบการเอกภาค±ซึ่งจะใช้เวลาและผลตอบแทนจำนวนเชิงซ้อนที่มีส่วนประกอบแทนและxy

ตอนนี้ที่ Lynn ได้เปิดเผยวิธีแก้ปัญหาจำนวนเชิงซ้อนและ Dennis เอาชนะคะแนนของฉันแล้วฉันไม่รู้สึกแย่นักสำหรับการโพสต์การติดตั้งระบบอ้างอิงแบบ Golfed :) (กลายเป็นคำตอบที่เหมือนกับของ Lynn)


สิ่งนี้จะช่วยได้ไหม ± 0 = 0 ⁢± z_: = z + I ^ ⌊ 2 ⁢ Arg @ z / Pi + 3/2 ⌋ (อาจจะมีถ่านที่แตกต่างกันสำหรับวงเล็บพื้น)
DavidC

@DavidC น่าเสียดายที่ไม่ใช่เพราะฉันต้องใช้การเข้ารหัส UTF-8 จากนั้นค่า±จะมีค่า 2 ไบต์ต่อครั้ง
Martin Ender

จะไม่เป็น 4 ไบต์แทน 7 จึงให้ประหยัด 3 ไบต์?
DavidC

@DavidC ไม่วงเล็บเหลี่ยมจะมีขนาด 3 ไบต์
Martin Ender

ฉันไม่ทราบว่า แต่ถึงอย่างนั้นคุณก็ควรจะประหยัดได้ 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

Ruby, 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และ?ดังนั้นมันจึงมีความยาวเท่ากัน ฉันได้รวมไว้เพราะฉันคิดว่าวิธีการของคุณอยู่ในบางวิธี neater ฉันคิดว่า Ruby กำลังพยายามส่งผ่านy?ซึ่งจะเป็นชื่อฟังก์ชันทางกฎหมาย
เลเวลริเวอร์เซนต์

3

Julia, 38 34 ไบต์

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

เดนนิสบันทึกสี่ไบต์ ขอบคุณ!

ลองออนไลน์!


ดูเหมือนว่าฉันจะผสมพฤติกรรมของintใน Julia รุ่นต่างๆ (ซึ่งในการป้องกันของฉันมันไม่สอดคล้องกันอย่างมาก ) 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;
}

ลองออนไลน์


ผมค่อนข้างมั่นใจว่าจะสามารถ(x>0?x:-(x)) (x>0?x:-x)
Yytsi

น่าเสียดายที่ไม่ได้เนื่องจากโทเค็น x จะถูกแทนที่ด้วยเช่น x + .5 ซึ่งเพิ่งได้รับ -x + .5
Anedar

Alright ฉันมีความคิดที่การปฏิเสธโดยไม่มีวงเล็บพลิกสัญญาณ: D
Yytsi

พูดอย่างเคร่งครัดคุณใช้ตัวประมวลผลล่วงหน้า C (ซึ่งเป็นที่ยอมรับส่วนหนึ่งของ C ++ แต่ยังใช้ร่วมกับตัวแปร C และลูกหลานอื่น ๆ ด้วย)
tucuxi

2

R, 131 110 ไบต์

ฟังก์ชันที่รับค่าจำนวนเต็มสองค่าx,yเป็นอินพุตและเขียนเอาต์พุตไปยัง stdout วิธีการแก้ปัญหาเป็นไปตามรูปแบบการควบคุม @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
}

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
นอกจากนี้ยังระบุว่า "ผมรูปแบบ / O มีความยืดหยุ่นอย่างเป็นธรรม" ก็อาจจะเกมที่ยุติธรรมเพื่อส่งออกโดยปริยายด้วยแทน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

Haskell, 53 ไบต์

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

ใช้ตัวเลขสองตัวส่งออก tuple หากจุดอยู่ในส่วนทางทิศตะวันออกให้-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

สกาลา, 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
}
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.