권선 수 계산


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.