J, 40 39 34 байти
3 :'(o.1)<(>./-<./)12 o.y*+{.y'@:-
Анонімна діадична функція, приймаючи крапку р як один із своїх аргументів і список точок Р як інший аргумент (не має значення, який аргумент є який), і повертається 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 °. Іншими словами, він перевіряє, чи містяться всі точки в Р під кутом 180 ° або менше, навколо p .
p знаходиться у опуклому корпусі P тоді і лише тоді, коли ця умова хибна.
Ціною ще декількох байтів ми можемо скористатися аналогічним методом, який не вимагає від нас явного обчислення кутів: Зауважте, що вищевказана умова еквівалентна тому, що p є поза опуклим корпусом P, якщо і лише тоді, коли існує прямій l через p , так що всі точки в P знаходяться на одній стороні l . Якщо така лінія існує, то також існує така лінія, яка стикається з однією (або декількома) точками P (ми можемо обертати l, поки вона не торкнеться однієї з точок на P ).
Для того, щоб (попередньо) знайти цю лінію, ми почнемо, дозволяючи л бути прямий , що проходить через р і перша точка P . Потім ми повторюємо решту точок P ; якщо одна з точок знаходиться зліва від l (ми припускаємо, що деяка спрямованість на всьому протязі, ліва або права насправді не має значення), замінюємо l на пряму, що проходить через p і ту точку, і продовжуємо. Після того, як ми повторили весь P , якщо (і тільки якщо) p знаходиться поза опуклою оболонкою, то всі точки в P повинні знаходитись праворуч від (або на) l . Перевіряємо, використовуючи другий прохід над точками P.
Пітон 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 і r . Зверніть увагу , що до-вліво від є відношення порядку P тоді і тільки тоді , коли всі точки Р знаходяться на одній і тій же боку деякої лінії , що проходить через р , тобто, якщо р знаходиться поза опуклої оболонки P . Описана вище процедура знаходить мінімальну точку PWRT цей порядок, тобто «крайній лівий» точку P . Замість виконання двох проходів ми можемо знайти максимум (тобто "найправіший" пункт), а також мінімальний, точки в P wrt того ж порядку в одному проході і перевірити, що мінімум знаходиться зліва від максимум, тобто ефективно, що ліворуч є перехідним.
Це буде добре, якщо p знаходиться поза опуклим корпусом P , в цьому випадку ліворуч - це фактично відношення порядку, але може зламатися, коли p знаходиться всередині опуклого корпусу (наприклад, спробуйте розібратися, що буде відбудеться , якщо ми запустили цей алгоритм , де точки в р є вершинами правильного п'ятикутника, працює проти годинникової стрілки, і п . є його центром) Для розміщення, ми трохи змінити алгоритм: ми вибираємо точку д в р , і Bisect P по лінії, що проходить через p і q (тобто, розділимо P навколо qwrt to-left-of.) Тепер у нас є "ліва частина" і "права частина" 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)