Echte Chebyshev-Rotation

15

Dies ist eine Herausforderung, die von Chebyshev Rotation inspiriert wurde . Ich schlage vor, dort nach Antworten zu suchen, um Inspiration für diese Herausforderung zu erhalten.

Bei einem Punkt auf der Ebene gibt es ein eindeutiges Quadrat (ein Rechteck mit gleichen Seiten), das auf dem Ursprung zentriert ist und diesen Punkt schneidet ( interaktive Demo ):

Bildbeschreibung hier eingeben

Geben Sie für einen Punkt p und einen Abstand d den Punkt zurück, den Sie erhalten, indem Sie den Abstand d von p entgegen dem Uhrzeigersinn (und für ein negatives d im Uhrzeigersinn ) entlang des Umfangs des Quadrats verschieben, das auf dem Ursprung zentriert ist, der p schneidet . Ihre Antwort muss auf mindestens 4 Dezimalstellen genau sein.

Testfälle:

(0, 0), 100 -> (0, 0)
(1, 1), 81.42 -> (-0.4200, 1.0000)
(42.234, 234.12), 2303.34 -> (-234.1200, 80.0940)
(-23, -39.234), -234.3 -> (39.2340, -21.8960)

Die folgenden Testfälle stammen von Martin Ender und sind alle mit d = 1 :

(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)
orlp
quelle
Könnten nicht fast alle von diesen nur geringfügig von der anderen Herausforderung geändert werden? Dies scheint eine unnötige Ergänzung zu sein.
ATaco
1
@ATaco Nein, es ist etwas komplizierter.
Orlp
Soll der Abstand entlang des Umfangs beginnend mit p berechnet werden?
Gábor Fekete
@ GáborFekete Was noch?
Orlp
Ja, ich verstehe, die Testfälle implizieren dies, aber es wird nicht explizit angegeben. Ich dachte zuerst, dass es am positiven Schnittpunkt auf der x-Achse beginnen würde.
Gábor Fekete

Antworten:

4

Python 2, 363 335 296 266 262 258 256 233 Bytes

Woo, 130 Bytes verloren! Vielen Dank an Neil für das Speichern von 4 Bytes, Nathan Merrill für das Speichern von 2 Bytes und xnor für das Speichern von lächerlichen 23 Bytes!

Die allgemeine Idee ist folgende: Wir können die zurückgelegte Strecke verringern, indem wir den Modul gegen den Umfang des Quadrats messen. Der Umfang ist definiert als das 8-fache der größten der beiden Koordinaten, da der Punkt darauf liegen muss. Dann, nachdem der Modul genommen wurde, ist garantiert, dass wir keine Überlappung haben. Dies garantiert auch, dass wir uns immer nur gegen den Uhrzeigersinn bewegen müssen, da der Modul ein positives Ergebnis liefert.

Von dort aus benutze ich einfach das, was wir aus den angegebenen x- und y-Koordinaten wissen, um herauszufinden, wo wir uns befinden: oben, unten, links, rechts oder in einer Ecke, und um die Richtung zu bestimmen, die eine der folgenden sein kann 0, 1, 2, 3:

0 --> we are on the 'top', moving 'left'
1 --> we are on the 'left', moving 'down'
2 --> we are on the 'bottom', moving 'right'
3 --> we are on the 'right', moving 'up'

Danach ist es so einfach wie ein Looping, während wir noch eine Distanz zurücklegen müssen. Basierend auf der Richtung, die wir subtrahieren oder zur entsprechenden Koordinate hinzufügen, teilen Sie der Schleife mit, in welche Richtung wir als Nächstes fahren.

p,d=input()
x,y=p
s=max(x,y,-x,-y)
d=d%(s*8or 1)
r=[(y<s)*[2,[3,x>-s][x<s]][y>-s],[2*(y<0),3*(y<=0)][x>0]][y*y==x*x]
while s>0<d:f=1-2*(r<2);m=abs(f*s-p[r%2]);j=d>m;p[r%2]=[p[r%2]+f*d,f*s][j];r=-~r%4;d=(d-m)*j
print"%.4f "*2%tuple(p)

