실제 체비 쇼프 회전


15

이것은 체비 쇼프 회전에서 영감을 얻은 도전 입니다. 이 도전에 대한 영감을 얻기 위해 거기에 대한 답변을 볼 것을 제안합니다.

평면에 한 점이 주어지면 원점을 중심으로하고 그 점과 교차하는 독특한 정사각형 (같은면이있는 직사각형)이 있습니다 ( 대화 형 데모 ).

여기에 이미지 설명을 입력하십시오

p 와 거리 d가 주어지면, 거리 dp 에서 반 시계 방향 (및 음수 d에 대해 시계 방향)으로 이동하여 얻은 점을 반환 사각형의 경계부)는, 교차 된 그 원점을 중심 P . 귀하의 답변은 소수점 이하 4 자리 이상이어야합니다.

테스트 케이스 :

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

이 모든 것들이 다른 도전에서 약간만 바뀔 수는 없었습니까? 이것은 불필요한 추가로 보입니다.
ATaco

1
@ATaco 아니요, 조금 더 복잡합니다.
orlp

p에서 시작하여 둘레를 따라 거리를 계산해야합니까?
Gábor Fekete

@ GáborFekete 다른 무엇입니까?
orlp

예, 테스트 사례가 이것을 암시하지만 명시 적으로 언급되지 않았습니다. 처음에는 x 축의 양의 교차점에서 시작한다고 생각했습니다.
Gábor Fekete

답변:


4

파이썬 2 363 335 296 266 262 267 256 233 바이트

우, 130 바이트가 없어졌습니다! 4 바이트를 절약 한 Neil, 2 바이트를 절약 한 Nathan Merrill, 말도 안되는 23 바이트를 절약 한 xnor에게 감사드립니다!

일반적인 아이디어는 다음과 같습니다. 우리는 그것이 사각형의 둘레에 대해 그것의 계수 인 것을 취함으로써 이동 거리를 줄일 수 있습니다. 점은 두 좌표 중 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

온라인으로 시도 하거나 테스트 사례를 실행 하십시오 .


합니까의 s=max(x,y,-x,-y)작업?
Neil

@ 닐 그것은 무리, 감사합니다!
Kade

(s>0)*(d>0)입니다 s>0<d. 출력은입니다 "%.4f "*2%tuple(p). if s:d=d%(8*s)일 수 있습니다 d%(s*8or 1). (r+1)일 수 있습니다 ~-r. 1*(x>-s)그냥 될 수 있습니다 (x>-s).abs(y)==abs(x)할 수 있습니다y*y==x*x
XNOR

@xnor 와우, 감사합니다! 내가 바꾼 얇은 부분 (x>-s)은 괄호와 ~-r감소 가 필요하지 않기 때문에 사용했습니다 -~r.
Kade

3

자바 스크립트 (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 ° 회전 한 방향으로 오버 슈트를 재귀 적으로 전달합니다. 방향은 실제로 수직 플래그 v와 단위를 사용하여 인코딩 w되므로 벡터 (1, 0), (0, 1), (-1, 0) 및 (0, -1)은 v0, 1, 0으로 인코딩됩니다. , 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 진수 표현에 대해 정확한 결과를 제공하지 않아야합니다. 정확한 답을 원한다면 이진 분수를 고수하십시오.
Neil
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.