计算绕组数


15

绕组数是净逆时针转观察者必须作出遵循给定闭合路径的整数。请注意,任何顺时针旋转都会对绕组数计数为负。路径允许自相交。

下面给出了一些示例(从Wikipedia中无耻地摘录):

在此处输入图片说明

您的目标是计算给定路径的绕组数。

输入值

假定观察者在原点(0,0)

输入是来自任何所需输入源的有限点序列(整数对类似),描述了分段线性路径。如果需要,可以将其展平为一维整数序列,也可以使输入模糊不清,以在所有y坐标之前取所有x坐标,反之亦然。您也可以将输入作为复数a+b i。路径可能会自相交,并且可能包含零长度段。第一点是路径的起点,假定位于正x轴上的某处。

路径的任何部分都不会与原点相交。路径将始终是封闭的(即,第一个和丢失的点是相同的)。您的代码可能暗示最后一点,也可能要求将其包括在内。

例如,根据您的喜好,两个输入都指定相同的正方形:

隐含终点

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

明确的终点

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

输出量

输出是绕组号的单个整数。这可以指向任何源(返回值,stdout,文件等)。

例子

所有示例都明确定义了端点,并以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

Answers:


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 '16

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 '16

@ edc65谢谢;我reduce之所以使用,是因为我没有意识到Math.atan2(0,0)为0。(嗯,这取决于您的0之一实际上是否为-0。)数学基于复数除法,通常计算为z / w = z * w* / |w|²,但我不在乎幅度,因此它只是乘以复共轭。同样,Math.atan2接受(y,x)参数也有些令人困惑。
尼尔

我承认我不懂代码,但是如果您的描述正确,那么我认为您的答案是错误的。确实,如果您从路径输入点(为了更清晰起见,我提供图片),则绕组数为1,而您的问题将输出
2。– Wojowu

@Wojowu对不起,我的意思是点之间的角度为从原点测量,而不是多边形的外角,所以对于你的照片,我的代码的确应该计算答案1
尼尔

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 2016年

@ETHproductions谢谢您的好话!是的,他们一直面临一些近期挑战。另一方面,我已经看到很多问题,其中Jelly的字节数大约是MATL的一半:-D
Luis Mendo

2

果冻,11个字节

æAI÷ØPæ%1SH

这将输入作为y坐标列表和x坐标列表。

在这里尝试。


1

蟒蛇,111

迄今为止最长的答案。我的动机是1)学习python和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π可得出所需的绕组数。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.