Es ist zwar ziemlich lang, aber es funktioniert auf jeden Fall. Hier ist ein Beispiel für I / O:

[0, 0], 100 --> 0.0000 0.0000
[1, 1], 81.42 --> -0.4200 1.0000
[42.234, 234.12], 2303.34 --> -234.1200 80.0940
[-23, -39.234], -234.3 --> 39.2340 -21.8960

Probieren Sie es online aus oder führen Sie Testfälle aus .

Kade
quelle
Does s=max(x,y,-x,-y)Arbeit?
Neil
@Neil Tut es, vielen Dank!
Kade
(s>0)*(d>0)ist s>0<d. Die Ausgabe kann sein "%.4f "*2%tuple(p). if s:d=d%(8*s)kann sein d%(s*8or 1). (r+1)kann sein ~-r. 1*(x>-s)kann einfach sein (x>-s). abs(y)==abs(x)kann seiny*y==x*x
xnor
@xnor Wow, danke! Nur die Änderungen, (x>-s)die ich vorgenommen habe, erforderten keine Klammern und ~-rDekremente, also habe ich sie verwendet -~r.
Kade
3

JavaScript (ES6), 147 Byte

f=(x,y,d,s=Math.max(x,y,-x,-y),c=(d/8%s+s)%s*8,v=0,w=x+y>0?1:-1,b=(v?x:y)*w+c-s)=>c?b>0?f(v?s*w:x,v?y:s*w,d,s,b,!v,v?w:-w):[x+c*w*v,y+c*w*!v]:[x,y]

Erläuterung: Arbeitet so, dass versucht wird, den Richtungsvektor innerhalb der Grenzen des Quadrats zu addieren. Jegliches Überschießen wird rekursiv zurückgeführt, wobei die Richtung um 90 ° gegen den Uhrzeigersinn gedreht wird. Die Richtung wird tatsächlich unter Verwendung eines vertikalen Flags vund einer Einheit codiert, wso dass die Vektoren (1, 0), (0, 1), (-1, 0) und (0, -1) mit v0, 1, 0 codiert werden , 1 bzw. wvon 1, 1, -1, -1. Der Richtungsvektor zeigt möglicherweise anfangs nicht in eine geeignete Richtung, aber er zeigt niemals nach hinten, sodass er sich schließlich in eine verwendbare Richtung dreht.

f=(x,y,d,                   Input parameters
 s=Math.max(x,y,-x,-y),     Calculate half the side of the square
 c=(d/8%s+s)%s*8,           Reduce the distance modulo the perimeter
 v=0,                       Initial vertical flag
 w=x+y>0?1:-1,              Initial direction
 b=(v?x:y)*w+c-s)=>         Will we overshoot the corner?
  c?b>0?f(v?s*w:x,v?y:s*w,  Advance to the next corner
          d,s,b,!v,v?w:-w): Rotate the direction
        [x+c*w*v,y+c*w*!v]: Advance the remaining amout
    [x,y]                   Nothing to do, zero input
Neil
quelle
Dies könnte daran liegen, dass mein Browser (Opera 40.0.2308.81) anscheinend einen Rundungsfehler aufweist, f(42.234, 234.12, 2303.34) -> [-234.12, 80.09399999999988]was bedeutet, dass er keine 4-stellige Genauigkeit aufweist. Vielleicht könnte dies durch Hinzufügen einer Ausgabeformatierung behoben werden? Gute Antwort! :)
Kade
@Shebang Bei der technischen Formatierung von Ausgaben ist eine Rundung erforderlich, sodass ein potenzieller Rundungsfehler auftritt. Die generierten Zahlen sind innerhalb der Grenzen der Gleitkomma-Arithmetik so genau wie möglich, was keine exakten Ergebnisse für beliebige Dezimaldarstellungen erwarten lässt. Halten Sie sich an binäre Brüche, wenn Sie genaue Antworten wünschen.
Neil