Controlla se il punto si trova all'interno del triangolo


40

Il tuo obiettivo è determinare se un determinato punto X X si trova all'interno del triangolo con determinati vertici A, B, C.

Scrivi una funzione che accetta le coordinate del punto di prova X e dei tre vertici del triangolo (quindi sono 8 coordinate in totale) e restituisce True se il punto si trova all'interno di quel triangolo e False se si trova all'esterno.

Non preoccuparti dei casi limite. Se il punto si trova sul limite del triangolo (bordo o vertice) o il triangolo è in realtà un segmento di linea, il codice può fare qualsiasi cosa, incluso l'arresto anomalo. Inoltre, non preoccuparti della stabilità numerica o della precisione in virgola mobile.

Il tuo codice deve essere una funzione denominata. Gli snippet di codice non saranno accettati.

Vince il minor numero di personaggi.

Ingresso:

Otto numeri reali che rappresentano le coordinate. I numeri si troveranno nell'intervallo (-1,1).

Il formato di input esatto è flessibile. Ad esempio, potresti prendere otto numeri, un elenco di otto numeri, un elenco di quattro punti ciascuno dato da una tupla, una matrice 2 * 4, quattro numeri complessi, due elenchi di coordinate xe coordinate y, e così via.

L'input deve essere solo i numeri in alcuni container, senza dati aggiuntivi. Non è possibile utilizzare l'input per eseguire alcuna preelaborazione, né è possibile richiedere alcun vincolo sull'input, come la richiesta di assegnare i punti in una coordinata y crescente. L'input deve consentire otto coordinate (anche se il codice può comportarsi in modo arbitrario nei casi limite menzionati in precedenza).

Si prega di indicare il formato di input.

Produzione:

O il corrispondente booleano True/ False, il numero corrispondente 1/ 0o gli analoghi nella tua lingua.

Casi test

Agli input viene fornito un elenco [X,A,B,C]di quattro tuple, prima il punto di prova, quindi i tre vertici del triangolo. Li ho raggruppati in quelli i cui risultati dovrebbero essere Truee quelli che dovrebbero essere False.

True casi:

[(-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)]
[(-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)]
[(0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)]
[(-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)]
[(0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)]
[(-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)]
[(-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)]
[(-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)]
[(0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)]
[(-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832)]

False casi:

[(-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)]
[(0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)]
[(0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)]
[(0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)]
[(0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)]
[(-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)]
[(-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)]
[(0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)]
[(0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)]
[(0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192)]

Qual è la tua definizione di personaggio? Ascii? Codificabile in 7 bit? In un byte? Qualche Unicode?
Isaacg,

Che cosa suggerisci? Esistono già soluzioni che utilizzano il codice compresso.
xnor

In genere, credo che i byte vengano utilizzati per caratteri non Ascii, perché altrimenti il ​​vantaggio Utf-32 è insormontabile.
Isaacg,

Bene, non posso tornare indietro ora; qualsiasi personaggio Unicode è un personaggio. Comprimi se vuoi.
xnor

Risposte:


19

Javascript / ECMAScript 6, 161 159 158/152

Javascript:

function $(t,r,i,a,n,g,l,e){b=(-g*l+a*(-n+l)+i*(g-e)+n*e)/2;c=b<0?-1:1;d=(a*l-i*e+(e-a)*t+(i-l)*r)*c;f=(i*g-a*n+(a-g)*t+(n-i)*r)*c;return d>0&&f>0&&d+f<2*b*c}

Versione ECMAScript 6 (grazie m.buettner, salva 6 caratteri)

$=(t,r,i,a,n,g,l,e)=>{b=(-g*l+a*(-n+l)+i*(g-e)+n*e)/2;c=b<0?-1:1;d=(a*l-i*e+(e-a)*t+(i-l)*r)*c;f=(i*g-a*n+(a-g)*t+(n-i)*r)*c;return d>0&&f>0&&d+f<2*b*c}

Chiamalo come tale (restituisce trueo false):

$(pointX, pointY, v1X, v1Y, v2X, v2Y, v3X, v3Y);

Utilizza alcuni elaborati calcoli di coordinate baricentriche basati sul codice di questa risposta . Segue una versione non golfata per il piacere della lettura:

function $ (pointX, pointY, v1X, v1Y, v2X, v2Y, v3X, v3Y) {
  var A =  (-v2Y * v3X + v1Y * (-v2X + v3X) + v1X * (v2Y - v3Y) + v2X * v3Y) / 2;
  var sign = A < 0 ? -1 : 1;
  var s = (v1Y * v3X - v1X * v3Y + (v3Y - v1Y) * pointX + (v1X - v3X) * pointY) * sign;
  var t = (v1X * v2Y - v1Y * v2X + (v1Y - v2Y) * pointX + (v2X - v1X) * pointY) * sign;
  return s > 0 && t > 0 && s + t < 2 * A * sign;
}

12
+1, se non altro per i nomi dei parametri!
Matt

Perché devi interrompere il mio conteggio dei caratteri UserScript ???
kitcar2000,

@ kitcar2000 che vuoi dire?
Abraham

Le regole dicono che vengono contati i caratteri, non i byte. Quindi puoi usare questo: xem.github.io/obfuscatweet per adattarti a 122 caratteri
xem

1
Sbaglio o avresti potuto usare al (a*(l-n)+i*(g-e)+n*e-g*l)posto di (-g*l+a*(-n+l)+i*(g-e)+n*e)?
Zacharý,

19

Python 2.7 128 127 117 110 109 103 99 95 94 91 90

Il mio primo tentativo di golf nel codice!

Codice

f=lambda x,y,t:sum(a*y+c*b+d*x<d*a+c*y+b*x for i in(0,1,2)for a,b,c,d in[t[i-1]+t[i]])%3<1

Prende come input (x, y, t) dove (x, y) è il punto che stiamo controllando e t è un triangolo t = ((x1, y1), (x2, y2), (x3, y3)).

Spiegazione

Sto calcolando i determinanti delle matrici

| 1 x1 y1 |      | 1 x2 y2 |      | 1 x3 y3 |
| 1 x2 y2 | ,    | 1 x3 y3 | ,    | 1 x1 y1 | .
| 1 x  y  |      | 1 x  y  |      | 1 x  y  |

Queste determinanti rappresentano le distanze segnate dai lati del triangolo al punto (x, y). Se hanno tutti lo stesso segno, il punto si trova sullo stesso lato di ogni linea ed è quindi contenuto nel triangolo.

Nel codice sopra, a*y+c*b+d*x-d*a-c*y-b*xè determinante per una di queste matrici.

Sto usando il fatto che True+True+True==3e False+False+False==0per determinare se questi determinanti hanno tutti lo stesso segno.

Uso gli indici di lista negativi di Python usando t[-1]invece di t[(i+1)%3].

Grazie a Peter per l'idea di usare s%3<1invece di s in(0,3)verificare se s è 0 o 3!

Versione di Sagemath

Non è davvero una soluzione diversa, quindi la includo in questa risposta, una soluzione sagemath che utilizza 80 caratteri:

f=lambda p,t,o=[1]:sum([det(Matrix([o+t[i-1],o+t[i],o+p]))<0for i in 0,1,2])%3<1

dove p=[x,y]et=[[x1,y1],[x2,y2],[x3,y3]]


1
Potrebbe s in (0,3)essere abbreviato in s%3<1?
Peter Taylor,

1
L'uso di indici negativi può essere modificato per salvarne un altro: -1,0,1 ... t[i]+t[i+1]è equivalente a0,1,2 ... t[i-1]+t[i]
Peter Taylor

@PeterTaylor Assolutamente vero! Peccato che ho rimosso lo spazio in -1,0,1prima di leggere questo. In realtà il tuo modo è più leggibile, quindi lo userò comunque.
Alex L

