J, 40 39 34 byte
3 :'(o.1)<(>./-<./)12 o.y*+{.y'@:-
Una funzione diadica anonima, prendendo un punto, p , come uno dei suoi argomenti, e un elenco di punti, P , come l'altro argomento (non importa quale argomento sia quale), e restituendo 0o 1, se p è esterno o all'interno dello scafo convesso di P , rispettivamente. Il punto p , e i punti in P , sono presi come numeri complessi.
Esempio
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
o...
Python 2, funzione, 121 103, programma completo, 162
Python 3, 149 byte
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)
Riceve input, nello stesso formato del post originale, tramite STDIN e stampa un valore booleano che indica se p è nello scafo convesso di P
Spiegazione
Il programma verifica se la differenza tra gli angoli massimo e minimo (con segno) tra qualsiasi punto r in P , p e un punto arbitrario fisso q in P (usiamo solo il primo punto in P ), è inferiore a 180 °. In altre parole, verifica se tutti i punti in P sono contenuti in un angolo di 180 ° o inferiore, attorno a p .
p è nello scafo convesso di P se e solo se questa condizione è falsa.
Al costo di qualche byte in più, possiamo usare un metodo simile che non ci richiede di calcolare esplicitamente gli angoli: Nota che la condizione sopra è equivalente a dire che p è al di fuori dello scafo convesso di P se e solo se esiste una linea da l a p , in modo tale che tutti i punti in P siano sullo stesso lato di l . Se esiste una tale linea, allora c'è anche una tale linea che è incidente a uno (o più) dei punti in P (possiamo ruotare l finché non tocca uno dei punti in P. )
Per (provvisoriamente) trovare questa linea, partiamo lasciando l la retta passante per p e il primo punto in P . Quindi ripetiamo il resto dei punti in P ; se uno dei punti è alla sinistra di l (assumiamo una certa direzionalità in tutto, sinistra o destra non contano davvero), sostituiamo l con la linea che passa attraverso p e quel punto e continuiamo. Dopo aver ripetuto tutta P , se (e solo se) p è al di fuori dello scafo convesso, tutti i punti in P dovrebbero essere a destra di (o su) l . Verifichiamo che usando un secondo passaggio sui punti in P.
Python 2, 172 byte
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)
In alternativa, per fare la stessa cosa in un unico passaggio, lasciate alla-sinistra di una realtion tra qualsiasi due punti, q ed r , in P , tale che q è a sinistra di r se q è a sinistra della linea che passa attraverso p e r . Si noti che per-il-sinistro di è un rapporto ordine su P se e solo se tutti i punti P sono sullo stesso lato di qualche linea passante per p , cioè, se p è esterno convesso di P . La procedura sopra descritta trova il punto minimo in PWRT questo ordine, cioè, il punto "sinistra" in P . Invece di eseguire due passaggi, possiamo trovare il massimo (ovvero il punto "più a destra"), nonché il minimo, i punti in P rispetto allo stesso ordine in un singolo passaggio e verificare che il minimo sia a sinistra del massimo, cioè efficacemente, che alla sinistra di è transitivo.
Funzionerebbe bene se p è fuori dallo scafo convesso di P , nel qual caso a sinistra di è in realtà una relazione d'ordine, ma potrebbe rompersi quando p è all'interno dello scafo convesso (ad esempio, provare a capire cosa sarà succede se abbiamo eseguito questo algoritmo in cui i punti in P sono i vertici di un pentagono regolare, correndo in senso antiorario, e p è il suo centro.) Per adattarlo, modifichiamo leggermente l'algoritmo: Selezioniamo un punto q in P e bisecare P lungo la linea che passa attraverso p e q (cioè partizioniamo P attorno a qwrt to-the-left-of.) Ora abbiamo una "parte sinistra" e una "parte destra" di P , ciascuna contenuta in un mezzo piano, in modo che a sinistra di una relazione d'ordine su ciascuna; troviamo il minimo della parte sinistra e il massimo della parte destra e li confrontiamo come descritto sopra. Ovviamente, non dobbiamo dividere in due fisicamente P , possiamo semplicemente classificare ogni punto in P mentre cerchiamo il minimo e il massimo, in un singolo passaggio.
Python 2, 194 byte
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)