実際のチェビシェフ回転


15

これは、チェビシェフローテーションに触発された挑戦です。この課題のインスピレーションを得るために、そこの答えを見ることをお勧めします。

平面上の点が与えられると、原点を中心としてその点と交差する一意の正方形(同じ辺を持つ長方形)があります(インタラクティブデモ)。

ここに画像の説明を入力してください

点所与Pとの距離D、距離移動した点を返すDからP、反時計回り(および負のために時計回り dは正方形の周囲に沿っての)交差する原点を中心P。回答は、少なくとも4桁の10進数で正確でなければなりません。

テストケース:

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

以下のテストケースは、Martin Enderによる元のチャレンジからのもので、すべて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)

これらのほとんどすべては、他の課題からわずかに変更することはできませんか?これは不必要な追加のようです。
アタコ

1
@ATacoいいえ、かなり複雑です。
orlp

距離は、pから始まる境界に沿って計算する必要がありますか?
ガボールフェ

@GáborFekete他に何?
orlp

ええ、テストケースはこれを暗示していますが、明示的には述べられていません。最初は、x軸の正の交差点から始まると考えました。
ガボールフェ

回答:


4

Python 2、363 335 296 266 262 258 256 233バイト

わあ、130バイトが失われました!4バイトを保存してくれたNeil、2バイトを保存してくれたNathan Merrill、とんでもない23バイトを保存してくれたxnorに感謝します!

一般的な考え方は次のとおりです。正方形の周囲に対する弾性率をとることにより、移動距離を短縮できます。境界は、ポイントがその上にある必要があるため、2つの座標の最大の8倍として定義されます。次に、モジュラスを取得した後、オーバーラップがないことが保証されます。また、モジュラスは正の結果を与えるため、反時計回りに移動するだけで済みます。

そこから、指定されたx座標とy座標から得た情報を使用して、現在の位置(上、下、左、右、または角)を把握し、次のいずれかの方向を決定します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'

この後、移動する距離がある間にループするのと同じくらい簡単です。方向に基づいて適切な座標を減算または追加し、ループに次の方向を指示します。

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)

かなり長い間、それは確かに動作します。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

オンラインで試すか、テストケースを実行します


DOESのs=max(x,y,-x,-y)作品?
ニール

@Neilありがとね!
ケード

(s>0)*(d>0)ですs>0<d。出力は"%.4f "*2%tuple(p)if s:d=d%(8*s)することができますd%(s*8or 1)(r+1)することができます~-r1*(x>-s)ちょうどすることができます(x>-s)abs(y)==abs(x)することができy*y==x*x
XNOR

@xnorうわー、ありがとう!私が変更したシンだけ(x>-s)が、カッコや~-rデクリメントを必要としないものなので、使用しました-~r
カーデ

3

JavaScript(ES6)、147バイト

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]

説明:正方形の境界内に保ちながら方向ベクトルを追加しようとすることで機能します。オーバーシュートは、反時計回りに90度回転した方向で再帰的に戻されます。ベクトル(1、0)、(0、1)、(-1、0)および(0、-1)が0、1、0でエンコードされるように、方向は実際に垂直フラグvと単位をw使用してエンコードされvます、1およびw1、1、-1、-1のそれぞれ。方向ベクトルは最初は適切な方向を指していない場合がありますが、逆方向を指すことはないため、最終的に使用可能な方向に回転します。

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

これは私のブラウザー(Opera 40.0.2308.81)が原因である可能性がありますが、f(42.234, 234.12, 2303.34) -> [-234.12, 80.09399999999988]4桁の精度を持たないことを意味するため、少し丸め誤差があるようです。出力フォーマットを追加するとこれが修正されるでしょうか?いい答えだ!:)
Kade

@Shebang技術的には、出力のフォーマットには丸めが必要になるため、潜在的な丸めエラーが発生します。生成される数値は、浮動小数点演算の制限内で最も近いものです。これは、任意の10進数表現の正確な結果を期待するものではありません。正確な答えが必要な場合は、バイナリ分数に固執します。
ニール
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.