JOT, 40 39 34 bajty
3 :'(o.1)<(>./-<./)12 o.y*+{.y'@:-
Anonimowa funkcja dyadyczna, przyjmująca punkt, p , jako jeden z jego argumentów, oraz listę punktów, P , jako drugi argument (nie ma znaczenia, który argument jest który), i zwracająca 0
lub 1
, jeśli p jest poza lub wewnątrz wypukłej z P , odpowiednio. Punkt p i punkty w P są traktowane jako liczby zespolone.
Przykład
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
lub...
Python 2, funkcja, 121 103, pełny program, 162
Python 3, 149 bajtów
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)
Pobiera dane wejściowe, w tym samym formacie co oryginalny post, za pośrednictwem STDIN i drukuje wartość logiczną wskazującą, czy p znajduje się w wypukłym kadłubie P
Wyjaśnienie
Testy programu, czy różnica pomiędzy maksymalną i minimalną (znakiem) kąty pomiędzy każdym punkcie R na P , P , i stałym dowolnego punktu P na P (po prostu wykorzystać pierwszy punkt P ) jest mniejszy niż 180 °. Innymi słowy, sprawdza, czy wszystkie punkty w P są zawarte w kącie 180 ° lub mniejszym, wokół p .
p znajduje się w wypukłym kadłubie P wtedy i tylko wtedy, gdy ten warunek jest fałszywy.
Kosztem kilku kolejnych bajtów możemy zastosować podobną metodę, która nie wymaga od nas jawnego obliczania kątów: Zwróć uwagę, że powyższy warunek jest równoważny z twierdzeniem, że p znajduje się poza wypukłym kadłubem P wtedy i tylko wtedy, gdy istnieje linia od l do p , tak że wszystkie punkty w P znajdują się po tej samej stronie l . Jeśli taka linia istnieje, istnieje również taka linia, która pada na jeden (lub więcej) punktów w P (możemy obracać l, aż dotknie jednego z punktów w P ).
Do (roboczo) znaleźć tę linię, zaczniemy pozwalając l być linia przez p , a pierwszy punkt P . Następnie iterujemy pozostałe punkty w P ; jeśli jeden z punktów znajduje się na lewo od l (zakładamy, że kierunkowość w całym, lewy lub prawy nie ma znaczenia), zastępujemy l linią przechodzącą przez p i ten punkt i kontynuujemy. Po iteracji po całym P , jeśli (i tylko jeśli) p znajduje się poza wypukłym kadłubem, wówczas wszystkie punkty w P powinny znajdować się na prawo od (lub na) l . Sprawdzamy to za pomocą drugiego przejścia nad punktami w P..
Python 2, 172 bajty
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)
Alternatywnie, aby zrobić to samo w jednym przejściu, pozwól, aby po lewej stronie znajdowała się rzeczywistość między dowolnymi dwoma punktami q i r , w P , tak że q znajduje się na lewo od r, jeśli q jest na lewo linii przechodzącej przez p i r . Należy pamiętać, że do-lewej z jest relacją zamówienie na P wtedy i tylko wtedy, gdy wszystkie punkty P są na tej samej stronie pewnej linii przechodzącej przez p , to znaczy, jeśli p jest poza wypukłą kadłuba P . Procedura opisana powyżej znajduje minimalny punkt w P.wrt ten porządek, czyli „skrajnie lewą” punkt P . Zamiast wykonywać dwa przejścia, możemy znaleźć maksimum (tj. „Skrajnie prawy” punkt), a także minimum, punkty w P wrt tej samej kolejności w jednym przejściu i sprawdzić, czy minimum znajduje się po lewej stronie maksimum, tzn. faktycznie, to, że po lewej stronie jest przechodnie.
Działa to dobrze, jeśli p znajduje się poza wypukłym kadłubem P , w którym to przypadku z lewej strony jest tak naprawdę relacja rzędna, ale może się zepsuć, gdy p znajduje się wewnątrz wypukłego kadłuba (na przykład spróbuj dowiedzieć się, co będzie się stało, gdyby zabrakło tego algorytmu, gdzie punkty P są wierzchołkami pięciokąta foremnego, działa w kierunku przeciwnym do ruchu wskazówek zegara, a p . jest jego centrum) Aby uwzględnić, że nieznacznie zmienić algorytm: Wybieramy punkt Q na P , a Przepoławiana P wzdłuż linii przechodzącej przez p i q (tzn. Dzielimy P wokół qwrt do-the-left-of.) Mamy teraz „lewą część” i „prawą część” P , każda zawarta w półpłaszczyźnie, tak że z lewej strony jest relacja porządkowa na każdej z nich; znajdujemy minimum lewej części i maksimum prawej części i porównujemy je jak opisano powyżej. Oczywiście nie musimy fizycznie przecinać P , możemy po prostu sklasyfikować każdy punkt w P , szukając minimum i maksimum, w jednym przejściu.
Python 2, 194 bajtów
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)