권선 수 계산


15

권수는 관찰자가 주어진 폐쇄 경로를 따라하게해야합니다 순 시계 반대 방향으로 회전의 정수이다. 시계 방향 회전은 권선 수에 대해 음수로 계산됩니다. 경로는 자체 교차 할 수 있습니다.

Wikipedia에서 발췌 한 몇 가지 예는 다음과 같습니다.

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

목표는 주어진 경로에 대한 권선 수를 계산하는 것입니다.

입력

관찰자는 원점에 있다고 가정합니다 (0,0).

입력은 조각 별 선형 경로를 설명하는 원하는 입력 소스의 유한 포인트 시퀀스 (정수의 쌍 모양)입니다. 원하는 경우 이것을 1D 정수형 정수로 편 평화하고 모든 y 좌표보다 먼저 모든 x 좌표를 취하기 위해 입력을 스위블 할 수도 있습니다. 입력을 복소수로 사용할 수도 있습니다 a+b i. 경로는 자체 교차 할 수 있으며 길이가 0 인 세그먼트를 포함 할 수 있습니다. 첫 번째 점은 경로의 시작이며 양의 x 축 어딘가에 있다고 가정합니다.

경로의 어느 부분도 원점과 교차하지 않습니다. 경로는 항상 닫힙니다 (즉, 첫 번째 지점과 손실 지점이 동일 함). 코드가 마지막 요점을 암시하거나 포함해야 할 수도 있습니다.

예를 들어, 선호도에 따라 두 입력 모두 동일한 사각형을 지정합니다.

암시 된 종점

1,0
1,1
-1,1
-1,-1
1,-1

명백한 종말점

1,0
1,1
-1,1
-1,-1
1,-1
1,0

산출

출력은 권선 번호의 단일 정수입니다. 이것은 모든 소스 (반환 값, 표준 출력, 파일 등) 일 수 있습니다.

모든 예제에는 명시 적으로 정의 된 끝 점이 있으며 x, y 쌍으로 제공됩니다. 또한 암시 적으로 정의 된 엔드 포인트를 가정하고 출력이 동일해야한다고 가정하면 이러한 예제를 코드에 직접 제공 할 수 있어야합니다.

1. 기본 테스트

1,0
1,1
-1,1
-1,-1
1,-1
1,0

산출

1

2. 반복 점 테스트

1,0
1,0
1,1
1,1
-1,1
-1,1
-1,-1
-1,-1
1,-1
1,-1
1,0

산출

1

3. 시계 방향 테스트

1,0
1,-1
-1,-1
-1,1
1,1
1,0

산출

-1

4. 외부 시험

1,0
1,1
2,1
1,0

산출

0

5. 혼합 권선

1,0
1,1
-1,1
-1,-1
1,-1
1,0
1,-1
-1,-1
-1,1
1,1
1,0
1,1
-1,1
-1,-1
1,-1
1,0
1,1
-1,1
-1,-1
1,-1
1,0

산출

2

채점

이것은 코드 골프입니다. 가장 짧은 코드가 승리합니다. 표준 허점이 적용됩니다. 권선 수를 계산하도록 특별히 설계되지 않은 한 내장 함수를 사용할 수 있습니다.


2
입력은 복소수 ( "1-i"또는 "1-1i"? 와 같은 문자열 표현)로 취할 수 있습니다
Level River St

예, 모든 유형의 쌍이 허용됩니다.
helloworld922

답변:


10

ES6, 83 바이트

a=>a.map(([x,y])=>r+=Math.atan2(y*b-x*c,y*c+x*b,b=x,c=y),b=c=r=0)&&r/Math.PI/2

복소수로 해석되는 점 쌍의 배열을 입력으로받습니다. 각 점을 각도로 변환하는 대신 점을 이전 점으로 나눈 다음 Math.atan2는 -π와 π 사이의 각도로 변환하여 경로가 감기 방향을 자동으로 결정합니다. 각도의 합은 권선 수의 2π 배입니다.

