실제 체비 쇼프 회전


15

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

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

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

점 p 와 거리 d가 주어지면, 거리 d 를 p 에서 반 시계 방향 (및 음수 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.