, 40 39 34个字节
3 :'(o.1)<(>./-<./)12 o.y*+{.y'@:-
一个匿名二进位函数,将点p作为其参数之一,并将点列表P作为另一个参数(无论哪个参数无关紧要),如果p在或之外,则返回0
or 1
。在P的凸包内部。点p和P中的点被视为复数。
例
is_inside =: 3 :'(o.1)<(>./-<./)12 o.y*+{.y'@:-
0.5j0.5 is_inside 0j0 0j1 1j0 1j1
1
1.5j0.5 is_inside 0j0 0j1 1j0 1j1
0
要么...
Python 2,函数, 121 103,完整程序, 162
Python 3,149字节
import sys,cmath as C
p,q,*P=[complex(*eval(l.replace(*";,")))for l in sys.stdin]
A=[C.phase((r-p)/(q-p+(q==p)))for r in P]
print(max(A)-min(A)>C.pi)
通过STDIN以与原始帖子相同的格式输入输入,并打印一个布尔值,该值指示p是否在P的凸包中
说明
程序检测的最大值和最小值(符号)之间的差是否任何点之间的角度- [R在P,p,和一个固定的任意的点q在P(我们只使用在第一点P),是小于180°。换句话说,它测试P中的所有点是否都包含在p周围的180°或更小的角度中。
p是在的凸包P当且仅当该条件为假。
以更多的字节为代价,我们可以使用类似的方法,该方法不需要我们显式地计算角度:请注意,上述条件等效于说且仅当存在时p位于P的凸包之外。一条从l到p的线,使得P中的所有点都在l的同一侧。如果存在这样一条线,那么也有一条线入射到P中的一个(或多个)点(我们可以旋转l直到它碰到P中的一个点)。
为了(暂时)找到这条线,我们首先让l为穿过p的线和P中的第一个点。然后,我们遍历P中的其余点;如果其中一个点位于l的左侧(我们假设整个方向性,实际上左右无关紧要),我们将l替换为穿过p和该点的线,然后继续。在对所有P进行迭代之后,如果(且仅当)p在凸包之外,则P中的所有点都应在l的右侧(或上方)。我们通过第二遍检查P中的点来检查。
Python 2,172字节
import sys
P=[eval(l.replace(*";,"))for l in sys.stdin]
x,y=P.pop(0)
C=lambda(a,b),(c,d):(a-x)*(d-y)-(b-y)*(c-x)>0
l=reduce(lambda*x:x[C(*x)],P)
print any(C(l,q)for q in P)
或者,为了做同样的事情在单次通过,让以最左的是任何两个点之间的维吾尔q和- [R ,在P,使得q是向左的ř如果q是向左穿过p和r的那一行。请注意,当且仅当P中的所有点都在通过p的某条线的同一侧时,即p在P的凸包之外时,to-the-left-of才是P上的顺序关系。上述过程在P中找到最小值此顺序,即P中的“最左”点。无需执行两次遍历,我们可以在一次遍历中以相同顺序找到P点的最大值(即“最右边”的点)和最小值,并验证最小值在顶点的左侧。最大,即有效地,最左边的是传递的。
如果p在P的凸包之外,这会很好地工作,在这种情况下,to-the-left实际上是一个顺序关系,但是当p在凸包内时可能会破裂(例如,尝试找出将如果运行此算法,则P中的点是正五边形的顶点,沿逆时针方向运行,p是其中心。如果要适应,我们将算法稍作改动:我们在P中选择一个点q,并等分P沿着穿过p和q的线(即,我们在q周围划分P现在,我们有一个P的一个“左部分”和一个“右部分” ,每个部分包含在一个半平面中,因此,在每个部分的最左边是一个顺序关系;我们找到左边的最小值,右边的最大值,并如上所述进行比较。当然,我们不必在物理上将P分为两等分,我们可以在一次寻找最小和最大值的过程中简单地对P中的每个点进行分类。
Python 2,194个字节
import sys
P=[eval(l.replace(*";,"))for l in sys.stdin]
x,y=P.pop(0)
C=lambda(a,b),(c,d):(a-x)*(d-y)-(b-y)*(c-x)>0
l=r=P[0]
for q in P:
if C(P[0],q):l=q*C(l,q)or l
elif C(q,r):r=q
print C(l,r)