J, 40 39 34 байта
3 :'(o.1)<(>./-<./)12 o.y*+{.y'@:-
Анонимная двоичная функция, принимающая точку p в качестве одного из своих аргументов и список точек P в качестве другого аргумента (не имеет значения, какой аргумент является каким), и возвращающая 0
или 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 под углом 180 ° или меньше вокруг p .
p находится в выпуклой оболочке P тогда и только тогда, когда это условие ложно.
Ценой еще нескольких байтов мы можем использовать аналогичный метод, который не требует от нас явного вычисления углов: обратите внимание, что вышеприведенное условие эквивалентно утверждению, что p находится вне выпуклой оболочки P, если и только если он существует прямая от l до p , так что все точки в 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 слева от r, если q слева линии, проходящей через р и р . Обратите внимание , что к-влево от является отношение порядка P тогда и только тогда , когда все точки Р находятся на одной и той же стороны некоторой линии , проходящей через р , то есть, если р находится вне выпуклой оболочки P . Процедура, описанная выше, находит минимальную точку в PWRT этот порядок, то есть «крайний левый» точку P . Вместо того, чтобы выполнить два прохода, мы можем найти максимум (т. Е. «Самую правую» точку), а также минимум, точки в P по одному и тому же порядку за один проход, и убедиться, что минимум находится слева от максимум, т. е. фактически то, что слева от является переходным.
Это будет хорошо работать, если p находится за пределами выпуклой оболочки P , и тогда слева направо на самом деле является отношение порядка, но оно может нарушиться, когда p находится внутри выпуклой оболочки (например, попытайтесь выяснить, что будет произойдет, если мы запустим этот алгоритм, где точки в P - это вершины правильного пятиугольника, бегущего против часовой стрелки, а p - его центр.) Чтобы приспособиться, мы немного изменим алгоритм: мы выбираем точку q в P и делим пополам P вдоль линии, проходящей через p и q (т.е. мы разбиваем P вокруг qпо левому краю.) Теперь у нас есть «левая часть» и «правая часть» 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)