1
Benvenuti nel codice golf! Puoi sbarazzarti delle parentesi quadre per la comprensione dell'elenco all'interno di sumse racchiudi le 0,1,2parentesi tra parentesi, nel qual caso un carattere sostituendo uno spazio. Il motivo è che Python consente la comprensione senza restrizioni delle funzioni, ma le virgole nella tupla nuda la 1,2,3confondono perché tenta di analizzarle come argomenti separati.
xnor

16

Mathematica, 67 byte

f=Equal@@({#2,-#}&@@(#-#2).(x-#)>0&@@@Partition[x=#;#2,2,1,{1,1}])&

La funzione accetta due argomenti, il punto Xe un elenco di punti {A,B,C}, che vengono chiamati rispettivamente #e #2. Questo è se chiami

f[X,{A,B,C}]

allora otterrai #come Xe #2come {A,B,C}. (Nota che ci sono altre due funzioni anonime nidificate all'interno del codice - #e #2hanno un significato diverso all'interno di quelle.)

Ecco una spiegazione della funzione stessa:

                                              x=#;#2            & (* Save X into a variable x, but evaluate to {A,B,C}. *)
                                    Partition[x=#;#2,2,1,{1,1}] & (* Get a cyclic list of pairs {{A,B},{B,C},{C,B}}. *)
       (                        &@@@Partition[x=#;#2,2,1,{1,1}])& (* Define an anonymous function and apply it to each 
                                                                     of the above pairs. The two elements are referred 
                                                                     to as # and #2. *)
       (          (#-#2)        &@@@Partition[x=#;#2,2,1,{1,1}])& (* Subtract the two points. For a pair of vertices 
                                                                     this yields a vector corresponding to the edge 
                                                                     between them. *)
        {#2,-#}&                                                  (* An anonymous function that takes two values, 
                                                                     reverses them, inverts the sign of one of them 
                                                                     and puts them into a list. *)
       ({#2,-#}&@@(#-#2)        &@@@Partition[x=#;#2,2,1,{1,1}])& (* Applied to the edge, this yields its normal. *)
       ({#2,-#}&@@(#-#2).(x-#)  &@@@Partition[x=#;#2,2,1,{1,1}])& (* Take the scalar product of that normal with a
                                                                     vector from a vertex to x. This is projection of 
                                                                     this vector onto that normal and hence the SIGNED
                                                                     distance of x from the edge. *)
       ({#2,-#}&@@(#-#2).(x-#)>0&@@@Partition[x=#;#2,2,1,{1,1}])& (* Check the sign of that distance, the exact mapping 
                                                                     between (left, right) and (True, False) is 
                                                                     irrelevant, as long as it's consistent. *)
Equal@@({#2,-#}&@@(#-#2).(x-#)>0&@@@Partition[x=#;#2,2,1,{1,1}])& (* Check if all signs are equal - that is, if point X 
                                                                     lies on the same side of all edges. This is 
                                                                     equivalent to check that the point is inside the 
                                                                     triangle. *)

Si noti che questa funzione funzionerà effettivamente per qualsiasi n-gon convessa fintanto che i suoi vertici sono dati in senso orario o antiorario.


Non sarebbe più efficace verificare se il prodotto delle distanze è positivo rispetto a tutti i segni uguali? Non Mathematica, ma sembra che dovrebbe essere più facile.
Isaacg,

@isaacg Ci sono tre termini, quindi se sono tutti negativi, il loro prodotto è negativo e se sono tutti positivi, il loro prodotto è positivo. Il tuo approccio funziona solo se i segni di due numeri devono essere uguali.
Martin Ender,

Perché non usare Det?
alephalpha,

@alephalpha Beh, molto probabilmente perché non ci ho pensato. : P ... Ci penserò su
Martin Ender il

@alephalpha Hm no, non riesco a trovare un modo per costruire le tre matrici richieste in meno caratteri.
Martin Ender,

7

CJam, 66 63 59 52 46 34 32 31 30 28 caratteri

"Ă䒟损崙㩴ァ椟饃꿾藭鑭蘁"2G#b131b:c~

Dopo aver trasformato la stringa Unicode, viene valutato il seguente codice ( 33 byte ):

{2*2/\f{f{+~@-@@-}~@@*@@*>})-!}:T

Si aspetta X [A B C]come input, dove ogni punto è del modulo [double double]. L'output è 1 o 0.

Provalo online.

Un grande ringraziamento va all'utente23013 per aver salvato 6 caratteri (13 byte di codice non compresso)!

Casi test

$ cat triangle.cjam
"Ă䒟损崙㩴ァ椟饃꿾藭鑭蘁"2G#b131b:c~

[
  [-0.31961 -0.12646] [ [0.38478 0.37419]   [-0.30613 -0.59754] [-0.85548 0.6633]   ] T
  [-0.87427 -0.00831] [ [0.78829 0.60409]   [-0.90904 -0.13856] [-0.80685 0.48468]  ] T
  [0.28997 -0.03668]  [ [-0.28362 0.42831]  [0.39332 -0.07474]  [-0.48694 -0.10497] ] T
  [-0.07783 0.04415]  [ [-0.34355 -0.07161] [0.59105 -0.93145]  [0.29402 0.90334]   ] T
  [0.36107 0.05389]   [ [0.27103 0.47754]   [-0.00341 -0.79472] [0.82549 -0.29028]  ] T
  [-0.01655 -0.20437] [ [-0.36194 -0.90281] [-0.26515 -0.4172]  [0.36181 0.51683]   ] T
  [-0.12198 -0.45897] [ [-0.35128 -0.85405] [0.84566 0.99364]   [0.13767 0.78618]   ] T
  [-0.03847 -0.81531] [ [-0.18704 -0.33282] [-0.95717 -0.6337]  [0.10976 -0.88374]  ] T
  [0.07904 -0.06245]  [ [0.95181 -0.84223]  [-0.75583 -0.34406] [0.16785 0.87519]   ] T
  [-0.33485 0.53875]  [ [-0.25173 0.51317]  [-0.62441 -0.90698] [-0.47925 0.74832]  ] T
  [-0.99103 0.43842]  [ [0.78128 -0.10985]  [-0.84714 -0.20558] [-0.08925 -0.78608] ] T
  [0.15087 -0.56212]  [ [-0.87374 -0.3787]  [0.86403 0.60374]   [0.01392 0.84362]   ] T
  [0.1114 0.66496]    [ [-0.92633 0.27408]  [0.92439 0.43692]   [0.8298 -0.29647]   ] T
  [0.87786 -0.8594]   [ [-0.42283 -0.97999] [0.58659 -0.327]    [-0.22656 0.80896]  ] T
  [0.43525 -0.8923]   [ [0.86119 0.78278]   [-0.01348 0.98093]  [-0.56244 -0.75129] ] T
  [-0.73365 0.28332]  [ [0.63263 0.17177]   [-0.38398 -0.43497] [-0.31123 0.73168]  ] T
  [-0.57694 -0.87713] [ [-0.93622 0.89397]  [0.93117 0.40775]   [0.2323 -0.30718]   ] T
  [0.91059 0.75966]   [ [0.60118 0.73186]   [0.32178 0.88296]   [-0.90087 -0.26367] ] T
  [0.3463 -0.89397]   [ [0.99108 0.13557]   [0.50122 -0.8724]   [0.43385 0.00167]   ] T
  [0.88121 0.36469]   [ [-0.29829 0.21429]  [0.31395 0.2734]    [0.43267 -0.78192]  ] T
]p;

$ cjam triangle.cjam
[1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0]

È una funzione con nome?
Martin Ender,

@ m.buettner: sorta di. Il wiki ufficiale dice quanto segue: Block - una parte di programma delimitato da {e }e trattato come una singola unità. Simile ai blocchi di codice in C / java, tranne i blocchi sono oggetti di prima classe e possono essere assegnati a variabili (definendo così le funzioni).
Dennis,

1
@xnor 1m<@m*prepara 3 coppie di X e il successivo ( i+1th) vertice del triangolo. @-@@-sposta l'attuale ( ith) vertice sull'origine (e rispecchia se non lo fosse @-\@-, ma non importa). @@*@@*>calcola l'asse z del prodotto incrociato, noto anche come determinante, e restituisce 1se è negativo. :+3%!restituisce se sono tutti uguali, ovvero tutti e 3 sono negativi o non negativi, il che significa positivo tranne che per i casi limite. Penso che sia più difficile leggere CJam che giocare a golf.
jimmy23013,

1
37 byte: {[_1m<\]z\f{f{+~@-@@-}~@@*@@*>})-!}:T. Utilizzare 2m>o Wm<per la sicurezza Unicode.
jimmy23013,

1
33 byte:{2*2/\f{f{+~@-@@-}~@@*@@*>})-!}:T
jimmy23013,

5

C - 156 byte

Gli input sono array di 3 float in X, 3 float in Y e separati xey per il punto di test. Bonus: gestisce tutti i casi limite!

int f(float*X,float*Y,float x,float y){int i,j,c=0;for(i=0,j=2;i<3;j=i++)if(((Y[i]>y)!=(Y[j]>y))&&(x<(X[j]-X[i])*(y-Y[i])/(Y[j]-Y[i])+X[i]))c=!c;return c;}

Adattato da PNPOLY.


i;j;c;f(float*X,float*Y,float x,float y){for(c=i=0,j=2;i<3;)c^=(Y[i]>y)-(Y[j]>y)&(x<(X[j]-X[i])*(y-Y[i])/(Y[j]-Y[i])+X[j=i++]);return c;}137 - testato in javascript
bebe

@bebe - Questo provoca un errore di sintassi.
Derek 朕 會 功夫

Ciò non causa un errore di sintassi.
Bebe,

4

Pyth 1.0.5 , 57 54 51

DgYb=Z0J'bWbK;bDiHNR*-'H'K-@N1@K1~Z>iYJiJY=JK)R!%Z3

Definisce la funzione g, che accetta due input: il punto di prova e quindi l'elenco dei vertici del triangolo. Uscite Truee False. Nota: distrugge l'input, in particolare b, l'elenco dei vertici del triangolo.

Provalo qui . Gli ultimi pochi caratteri, gvwvwchiamano la funzione con un test case sulle due righe successive.

Basato su questo algoritmo

Spiegazione:

DgYb                  Define g(Y,b):
=Z0                     Z=0
J'b                     J=b[0]              (No = is needed because j is special).
Wb                      While len(b)>0:     (While b:)
K;b                       K=b.pop()
DiHN                      Define i(H,N):    
R*-'H'K-@N1@K1              Return half of the linked equation.
~ZiYJiJY                  Z+=i(Y,J)>i(J,Y)
=JK                       J=K
)                       Wend
R!%Z3                   return not Z%3==0   (True iff Z == 0 or 3)

The CJam - La guerra di Pyth infuria!


Questa dovrebbe essere una funzione denominata. Sta wprendendo input STDIN?
xnor

@xnor Oops, mi mancava quel pezzo di descrizione. Modifica.
isaacg,

@xnor Sono consentite funzioni che stampano la risposta o devono restituire la risposta? Attualmente, questo stampa la risposta, ma potrei farlo tornare per un altro personaggio.
isaacg,

Restituire la risposta
xnor

Puoi forse salvare i personaggi sostituendo il contatore Zcon un set vuoto con cui ti accumuli Z|=, quindi testarne la lunghezza per vedere se solo 0o 1sono stati visti? La strategia si è rivelata più lunga in Python, ma forse ne vale la pena usando le primitive di Pyth.
xnor

4

J 64 45 (42 senza assegnazione)

c=:*./@(>:&0)@({.(,(1-+/))@%.|:@}.)@(}:-"1{:)

L'assegnazione non è necessaria affinché la cosa sia una funzione, quindi non sei sicuro di contarla o meno. Approfittando dell'input flessibile: mi piacerebbe avere una matrice di (1 + numero di vertici) x (dimensionalità dello spazio).

Sperando di segnare alcuni punti extra qui ...: Questa cosa funziona per qualsiasi dimensione del simplex, non solo triangoli in un piano, ma anche una piramide a 3 facce nello spazio 3d e così via. Funziona anche quando il numero di vertici del simplex è inferiore a (n + 1), quindi calcola se la proiezione del punto sul simplex è interna o meno.

Si converte in coordinate baricentriche , quindi controlla quelle negative, indicando che il punto è esterno. Ricorda che J usa _ per negativo

NB. example in triangle
D =: 4 2 $ 1 1 0 0 3 0 0 2 NB. 4 rows , x first, then the vertices of the triangle

NB. subtract last vertex coordinates from the rest and drop reference node
n=: (}:-"1{:)

NB. preprocessed to barycentric coordinates
bar=: {. (, 1 - +/)@%. |:@}.

NB. all positive
ap =: *./@(>:&0)

insided =: ap@bar@n

inside D
1

Una corsa sugli esempi forniti:

   true =: 0 : 0
[(-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)]
[(-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)]
[(0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)]
[(-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)]
[(0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)]
[(-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)]
[(-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)]
[(-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)]
[(0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)]
[(-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832)]
)

   false =: 0 : 0
[(-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)]
[(0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)]
[(0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)]
[(0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)]
[(0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)]
[(-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)]
[(-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)]
[(0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)]
[(0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)]
[(0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192)]
)
   NB. replace - by _ to avoid problems
   NB. cut up per row, drop the [ ] and convert to numbers
   $dat_t =: ((4 2 $ ".)@}:@}.;._2) (true='-')} true ,: '_'
10 4 2
   $dat_f =: ((4 2 $ ".)@}:@}.;._2) (false='-')}false,: '_'
10 4 2
   NB. this results in arrays with shape 10 4 2

   NB. for each 4 x 2 array (rank 2), do c for all true instances
   c=:*./@(>:&0)@({.(,(1-+/))@%.|:@}.)@(}:-"1{:)
   c"2 dat_t
1 1 1 1 1 1 1 1 1 1
   NB. the same for the false ones, demonstrating anonymous usage
   NB. still a function though (or verb in J parlance)
   *./@(>:&0)@({.(,(1-+/))@%.|:@}.)@(}:-"1{:)"2 dat_f
0 0 0 0 0 0 0 0 0 0

Ho chiesto una funzione con nome, quindi contano i caratteri dell'assegnazione. Ecco alcuni punti per generalizzare ai poligoni! ······
xnor

Beh, in realtà, non generalizzo abbastanza ai poligoni, ma ai simplex N-dimensionali, con N+1vertici massimi . Ad esempio una piramide a 4 vertici nello spazio 3D o un simplex a 5 vertici nello spazio 3D. Il numero di vertici può essere inferiore a N+1, nel qual caso l'algoritmo verifica se la proiezione ortogonale sull'iperpiano in cui risiede il simplex si trova all'interno del simplex o meno (ad es. Un simplex a 2 punti in 2-D verrà proiettato sulla linea e verificato se questa proiezione si trova tra i punti finali)
jpjacobs

4

HTML5 + JS, 13b + 146b / 141b / 114 caratteri

HTML:

<canvas id=C>

JS (146b):

// @params: t1x, t1y, t2x, t2y, t3x, t3y, pointx, pointy
function T(a,b,c,d,e,f,g,h){with(C.getContext("2d"))return beginPath(),moveTo(a,b),lineTo(c,d),lineTo(e,f),fill(),!!getImageData(g,h,1,1).data[3]}

o ES6 (141b):

T=(a,b,c,d,e,f,g,h)=>{with(C.getContext("2d"))return beginPath(),moveTo(a,b),lineTo(c,d),lineTo(e,f),fill(),!!getImageData(g,h,1,1).data[3]}

o ES6 unicode-offuscato (114 caratteri):

eval(unescape(escape('𥀽𚁡𛁢𛁣𛁤𛁥𛁦𛁧𛁨𚐽🡻𭱩𭁨𚁃𛡧𩑴𠱯𫡴𩑸𭀨𘠲𩀢𚐩𬡥𭁵𬡮𘁢𩑧𪑮𤁡𭁨𚀩𛁭𫱶𩑔𫰨𨐬𨠩𛁬𪑮𩑔𫰨𨰬𩀩𛁬𪑮𩑔𫰨𩐬𩠩𛁦𪑬𫀨𚐬𘐡𩱥𭁉𫑡𩱥𡁡𭁡𚁧𛁨𛀱𛀱𚐮𩁡𭁡𦰳𧑽').replace(/uD./g,'')))

demo: http://jsfiddle.net/xH8mV/

Offuscamento Unicode realizzato con: http://xem.github.io/obfuscatweet/


Non sembra dare il risultato corretto quando il punto è vicino al lato: jsfiddle.net/L2B2A Credo che ciò sia dovuto al fatto che tutti gli input sono compresi tra (-1,1) e il tuo codice sta testando solo i 4 pixel intorno l'origine.
Derek 朕 會 功夫

esatto, per adattarsi agli esempi, dovrei cambiare l'origine e la scala della mia tela per gestire i triangoli all'interno [-1,1]. Ma perché quei triangoli sono così piccoli comunque?
xem,

il problema dice che tutti gli xy sono compresi tra -1 e 1. Non so davvero perché, ma credo che puoi semplicemente moltiplicare ogni input per 1e7 (per mantenere la precisione) per ottenere il risultato corretto: D
Derek 朕 會 功夫

Una soluzione grafica, molto intelligente!
xnor

3

Python (65)

Le persone sembrano aver finito di inviare, quindi posterò la mia soluzione alla mia domanda.

f=lambda X,L:sum(((L[i-1]-X)/(L[i]-X)).imag>0for i in(0,1,2))%3<1

Xè il numero complesso che rappresenta i punti di prova ed Lè un elenco di tre punti, ciascuno un numero complesso.

Innanzitutto, spiegherò una versione meno giocata del codice;

def f(X,A,B,C):A-=X;B-=X;C-=X;return((A/B).imag>0)==((B/C).imag>0)==((C/A).imag>0)

Spostiamo i punti in A,B,C,Xmodo che Xsiano all'origine, sfruttando l'aritmetica complessa integrata di Python. Dobbiamo verificare se l'origine è contenuta nello scafo convesso di A,B,C. Ciò equivale all'origine che giace sempre sullo stesso lato (sinistro o destro) dei segmenti di linea AB, BC e AC.

Un segmento ABha l'origine a sinistra se si viaggia in senso antiorario a meno di 180 gradi per passare da A a B, e in caso contrario a destra. Se consideriamo gli angoli a, be ccorrispondenti a questi punti, ciò significab-a < 180 degrees (angoli presi nell'intervallo da 0 a 360 gradi). Come numeri complessi, angle(B/A)=angle(B)/angle(A). Inoltre, angle(x) < 180 degreesesattamente per il punto nel mezzo piano superiore, che controlliamo tramite imag(x)>0.

Quindi, se l'origine si trova alla sinistra di AB è espresso come (A/B).imag>0 . Controllare se questi sono tutti uguali per ogni coppia ciclica in A,B,Cci dice se il triangolo ABCcontiene l'origine.

Ora torniamo al codice completamente golfato

f=lambda X,L:sum(((L[i-1]-X)/(L[i]-X)).imag>0for i in(0,1,2))%3<1

Generiamo ogni coppia ciclica in (A-X,B-X,C-X)=(L[0]-X,L[1]-X,L[2]-X), sfruttando gli indici negativi dell'elenco Python che si avvolgono ( L[-1]= L[2]). Per verificare che i bool siano tutti True( 1) o tutti False( 0), li aggiungiamo e controlliamo la divisibilità per 3, come hanno fatto molte soluzioni.


2

Fortran - 232 218 195 174

Maledettamente orribile. La funzione è orrenda a causa del requisito che i dati gli vengono passati e non possiamo preelaborarli.

logical function L(x);real::x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);t=x(7)-x(3);u=x(8)-x(4);L=ALL([p*(s-u)+q*(t-r)+r*u-t*s,p*u-q*t,q*r-p*s]>=r*u-t*s);endfunction

La diminuzione di 14 caratteri è dovuta al fatto che ho dimenticato di giocare a golf il nome della funzione dalle mie prove. L'ulteriore riduzione è dovuta alla digitazione implicita e alla dimenticanza di modificare il nome della funzione. I successivi 20 personaggi si staccarono a causa della lettura dei punti come un singolo array. Il programma completo è

program inTriagle
   real, dimension(2) :: a,b,c,x
   do 
      print*,"Enter coordinates as x,a,b,c"
      read*,x,a,b,c
      if(all(x==0.0).and.all(a==0.0).and.all(b==0.0).and.all(c==0.0)) exit
      print*,"Is point in triangle: ",T(x,a,b,c)
   enddo
 contains!                       
   logical function L(x)
     real::x(8)
     p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3)
     s=x(6)-x(4);t=x(7)-x(3);u=x(8)-x(4)
     L=ALL([p*(s-u)+q*(t-r)+r*u-t*s,p*u-q*t,q*r-p*s]>=r*u-t*s)
   endfunction
end program inTriagle

1
Puoi renderlo un po 'più breve facendo affidamento sulla digitazione implicita di Fortran e usando un singolo array di input contenente tutti gli 8 numeri: logical function T(x);real x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);u=x(7)-x(3);v=x(8)-x(4);o=r*v-u*s;T=ALL([p*(s-v)+q*(u-r)+o,p*v-q*u,q*r-p*s]>=o);endho provato ad accorciarlo ulteriormente utilizzando le operazioni di elenco, ma sfortunatamente non ha funzionato molto bene.
Ventero,

1
Ancora più breve eliminando le sottoespressioni più comuni: logical function T(x);real x(8);p=x(1)-x(3);q=x(2)-x(4);r=x(5)-x(3);s=x(6)-x(4);u=x(7)-x(3);v=x(8)-x(4);a=r*v-u*s;b=p*v-q*u;d=q*r-p*s;T=ALL([a-b-d,b,d]>=a);endspero di non aver commesso errori nelle trasformazioni! Anche se sembra che il tuo codice originale non superi tutti i test.
Ventero,

@Ventero: non riesco a credere di aver dimenticato di abusare della digitazione implicita :(. Grazie per il tuo aiuto!
Kyle Kanos,

@Ventero: Inoltre, sembra che la mia risposta dipenda dall'orientamento del triangolo. Il primo Trueesempio in OP fornisce Falsese cambio Be Cvalori mentre fornisco Truel'orientamento originale.
Kyle Kanos,

Ah, in effetti, il problema è causato quando (riutilizzando la notazione dal mio commento precedente) a < 0, che invertisce effettivamente la condizione che devi testare. Sfortunatamente questo non può essere risolto semplicemente avvolgendo tutto in un abs, poiché quindi la condizione implicita di be davendo lo stesso segno di come asi perde. Questo può essere risolto usando qualcosa di simile (di nuovo, riutilizzando la notazione e le variabili predefinite dal mio ultimo commento) e=a-b-d;T=ALL([a*a-b*b,a*a-d*d,a*a-e*e,a*b,a*d,a*e]>=0)- che probabilmente può essere golfato di più.
Ventero,

2

MATLAB: 9!

Non molti di me scrivono qui

inpolygon

Può essere chiamato così:

inpolygon(2/3, 2/3, [0 1 1], [0 0 1])

L'output è assegnato a una variabile denominata ans


Se dovessi effettivamente scrivere una funzione, potrebbe essere qualcosa del genere, probabilmente potrebbe essere ottimizzato:

function y=f(a,b,c,d)
inpolygon(a,b,c,d)

2
può essere più breve usando un handle di funzione:f=@(a,b,c,d)inpolygon(a,b,c,d)
jpjacobs

2

C # 218 (149?)

using P=System.Drawing.PointF;
bool F(P[]p){for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}P[]a=new P[3];Array.Copy(p,1,a,0,3);var g=new System.Drawing.Drawing2D.GraphicsPath();g.AddLines(a);return g.IsVisible(p[0]);}

Probabilmente non efficiente dal punto di vista dei caratteri come un metodo matematico, ma è un uso divertente delle librerie. Per inciso, anche piuttosto lento.

Sfruttando anche "Non preoccuparti della stabilità numerica o della precisione in virgola mobile". - sfortunatamente, GraphicsPathusa intinternamente s, quindi un valore nell'intervallo -1 <f <1 può avere solo tre possibili valori. Dato che i float hanno solo 7 cifre di precisione, moltiplico solo per 1e7 per trasformarli in numeri interi. Hm, immagino che non stia davvero perdendo precisione. È anche sfruttabile in un altro modo: probabilmente avrei potuto trarre vantaggio dall'ignorare la precisione e dare la risposta "sbagliata".

Se mi è permesso ignorare il costo dei caratteri dell'importazione delle librerie, 149 (almeno, System.Linqe System.Drawingsono piuttosto standard sulla maggior parte dei progetti WinForms, ma System.Drawing.Drawing2Dpotrebbe essere un po 'più lungo):

bool G(PointF[]p){for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}var g=new GraphicsPath();g.AddLines(p.Skip(1).ToArray());return g.IsVisible(p[0]);}

Programma di test (sì, è brutto):

using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using P=System.Drawing.PointF;
using System.Linq;

class Program
{
    static void Main(string[] args)
    {
        Program prog = new Program();
        foreach (string test in
@"[(-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)]
[(-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)]
[(0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)]
[(-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)]
[(0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)]
[(-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)]
[(-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)]
[(-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)]
[(0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)]
[(-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832)]
[(-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)]
[(0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)]
[(0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)]
[(0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)]
[(0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)]
[(-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)]
[(-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)]
[(0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)]
[(0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)]
[(0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192)]".Split('\n'))
        {
            string t = test.Replace("[(", "").Replace(")]", "");
            string[] points = t.Split(new string[] { "), (" }, StringSplitOptions.None);

            string[] p = points[0].Split(',');
            P[] xabc = new P[4];

            for (int i = 0; i < 4; i++)
            {
                p = points[i].Split(',');
                xabc[i] = new F(float.Parse(p[0]), float.Parse(p[1]));
            }

            Console.WriteLine(test + "=>" + prog.F(xabc));
        }

        Console.ReadKey();
    }

    bool G(PointF[]p)
    {
        for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}
        var g=new GraphicsPath();
        g.AddLines(p.Skip(1).ToArray());
        return g.IsVisible(p[0]);
    }

    bool F(P[]p)
    {
        for(int i=0;i<4;i++){p[i].X*=1e7f;p[i].Y*=1e7f;}
        var g=new System.Drawing.Drawing2D.GraphicsPath();
        g.AddLines(p.Skip(1).ToArray());
        return g.IsVisible(p[0]);
    }
}

Carina, convincere il motore di disegno a fare il lavoro.
xnor

2

Haskell - 233 127

Utilizzando prodotti incrociati come descritto qui :

h(a,b)(p,q)(r,s)(t,u)=z a b p q r s==z a b r s t u&&z a b r s t u==z a b t u p q where z j k l m n o =(o-m)*(j-l)+(l-n)*(k-m)>0

La soluzione precedente implementata usando coordinate baricentriche e le formule descritte in questa risposta di Stack Stack :

g(p,q)(r,s)(t,u)(v,w)=
 let (j,k)=(p+(-r),q+(-s))
     (l,m)=(t+(-r),u+(-s))
     (n,o)=(v+(-r),w+(-s))
     d=l*o-n*m
     a=(j*(m-o)+k*(n-l)+l*o-n*m)/d
     b=(j*o-k*n)/d
     c=(k*l-j*m)/d
 in (0<=a&&a<1)&&(0<=b&&b<1)&&(0<=c&&c<1)

Entrambe le funzioni ge hprendono quattro coppie, la prima delle quali è il punto da testare per l'inclusione e il resto sono le coordinate dei vertici del triangolo.

Per testare con l'input di esempio:

let trueTestCases =
  [((-0.31961, -0.12646), (0.38478, 0.37419), (-0.30613, -0.59754), (-0.85548, 0.6633)),
   ((-0.87427, -0.00831), (0.78829, 0.60409), (-0.90904, -0.13856), (-0.80685, 0.48468)),
   ((0.28997, -0.03668), (-0.28362, 0.42831), (0.39332, -0.07474), (-0.48694, -0.10497)),
   ((-0.07783, 0.04415), (-0.34355, -0.07161), (0.59105, -0.93145), (0.29402, 0.90334)),
   ((0.36107, 0.05389), (0.27103, 0.47754), (-0.00341, -0.79472), (0.82549, -0.29028)),
   ((-0.01655, -0.20437), (-0.36194, -0.90281), (-0.26515, -0.4172), (0.36181, 0.51683)),
   ((-0.12198, -0.45897), (-0.35128, -0.85405), (0.84566, 0.99364), (0.13767, 0.78618)),
   ((-0.03847, -0.81531), (-0.18704, -0.33282), (-0.95717, -0.6337), (0.10976, -0.88374)),
   ((0.07904, -0.06245), (0.95181, -0.84223), (-0.75583, -0.34406), (0.16785, 0.87519)),
   ((-0.33485, 0.53875), (-0.25173, 0.51317), (-0.62441, -0.90698), (-0.47925, 0.74832))]

let falseTestCases =
  [((-0.99103, 0.43842), (0.78128, -0.10985), (-0.84714, -0.20558), (-0.08925, -0.78608)),
   ((0.15087, -0.56212), (-0.87374, -0.3787), (0.86403, 0.60374), (0.01392, 0.84362)),
   ((0.1114, 0.66496), (-0.92633, 0.27408), (0.92439, 0.43692), (0.8298, -0.29647)),
   ((0.87786, -0.8594), (-0.42283, -0.97999), (0.58659, -0.327), (-0.22656, 0.80896)),
   ((0.43525, -0.8923), (0.86119, 0.78278), (-0.01348, 0.98093), (-0.56244, -0.75129)),
   ((-0.73365, 0.28332), (0.63263, 0.17177), (-0.38398, -0.43497), (-0.31123, 0.73168)),
   ((-0.57694, -0.87713), (-0.93622, 0.89397), (0.93117, 0.40775), (0.2323, -0.30718)),
   ((0.91059, 0.75966), (0.60118, 0.73186), (0.32178, 0.88296), (-0.90087, -0.26367)),
   ((0.3463, -0.89397), (0.99108, 0.13557), (0.50122, -0.8724), (0.43385, 0.00167)),
   ((0.88121, 0.36469), (-0.29829, 0.21429), (0.31395, 0.2734), (0.43267, -0.78192))]

type Point = (Double, Double)

test :: [(Point, Point, Point, Point)] -> [Bool]
test testCases =
  map (\((px,py),(ax,ay),(bx,by),(cx,cy)) -> h (px,py) (ax,ay) (bx,by) (cx,cy)) testCases

test trueTestCases --> [True,True,True,True,True,True,True,True,True,True]
test falseTestCases --> [False,False,False,False,False,False,False,False,False,False]

Soluzioni non golfate:

type Point = (Double, Double)

-- using cross products

triangulate' (a, b) (p, q) (r, s) (t, u) =
  (side a b p q r s == side a b r s t u) && (side a b r s t u == side a b t u p q)
  where side j k l m n o = (o - m) * (j - l) + (-n + l) * (k - m) >= 0

-- using barycentric coordinates

triangulate :: (Point, Point, Point, Point) -> Bool
triangulate ((px, py), (ax, ay), (bx, by), (cx, cy)) = 
  let (p'x, p'y) = (px + (-ax), py + (-ay))
      (b'x, b'y) = (bx + (-ax), by + (-ay))
      (c'x, c'y) = (cx + (-ax), cy + (-ay))
      d = b'x * c'y - c'x * b'y
      a = (p'x * (b'y - c'y) + p'y * (c'x - b'x) + b'x * c'y - c'x * b'y) / d
      b = (p'x * c'y - p'y * c'x) / d
      c = (p'y * b'x - p'x * b'y) / d
  in
      (0 <= a && a < 1) && (0 <= b && b < 1) && (0 <= c && c < 1)

2

JavaScript (ES6) 120

C=(p,q,i,j,k,l,m,n,
 z=j*(m-k)+i*(l-n)+k*n-l*m,
 s=(j*m-i*n+(n-j)*p+(i-m)*q)/z,
 t=(i*l-j*k+(j-l)*p+(k-i)*q)/z
)=>s>0&t>0&s+t<1

Direttamente copiato dalla mia risposta a quest'altra domanda

Test nella console FireFox / FireBug

Emette tutti 1s

;[
C(-0.31961, -0.12646, 0.38478, 0.37419, -0.30613, -0.59754, -0.85548, 0.6633),
C(-0.87427, -0.00831, 0.78829, 0.60409, -0.90904, -0.13856, -0.80685, 0.48468),
C(0.28997, -0.03668, -0.28362, 0.42831, 0.39332, -0.07474, -0.48694, -0.10497),
C(-0.07783, 0.04415, -0.34355, -0.07161, 0.59105, -0.93145, 0.29402, 0.90334),
C(0.36107, 0.05389, 0.27103, 0.47754, -0.00341, -0.79472, 0.82549, -0.29028),
C(-0.01655, -0.20437, -0.36194, -0.90281, -0.26515, -0.4172, 0.36181, 0.51683),
C(-0.12198, -0.45897, -0.35128, -0.85405, 0.84566, 0.99364, 0.13767, 0.78618),
C(-0.03847, -0.81531, -0.18704, -0.33282, -0.95717, -0.6337, 0.10976, -0.88374),
C(0.07904, -0.06245, 0.95181, -0.84223, -0.75583, -0.34406, 0.16785, 0.87519),
C(-0.33485, 0.53875, -0.25173, 0.51317, -0.62441, -0.90698, -0.47925, 0.74832)
]

Emette tutti 0

;[
C(-0.99103, 0.43842,0.78128, -0.10985,-0.84714, -0.20558,-0.08925, -0.78608),
C(0.15087, -0.56212,-0.87374, -0.3787,0.86403, 0.60374,0.01392, 0.84362),
C(0.1114, 0.66496,-0.92633, 0.27408,0.92439, 0.43692,0.8298, -0.29647),
C(0.87786, -0.8594,-0.42283, -0.97999,0.58659, -0.327,-0.22656, 0.80896),
C(0.43525, -0.8923,0.86119, 0.78278,-0.01348, 0.98093,-0.56244, -0.75129),
C(-0.73365, 0.28332,0.63263, 0.17177,-0.38398, -0.43497,-0.31123, 0.73168),
C(-0.57694, -0.87713,-0.93622, 0.89397,0.93117, 0.40775,0.2323, -0.30718),
C(0.91059, 0.75966,0.60118, 0.73186,0.32178, 0.88296,-0.90087, -0.26367),
C(0.3463, -0.89397,0.99108, 0.13557,0.50122, -0.8724,0.43385, 0.00167),
C(0.88121, 0.36469,-0.29829, 0.21429,0.31395, 0.2734,0.43267, -0.78192)
]

2

SmileBASIC, 111 100 caratteri

DEF T X,Y,A,B,C,D,E,F
Q=9e5GCLS
GTRI(A-X)*Q,Q*(B-Y),Q*(C-X),Q*(D-Y),Q*(E-X),Q*(F-Y)?!!GSPOIT(0,0)END

Disegna un triangolo e controlla il colore del pixel nel punto. Il triangolo viene ridimensionato di 99999x e spostato in modo che il punto da verificare sia a (0,0) prima di essere disegnato, per ridurre al minimo la perdita di precisione.


2

Assemblaggio FPU Intel 8087, 222 220 byte

Utilizza solo l'hardware FPU 8087 per il calcolo. Ecco la versione non assemblata (anche in questo caso non risolta) come MACRO (ti risparmierà i 220 byte byte):

; calculate the area of of a triangle ABC using determinate
; input: coordinates (float), Ax,Ay,Bx,By,Cx,Cy
; output: area in ST
TAREA   MACRO   A1,A2,B1,B2,C1,C2
    FLD  A1
    FLD  B2
    FLD  C2
    FSUB        ; ST = By - Cy
    FMUL        ; ST = Ax * ( By - Cy )
    FLD  B1 
    FLD  C2
    FLD  A2
    FSUB        ; ST = Cy - Ay
    FMUL        ; ST = Bx * ( Cy - Ay )
    FLD  C1
    FLD  A2
    FLD  B2
    FSUB        ; Ay - By
    FMUL        ; Cx * ( Ay - By )
    FADD        ; Cx * ( Ay - By ) + Bx * ( Cy - Ay )
    FADD        ; Cx * ( Ay - By ) + Bx * ( Cy - Ay ) + Ax * ( By - Cy )
    FLD1        ; make a value of 2
    FADD ST,ST  ; ST = 2
    FDIV        ; divide by 2
    FABS        ; take abs value
        ENDM

; determine if point X is in triangle ABC
; input: points X, A, B, C
; output: ZF=1 if X in triangle, ZF=0 if X not in triangle
TXINABC     MACRO X1,X2,A1,A2,B1,B2,C1,C2

    TAREA  A1,A2,B1,B2,C1,C2    ; ST(3) = area of triangle ABC
    TAREA  X1,X2,B1,B2,C1,C2    ; ST(2) = area of triangle XBC
    TAREA  A1,A2,X1,X2,C1,C2    ; ST(1) = area of triangle AXC
    TAREA  A1,A2,B1,B2,X1,X2    ; ST(0) = area of triangle ABX

    FADD        ; add areas of triangles with point
    FADD        ; ST = ST + ST(1) + ST(2)
    FCOMPP      ; compare ST to ST(1) and pop results
    FWAIT       ; sync CPU/FPU
    FSTSW R     ; store result flags to R
    MOV  AX, R  ; move result to AX
    SAHF        ; store result into CPU flags for conditional check
        ENDM

Spiegazione

Utilizza il determinato per calcolare l'area del triangolo ABC, quindi il triangolo formato con il punto X e altri due punti del triangolo ABC. Se l'area del triangolo ABC è uguale alla somma delle aree dei triangoli XBC + AXC + ABX, il punto è all'interno del triangolo. Il risultato viene restituito come ZF.

Cosa c'è di bello in questo

Tutte le operazioni matematiche e in virgola mobile vengono eseguite in hardware con precisione estesa a 80 bit. Anche il confronto finale in virgola mobile viene eseguito in hardware, quindi sarà molto preciso.

Questo utilizza anche tutti e otto i registri dello stack dell'8087 contemporaneamente.

Cosa non è così pulito

Poiché i punti del triangolo devono essere ricollegati più volte alle formule durante il calcolo, è necessario che ciascuna variabile in memoria sia caricata nei registri dello stack della FPU una alla volta nell'ordine corretto. Mentre questo può essere modellato abbastanza facilmente come una funzione come MACRO, significa che il codice viene espanso ogni volta durante l'assemblaggio, creando codice ridondante. Sono stati salvati 41 byte spostando alcuni degli stessi segmenti di codice ripetuti in PROC. Tuttavia rende il codice meno leggibile, quindi l'elenco sopra è privo di esso (motivo per cui è etichettato come "non golfato").

test

Ecco un programma di test che utilizza IBM DOS che mostra l'output:

TTEST   MACRO T
        LOCAL IS_IN_TRI

    TXINABC T,T+4*1,T+4*2,T+4*3,T+4*4,T+4*5,T+4*6,T+4*7
    MOV  DX, OFFSET TEQ     ; load true string by default 
    JZ   IS_IN_TRI          ; if ZF=1, it is in triangle, skip to display
    MOV  DX, OFFSET FEQ     ; otherwise ZF=0 means not in triangle, so load false string
IS_IN_TRI:
    MOV  AH, 9              ; DOS write string function
    INT  21H 
        ENDM

START:
    FINIT                   ; reset 8087

    TTEST   T0              ; true tests
    TTEST   T1
    TTEST   T2
    TTEST   T3
    TTEST   T4
    TTEST   T5
    TTEST   T6
    TTEST   T7
    TTEST   T8
    TTEST   T9

    TTEST   F0              ; false tests
    TTEST   F1
    TTEST   F2
    TTEST   F3
    TTEST   F4
    TTEST   F5
    TTEST   F6  
    TTEST   F7
    TTEST   F8  
    TTEST   F9

    RET         ; return to DOS

T0  DD  -0.31961, -0.12646, 0.38478, 0.37419, -0.30613, -0.59754, -0.85548, 0.6633
T1  DD  -0.87427, -0.00831, 0.78829, 0.60409, -0.90904, -0.13856, -0.80685, 0.48468
T2  DD  0.28997, -0.03668, -0.28362, 0.42831, 0.39332, -0.07474, -0.48694, -0.10497
T3  DD  -0.07783, 0.04415, -0.34355, -0.07161, 0.59105, -0.93145, 0.29402, 0.90334
T4  DD  0.36107, 0.05389, 0.27103, 0.47754, -0.00341, -0.79472, 0.82549, -0.29028
T5  DD  -0.01655, -0.20437, -0.36194, -0.90281, -0.26515, -0.4172, 0.36181, 0.51683
T6  DD  -0.12198, -0.45897, -0.35128, -0.85405, 0.84566, 0.99364, 0.13767, 0.78618
T7  DD  -0.03847, -0.81531, -0.18704, -0.33282, -0.95717, -0.6337, 0.10976, -0.88374
T8  DD  0.07904, -0.06245, 0.95181, -0.84223, -0.75583, -0.34406, 0.16785, 0.87519
T9  DD  -0.33485, 0.53875, -0.25173, 0.51317, -0.62441, -0.90698, -0.47925, 0.74832

F0  DD  -0.99103, 0.43842, 0.78128, -0.10985, -0.84714, -0.20558, -0.08925, -0.78608
F1  DD  0.15087, -0.56212, -0.87374, -0.3787, 0.86403, 0.60374, 0.01392, 0.84362
F2  DD  0.1114, 0.66496, -0.92633, 0.27408, 0.92439, 0.43692, 0.8298, -0.29647
F3  DD  0.87786, -0.8594, -0.42283, -0.97999, 0.58659, -0.327, -0.22656, 0.80896
F4  DD  0.43525, -0.8923, 0.86119, 0.78278, -0.01348, 0.98093, -0.56244, -0.75129
F5  DD  -0.73365, 0.28332, 0.63263, 0.17177, -0.38398, -0.43497, -0.31123, 0.73168
F6  DD  -0.57694, -0.87713, -0.93622, 0.89397, 0.93117, 0.40775, 0.2323, -0.30718
F7  DD  0.91059, 0.75966, 0.60118, 0.73186, 0.32178, 0.88296, -0.90087, -0.26367
F8  DD  0.3463, -0.89397, 0.99108, 0.13557, 0.50122, -0.8724, 0.43385, 0.00167
F9  DD  0.88121, 0.36469, -0.29829, 0.21429, 0.31395, 0.2734, 0.43267, -0.78192

TEQ DB 'In Triangle',0DH,0AH,'$'
FEQ DB 'Not In Triangle',0DH,0AH,'$'

Produzione

In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle
Not In Triangle

1

C 414 (era 465)

golfed

#define D double 
int F(D ax,D ay,D bx,D by,D cx,D cy,D px,D py){int y=0;double J,K;D m=(ax-bx<0.001)?(by-ay)/(ax-bx):1000;D b=m*ax+ay;J=m*cx-cy+b;K=m*px-py+b;if(J*K>=0)y=1;return y;}D T[8],k;int i,n;void G(){while(i<8){scanf("%lf",&k);T[i++]=k;}n+=F(T[2],T[3],T[4],T[5],T[6],T[7],T[0],T[1]);n+=F(T[4],T[5],T[6],T[7],T[2],T[3],T[0],T[1]);n+=F(T[2],T[3],T[6],T[7],T[4],T[5],T[0],T[1]);printf(n==3?"True":"False");}

Dichiarazione di funzione originale aggiunta per spiegazione

/**
* determine if points C & P are on same side of line AB
* return 1 if true, 0 otherwise
*/
int PointsSameSide(D ax,D ay,D bx,D by,D cx, D cy, D px, D py);

Riscritto come una funzione denominata: input tramite stdin uno per riga o tutto in uno spazio separato da spazi.

#define D double
int F(D ax,D ay,D bx,D by,D cx, D cy, D px, D py)
{
int y=0;
double J,K;
D m = (ax-bx<0.001)?(by-ay)/(ax-bx):1000;
D b = m*ax+ay;
J=m*cx-cy+b;
K=m*px-py+b;
if(J*K>=0)y=1;
return y;
}
double T[8],k;
int i,n;
void G()
{
while(i<8){scanf("%lf",&k);T[i++]=k;}
n+=F(T[2],T[3],T[4],T[5],T[6],T[7],T[0],T[1]);
n+=F(T[4],T[5],T[6],T[7],T[2],T[3],T[0],T[1]);
n+=F(T[2],T[3],T[6],T[7],T[4],T[5],T[0],T[1]);
printf(n==3?"True":"False");
}

3
È possibile salvare alcuni byte eliminando nuove righe e spazi non necessari. Inoltre, hai doubleridefinito come Dma usi ancora doublenel codice.
gronostaj,

1

Java, 149 caratteri

g=Math.atan2(100*(d-y),(a-x));h=Math.atan2(100*(e-y),(b-x));i=Math.atan2(100*(f-y),(c-x));k=Math.round(Math.abs(g-h)+Math.abs(h-i)+Math.abs(i-g))==6;

Orribile considerando che devo scrivere "Matematica". ogni volta. Questo è il programma attuale:

package mathPackage;
public class InTriangle {
public static void main(String[] args) {
    boolean k;
    double a=-1,b=0,c=1,d=0,e=1,f=0,x=0,y=0.4;
    double g,h,i;
    g=Math.atan2(100*(d-y),(a-x));
    h=Math.atan2(100*(e-y),(b-x));
    i=Math.atan2(100*(f-y),(c-x));
    k=Math.round(Math.abs(g-h)+Math.abs(h-i)+Math.abs(i-g))==6;
    System.out.println(k);
    System.out.println(g);
    System.out.println(h);
    System.out.println(i);
    System.out.print(Math.abs(g-h)+Math.abs(h-i)+Math.abs(i-g));
}
}

dove a è la x del punto a, b è la x del punto b, c per x di c, d è y di a, e è y di b, f è la y di c, e x e y sono la x e y del punto. Il k booleano determina se è vero o no.


1
A cosa servono 100*?
xnor

1

JavaScript 125/198

Se vengono forniti punti in 8 argomenti:

function d(x,y,a,b,c,d,e,f){function z(a,b,c,d){return(y-b)*(c-a)-(x-a)*(d-b)>0}return(z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1}

Se i punti sono forniti in una matrice bidimensionale:

function c(s){return (z(s[1][0],s[1][1],s[2][0],s[2][1])+z(s[2][0],s[2][1],s[3][0],s[3][1])+z(s[3][0],s[3][1],s[1][0],s[1][1]))%3<1;function z(a,b,c,d){return (s[0][1]-b)*(c-a)-(s[0][0]-a)*(d-b)>0}}

Questo codice non usa nessuna di quelle fantasiose matematiche vettoriali. Invece, utilizza solo un semplice trucco di algebra per determinare se il punto si trova all'interno del triangolo o meno. La formula:

(y-b)(c-a) - (x-a)(d-b)

che indica che il punto si trova su quale lato di una linea , deriva dal riordinare la definizione di pendenza:

            m = (y2-y1)/(x2-x1)
      (y2-y1) = m(x2-x1)
       (y-y1) = m(x-x1)     ,substituting point we are testing (x,y) to be the 2nd point
       (y-y1) = (x-x1)(y2-y1)/(x2-x1)  ,substitute back the original definition of m
(y-y1)(x2-x1) = (x-x1)(y2-y1)    <-- left side will be greater than the right side, if
                                     the point is on the left; otherwise, it's on the right
            0 = (y-b)(c-a)-(x-a)(d-b) ,where (a,b)=(x1,y1), (c,d)=(x2,y2)

Se testiamo tutti e 3 i lati, tutti e 3 dovrebbero produrre alcuni numeri con lo stesso segno solo quando il punto si trova all'interno del triangolo poiché lo stiamo testando attorno al triangolo. Se il punto è su un lato, uno dei test dovrebbe restituire 0.

Codice test jsFiddle: http://jsfiddle.net/DerekL/zEzZU/

var l = [[-0.31961, -0.12646, 0.38478, 0.37419, -0.30613, -0.59754, -0.85548, 0.6633],[-0.87427, -0.00831, 0.78829, 0.60409, -0.90904, -0.13856, -0.80685, 0.48468],[0.28997, -0.03668, -0.28362, 0.42831, 0.39332, -0.07474, -0.48694, -0.10497],[-0.07783, 0.04415, -0.34355, -0.07161, 0.59105, -0.93145, 0.29402, 0.90334],[0.36107, 0.05389, 0.27103, 0.47754, -0.00341, -0.79472, 0.82549, -0.29028],[-0.01655, -0.20437, -0.36194, -0.90281, -0.26515, -0.4172, 0.36181, 0.51683],[-0.12198, -0.45897, -0.35128, -0.85405, 0.84566, 0.99364, 0.13767, 0.78618],[-0.03847, -0.81531, -0.18704, -0.33282, -0.95717, -0.6337, 0.10976, -0.88374],[0.07904, -0.06245, 0.95181, -0.84223, -0.75583, -0.34406, 0.16785, 0.87519],[-0.33485, 0.53875, -0.25173, 0.51317, -0.62441, -0.90698, -0.47925, 0.74832],
         [-0.99103, 0.43842, 0.78128, -0.10985, -0.84714, -0.20558, -0.08925, -0.78608],[0.15087, -0.56212, -0.87374, -0.3787, 0.86403, 0.60374, 0.01392, 0.84362],[0.1114, 0.66496, -0.92633, 0.27408, 0.92439, 0.43692, 0.8298, -0.29647],[0.87786, -0.8594, -0.42283, -0.97999, 0.58659, -0.327, -0.22656, 0.80896],[0.43525, -0.8923, 0.86119, 0.78278, -0.01348, 0.98093, -0.56244, -0.75129],[-0.73365, 0.28332, 0.63263, 0.17177, -0.38398, -0.43497, -0.31123, 0.73168],[-0.57694, -0.87713, -0.93622, 0.89397, 0.93117, 0.40775, 0.2323, -0.30718],[0.91059, 0.75966, 0.60118, 0.73186, 0.32178, 0.88296, -0.90087, -0.26367],[0.3463, -0.89397, 0.99108, 0.13557, 0.50122, -0.8724, 0.43385, 0.00167],[0.88121, 0.36469, -0.29829, 0.21429, 0.31395, 0.2734, 0.43267, -0.78192]];

function d(x,y,a,b,c,d,e,f){function z(a,b,c,d){return(y-b)*(c-a)-(x-a)*(d-b)>0}return(z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1}

for(var i = 0; i < l.length; i++){
    console.log(d.apply(undefined,l[i]));    //10 true, 10 false
}

97 caratteri (senza contare spazi o tabulazioni) contano se convertiti in CoffeeScript:

d=(x,y,a,b,c,d,e,f)->
    z=(a,b,c,d)->
        (y-b)*(c-a)-(x-a)*(d-b)>0
    (z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1

115 caratteri se convertiti in ES6:

d=(x,y,a,b,c,d,e,f)=>{z=(a,b,c,d)=>{return (y-b)*(c-a)-(x-a)*(d-b)>0};return(z(a,b,c,d)+z(c,d,e,f)+z(e,f,a,b))%3<1}

Questa è la "matematica vettoriale fantasiosa" che sto usando: D (non l'approccio coordinato baricentrico di fantasia che alcuni hanno adottato, però). Come la risposta più votata, è possibile salvare alcuni byte utilizzando ES6 e definendo funzioni come d=(x,y,...)=>{...}. Nel tuo caso, puoi risparmiare ancora di più usando CoffeeScript, che non è necessario return: pastebin.com/RVFk1D5k ... e in ogni caso puoi salvare un byte usando <1invece di ==0.
Martin Ender,

@ m.buettner: o Pensavo che l'equazione che ho usato non avesse nulla a che fare con i vettori (derivati ​​dalla semplice algebra) ma apparentemente entrambi producono la stessa equazione. La matematica è meravigliosa.
Derek 朕 會 功夫

1

R, 23

Ispirato da MATLAB ,

SDMTools::pnt.in.poly()

chiamato like SDMTools::pnt.in.poly(point,triangle)where pointè un vettore lunghezza 2 ed triangleè una matrice 3x2 di vertici. SDMTools è disponibile su CRAN.


1

Mathematica, 38 personaggi

RegionMember[Polygon[#[[1]]],#[[2]]] &

Esempio:

d = {{{0, 0}, {1, 0}, {.5, .7}}, {.5, .6}};

RegionMember[Polygon[#[[1]]], #[[2]]] & @ d

(* Vero *)


È normale contare gli spazi come personaggi, ma presumibilmente qui puoi rimuoverli senza che si rompano.
xnor

1
Inoltre, è necessario prendere input e produrre output anziché utilizzare variabili predefinite. Puoi cercare alcune risposte di Mathematica per vedere come lo fanno.
xnor

0

C (gcc) , 108 byte

i;f(a,b,c,d,e,f,g,h)float a,b,c,d,e,f,g,h;{i=(e-=a)*(h-=b)>(f-=b)*(g-=a);i=(c-=a)*f>(d-=b)*e==i&i==g*d>h*c;}

Provalo online!

Accetta tre prodotti incrociati e restituisce 1se il segno del componente non cambia.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.