Math.atan2는 인수의 스케일에 신경 쓰지 않기 때문에 실제로 전체 분할을 수행하지 않고 z / w = (z * w*) / (w * w*)대신 각 포인트에 이전 포인트의 복잡한 켤레를 곱합니다.

편집 : @ edc65 덕분에 4 바이트가 절약되었습니다.


좋고 빠릅니다. 그리고 나는 당신의 수학을 이해하지 못합니다. 그러나 reduce거의 항상 나쁜 선택입니다.
edc65

a=>a.map(([x,y])=>r+=Math.atan2(y*b-x*c,y*c+x*b,b=x,c=y),b=c=r=0)&&r/Math.PI/2대신 맵을 사용하거나 줄입니다. 당신은 어쨌든 내 투표를했습니다
edc65

@ edc65 감사합니다; reduceMath.atan2 (0,0)이 0이라는 사실을 알지 못했기 때문에 사용 했습니다. (음, 0 중 하나가 실제로 -0인지 여부에 따라 다릅니다.) 수학은 복잡한 나눗셈을 기반으로합니다. z / w = z * w* / |w|²그러나 크기에 대해서는 신경 쓰지 않으므로 복잡한 공액에 의한 곱셈입니다. 또한 약간 혼란스러운 Math.atan2는 (y, x) 인수를 허용합니다.
Neil

코드를 이해하지 못하지만 귀하의 설명이 정확하면 귀하의 답변이 잘못되었다고 생각합니다. 사실, 당신은에서 포인트를 입력하면 경로 (I 큰 선명도의 사진을주고있다) 다음 권수가 1 인 동안 문제 것 출력 2.
Wojowu

@Wojowu 죄송합니다. 다각형의 외부 각도가 아닌 원점에서 측정 한 점 사이의 각도를 의미하므로 그림의 코드는 실제로 1로 답을 계산해야합니다.
Neil

3

MATL , 11 바이트

X/Z/0)2/YP/

입력은 끝점을 포함한 일련의 복소수입니다.

온라인으로 사용해보십시오!

설명

대부분의 작업은 Z/함수 ( unwrap)에 의해 수행됩니다.이 함수 는 절대 점프를 pi보다 크거나 같은 2 * pi 보수로 변경하여 각도를 라디안 단위로 풉니 다.

X/       % compute angle of each complex number
Z/       % unwrap angles
0)       % pick last value. Total change of angle will be a multiple of 2*pi because 
         % the path is closed. Total change of angle coincides with last unwrapped
         % angle because the first angle is always 0
2/       % divide by 2
YP/      % divide by pi

1
MATL과 Jelly는 최근에 대부분의 수학 과제를 거의 묶어 놓았습니다. 나는 당신이 거의 골치 아픈 데니스의 언어에 감명을 받았습니다 ...
ETHproductions

@ETHproductions 멋진 단어 감사합니다! 예, 그들은 최근의 몇 가지 도전에 묶여 있습니다. 반면에, Jelly의 바이트 수가 MATL :-D
Luis Mendo의

2

젤리, 11 바이트

æAI÷ØPæ%1SH

이것은 y 좌표 목록과 x 좌표 목록으로 입력을받습니다.

여기서 사용해보십시오 .


1

파이썬, 111

지금까지 가장 긴 답변. 내 동기는 1) 파이썬을 배우고 2) 아마도 이것을 pyth로 포팅하는 것입니다.

from cmath import *
q=input()
print reduce(lambda x,y:x+y,map(lambda (x,y):phase(x/y)/pi/2,zip(q[1:]+q[:1],q)))

입력은 복소수 목록으로 제공됩니다.

이데온

나는 그 접근법이 ES6 답변과 비슷하다고 생각합니다.

2 개의 복소수를 곱하면 곱의 인수 또는 단계는 두 숫자의 인수 또는 단계의 합입니다. 따라서 복소수가 다른 수로 나뉘면 몫의 위상은 분자의 위상과 분모의 차이입니다. 따라서 각 점과 다음 점에 대해 통과 한 각도를 계산할 수 있습니다. 이 각도를 합산하고 2π로 나누면 필요한 권선 수가 제공됩니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.