Votre objectif est de déterminer si un point 2D donné X se situe dans la zone du triangle avec les sommets A, B, C donnés.
Ecrivez une fonction qui prend les coordonnées du point de test X et des trois sommets du triangle (donc 8 coordonnées au total) et renvoie Vrai si le point se trouve à l'intérieur de ce triangle et Faux s'il se trouve à l'extérieur.
Ne vous inquiétez pas des cas de bord. Si le point se trouve sur la limite du triangle (arête ou sommet) ou si le triangle est en fait un segment de ligne, votre code peut faire n'importe quoi, y compris un crash. Ne vous inquiétez pas non plus de la stabilité numérique ou de la précision en virgule flottante.
Votre code doit être une fonction nommée. Les extraits de code ne seront pas acceptés.
Le moins de personnages gagne.
Contribution:
Huit nombres réels représentant des coordonnées. Les chiffres vont se situer dans la plage (-1,1)
.
Le format d'entrée exact est flexible. Vous pouvez, par exemple, prendre huit chiffres, une liste de huit chiffres, une liste de quatre points chacun donnée par un tuple, une matrice 2 * 4, quatre nombres complexes, deux listes de coordonnées x et y, etc.
L'entrée doit simplement correspondre aux numéros d'un conteneur, sans données supplémentaires. Vous ne pouvez pas utiliser l'entrée pour effectuer un prétraitement, ni imposer de contrainte à l'entrée, telle que demander que les points soient donnés en coordonnée y ascendante. Votre entrée doit autoriser huit coordonnées (bien que votre code puisse se comporter de manière arbitraire dans les cas extrêmes mentionnés précédemment).
Veuillez indiquer votre format d'entrée.
Sortie:
Soit le booléen True
/ False
, le numéro 1
/ 0
, ou les analogues de votre langue.
Cas de test
Les entrées reçoivent une liste [X,A,B,C]
de quatre tuples, le point de test en premier, puis les trois sommets du triangle. Je les ai regroupés dans ceux dont les résultats devraient être True
et ceux qui devraient être False
.
True
instances:
[(-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
instances:
[(-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)]
Réponses:
Javascript / ECMAScript 6,
161159158/152Javascript:
Version ECMAScript 6 (merci m.buettner, enregistre 6 caractères)
Appelez-le comme tel (retourne
true
oufalse
):Utilise des calculs de coordonnées barycentriques sophistiqués basés sur le code de cette réponse . Voici une version non-golfée pour votre plus grand plaisir de lecture:
la source
(a*(l-n)+i*(g-e)+n*e-g*l)
au lieu de(-g*l+a*(-n+l)+i*(g-e)+n*e)
?Python 2,7
1281271171101091039995949190Ma première tentative de code-golf!
Code
Prend comme entrée (x, y, t) où (x, y) est le point que nous vérifions et t est un triangle t = ((x1, y1), (x2, y2), (x3, y3)).
Explication
Je calcule les déterminants des matrices
Ces déterminants représentent les distances signées entre les côtés du triangle et le point (x, y). S'ils ont tous le même signe, le point se trouve du même côté de chaque ligne et est donc contenu dans le triangle.
Dans le code ci-dessus,
a*y+c*b+d*x-d*a-c*y-b*x
est un déterminant de l'une de ces matrices.J'utilise le fait que
True+True+True==3
etFalse+False+False==0
pour déterminer si ces déterminants ont tous le même signe.Je me sers des index de liste négatifs de Python en utilisant à la
t[-1]
place det[(i+1)%3]
.Merci Peter pour l'idée d'utiliser
s%3<1
au lieu des in(0,3)
vérifier si s vaut 0 ou 3!Sagemath Version
Ce n'est pas vraiment une solution différente, alors je l'inclus dans cette réponse, une solution sagemath de 80 caractères:
où
p=[x,y]
ett=[[x1,y1],[x2,y2],[x3,y3]]
la source
s in (0,3)
être raccourci às%3<1
?-1,0,1 ... t[i]+t[i+1]
équivalent à0,1,2 ... t[i-1]+t[i]
in -1,0,1
avant de lire ceci. En fait, votre chemin est plus lisible, donc je l’utiliserai quand même.sum
si vous mettez les0,1,2
parenthèses, auquel cas un caractère en remplaçant un espace. La raison en est que Python autorise la transmission de la compréhension non encadrée dans des fonctions, mais les virgules du nuplet nu le1,2,3
confondent car il tente de les analyser en tant qu'arguments séparés.Mathematica, 67 octets
La fonction prend deux arguments, le point
X
et une liste de points{A,B,C}
, désignés respectivement par#
et#2
. C'est si vous appelezalors vous obtiendrez au
#
furX
et à#2
mesure{A,B,C}
. (Notez qu’il existe deux autres fonctions anonymes imbriquées dans le code#
et qu’elles#2
ont une signification différente.)Voici une explication de la fonction elle-même:
Notez que cette fonction fonctionnera réellement pour tout n-gon convexe tant que ses sommets sont donnés dans le sens horaire ou anti-horaire.
la source
Det
?CJam,
66635952463432313028 caractèresAprès avoir transformé la chaîne Unicode, le code suivant ( 33 octets ) est évalué:
Attend
X [A B C]
comme entrée, où chaque point est de la forme[double double]
. La sortie est 1 ou 0.Essayez-le en ligne.
Un grand merci à user23013 pour avoir enregistré 6 caractères (13 octets de code non compressé)!
Cas de test
la source
{
et}
et traitée comme une seule unité. Similaire aux blocs de code en C / java, les blocs exceptés sont des objets de première classe et peuvent être affectés à des variables (définissant ainsi des fonctions).1m<@m*
prépare 3 paires de X et le prochaini+1
sommet du triangle.@-@@-
déplace le (i
th) sommet actuel vers l'origine (et inversé s'il ne l'était pas@-\@-
, mais cela n'a pas d'importance).@@*@@*>
calcule l'axe z du produit croisé, dit déterminant, et retourne1
s'il est négatif.:+3%!
renvoie si elles sont toutes identiques, c'est-à-dire que les 3 sont négatives ou non négatives, ce qui signifie positives sauf pour les cas extrêmes. Je pense qu'il est plus difficile de lire CJam que de jouer au golf.{[_1m<\]z\f{f{+~@-@@-}~@@*@@*>})-!}:T
. Utilisez2m>
ouWm<
pour la sécurité Unicode.{2*2/\f{f{+~@-@@-}~@@*@@*>})-!}:T
C - 156 octets
Les entrées sont un tableau de 3 flottants dans X, 3 flotteurs dans Y et de séparer x et y pour le point de test. Bonus: gère tous les cas!
Adapté de PNPOLY.
la source
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 - testé en javascriptPyth 1.0.5 ,
575451Définit la fonction g, qui prend deux entrées: le point de test, puis la liste des sommets du triangle. Sorties
True
etFalse
. Remarque: détruit l'entrée, en particulier b, la liste des sommets du triangle.Essayez ici . Les derniers caractères
gvwvw
appellent la fonction avec un scénario de test sur les deux lignes suivantes.Basé sur cet algorithme
Explication:
La guerre CJam - Pyth continue!
la source
w
prendre l'entrée STDIN?Z
par un ensemble vide avec lequel vous vous êtes accumuléZ|=
, puis en tester la longueur pour voir s'il ne s'agit que0
de ou1
ont été vus? La stratégie s'est avérée plus longue en Python, mais peut-être que ça vaut la peine d'utiliser des primitives Pyth.J
6445 (42 sans affectation)L'affectation n'est pas nécessaire pour que la chose soit une fonction, il est donc incertain de la compter ou non. Profitant de l'entrée flexible: j'aimerais avoir un tableau de (1 + nombre de sommets) x (dimensionnalité de l'espace).
En espérant marquer quelques points supplémentaires ici ...: Cette chose fonctionne pour toutes les dimensions du simplexe, pas seulement les triangles dans un plan, mais également une pyramide à 3 faces dans un espace 3D, etc. Cela fonctionne également lorsque le nombre de sommets du simplex est inférieur à (n + 1), puis il calcule si la projection du point sur le simplex est à l'intérieur ou non.
Il convertit en coordonnées barycentriques , puis vérifie les négatives, indiquant que le point est à l'extérieur. Ne pense pas que J utilise _ pour négatif
Une analyse des exemples donnés:
la source
N+1
sommets maximum . Par exemple, une pyramide à 4 sommets dans un espace à trois dimensions ou un simplex à cinq sommets dans un espace à quatre dimensions. Le nombre de sommets peut être inférieur àN+1
. Dans ce cas, l'algorithme détermine si la projection orthogonale sur l'hyperplan du simplex réside ou non dans le simplex (par exemple, un simplex à 2 points en 2D sera projeté sur la ligne et coché). si cette projection se situe entre les points finaux)HTML5 + JS, 13b + 146b / 141b / 114 caractères
HTML:
JS (146b):
ou ES6 (141b):
ou ES6 unicode-obscurci (114 caractères):
démo: http://jsfiddle.net/xH8mV/
Obfuscation Unicode réalisée avec: http://xem.github.io/obfuscatweet/
la source
Python (65)
Les gens semblent avoir fini de soumettre, alors je vais poster ma propre solution à ma question.
X
est le nombre complexe représentant les points de test etL
est une liste de trois points, chacun étant un nombre complexe.Premièrement, je vais expliquer une version moins codée du code;
Nous décalons les points
A,B,C,X
pour qu'ilsX
soient à l'origine, tirant parti de l'arithmétique complexe intégrée de Python. Nous devons vérifier si l’origine est contenue dans la coque convexe deA,B,C
. Cela équivaut à l'origine se trouvant toujours du même côté (gauche ou droite) des segments AB, BC et AC.Un segment
AB
a l'origine sur la gauche si l'on se déplace dans le sens anti-horaire de moins de 180 degrés pour aller de A à B, et sur la droite sinon. Si nous considérons les anglesa
,b
etc
correspondant à ces points, cela signifieb-a < 180 degrees
(angles pris dans la plage de 0 à 360 degrés). Comme nombres complexes,angle(B/A)=angle(B)/angle(A)
. Aussi,angle(x) < 180 degrees
exactement pour le point dans le demi-plan supérieur, que nous vérifions viaimag(x)>0
.Ainsi, l’origine à gauche de AB est exprimée par
(A/B).imag>0
. En vérifiant si elles sont toutes égales pour chaque paire cyclique enA,B,C
nous indique si le triangleABC
contient l'origine.Revenons maintenant au code entièrement joué au golf
Nous générons chaque paire cyclique dans
(A-X,B-X,C-X)=(L[0]-X,L[1]-X,L[2]-X)
, en tirant parti des indices de liste Python négatifs qui enveloppent (L[-1]
=L[2]
). Pour vérifier que les Bools sont allTrue
(1
) ou allFalse
(0
), nous les ajoutons et vérifions la divisibilité par 3, à l'instar de nombreuses solutions.la source
Fortran -
232218195174C'est affreux. La fonction est épouvantable à cause du fait que les données lui sont transmises et nous ne pouvons pas le prétraiter.
La diminution de 14 caractères est due au fait que j'ai oublié de jouer au golf le nom de la fonction de mes tests. La diminution supplémentaire est due au typage implicite et à l’oubli du changement du nom de la fonction. Les 20 caractères suivants ont été supprimés suite à la lecture des points sous forme de tableau unique. Le programme complet est
la source
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);end
j'ai essayé de le raccourcir davantage en utilisant des opérations de liste, mais malheureusement, cela n'a pas très bien fonctionné.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);end
j'espère ne pas avoir commis d'erreur dans les transformations! Bien qu'il semble que votre code d'origine ne passe pas tous les tests.True
exemple dans OP donneFalse
si je permuteB
avecC
les valeurs de tout en donnantTrue
pour l’orientation originale.a < 0
, ce qui inverse la condition que vous devez tester. Malheureusement, cela ne peut pas simplement être corrigé en enveloppant le tout dans unabs
, comme dans le cas de la condition implicite,b
et end
ayant le même signe que celui quia
est perdu. Cela peut être corrigé en utilisant quelque chose comme (encore une fois, en réutilisant la notation et les variables prédéfinies de mon dernier commentaire)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)
- ce qui peut probablement être joué davantage au golf.MATLAB: 9!
Pas beaucoup de moi pour écrire ici
Peut être appelé comme suit:
La sortie est affectée à une variable nommée
ans
Si je devais écrire une fonction, ce pourrait être quelque chose comme ça, pourrait probablement être optimisé:
la source
f=@(a,b,c,d)inpolygon(a,b,c,d)
C # 218 (149?)
Probablement pas aussi efficace en caractères qu'une méthode mathématique, mais c'est une utilisation amusante des bibliothèques. Incidemment, aussi plutôt lent.
Tirez également parti de "Ne vous inquiétez pas non plus de la stabilité numérique ou de la précision en virgule flottante." - malheureusement,
GraphicsPath
utiliseint
s en interne, donc une valeur dans la plage -1 <f <1 ne peut avoir que trois valeurs possibles. Comme les flotteurs n'ont que 7 chiffres de précision, je multiplie simplement par 1e7 pour les transformer en nombres entiers. Hm, je suppose que ce n'est pas vraiment perdre toute précision. C'est aussi exploitable d'une autre manière: j'aurais probablement pu profiter d'ignorer la précision et simplement donner la "mauvaise" réponse.Si je suis autorisé à ignorer le coût en caractères d'importation de bibliothèques, 149 (à tout le moins,
System.Linq
etSystem.Drawing
sont assez standard sur la plupart des projets WinForms, maisSystem.Drawing.Drawing2D
peut être un peu exagéré):Programme de test (oui, c'est moche):
la source
Haskell -
233127Utilisation de produits croisés comme décrit ici :
Solution précédente mise en œuvre à l'aide de coordonnées barycentriques et des formules décrites dans cette réponse Stack Exchange :
Les deux fonctions
g
eth
prennent quatre paires, la première est le point à tester pour l'inclusion et le reste étant les coordonnées des sommets du triangle.Pour tester avec l'entrée d'exemple:
Solutions non-golfées:
la source
JavaScript (ES6) 120
Directement copié de ma réponse à Cette autre question
Test dans la console FireFox / FireBug
Sortie tous les 1
Sortir tous les 0
la source
SmileBASIC,
111100 caractèresDessine un triangle et vérifie la couleur du pixel au point. Le triangle est redimensionné à 99999x et décalé de manière à ce que le point à vérifier soit à (0,0) avant d'être tracé, afin de minimiser la perte de précision.
la source
Assemblage Intel 8087 FPU,
222220 octetsUtilise uniquement le matériel 8087 FPU à calculer. Voici la version non assemblée (ungolfed dans ce cas aussi) en tant que MACRO (vous épargnera les codes à 220 octets):
Explication
Utilise le déterminé pour calculer l'aire du triangle ABC, puis le triangle formé avec le point X et deux autres points du triangle ABC. Si l'aire du triangle ABC est égale à la somme des aires des triangles XBC + AXC + ABX, alors le point est dans le triangle. Le résultat est renvoyé sous forme de ZF.
Qu'est-ce qui est chouette
Toutes les opérations mathématiques et à virgule flottante sont effectuées de manière matérielle avec une précision étendue de 80 bits. La comparaison finale en virgule flottante est également effectuée dans le matériel, elle sera donc très précise.
Cela utilise également les huit registres de pile du 8087 en même temps.
Qu'est-ce qui n'est pas aussi net dans cette affaire?
Comme les points du triangle doivent être rebranchés à plusieurs reprises dans les formules pendant le calcul, il faut que chaque variable en mémoire soit chargée dans les registres de pile de la FPU, l'un après l'autre, dans le bon ordre. Bien que cela puisse être assez facilement modélisé comme une fonction en tant que MACRO, cela signifie que le code est développé à chaque assemblage, créant ainsi un code redondant. 41 octets ont été sauvegardés en déplaçant certains des mêmes segments de code répétés dans PROCs. Cependant, cela rend le code moins lisible, donc la liste ci-dessus est sans lui (c'est pourquoi il est étiqueté comme "non golfé").
Des tests
Voici un programme de test utilisant IBM DOS montrant la sortie:
Sortie
la source
C 414 (était 465)
Golfé
Déclaration de fonction originale ajoutée pour l'explication
Réécrit comme une fonction nommée: saisissez via stdin une ligne ou toutes les lignes en une ligne séparées par des espaces.
la source
double
redéfini commeD
mais vous utilisez toujoursdouble
dans le code.Java, 149 caractères
Horrible vu que je dois écrire "Math". à chaque fois. Voici le programme actuel:
où a est le x du point a, b est le x du point b, c pour x de c, d est y de a, e est y de b, f est le y de c, et x et y sont les x et y du point. Le booléen k détermine si c'est vrai ou pas.
la source
100*
pour?JavaScript 125/198
Si les points sont fournis dans 8 arguments:
Si des points sont fournis dans un tableau à 2 dimensions:
Ce code n'utilise aucun de ces mathématiques vectorielles fantaisie. Au lieu de cela, il n’utilise qu’une simple astuce algébrique pour déterminer si le point est à l’intérieur du triangle ou non. La formule:
qui dit que le point est de quel côté d'une ligne , est dérivé de la réorganisation de la définition de la pente:
Si nous testons les 3 côtés, tous les 3 devraient donner des nombres avec le même signe que lorsque le point est à l'intérieur du triangle, car nous le testons tout autour du triangle. Si le point est d'un côté, l'un des tests doit renvoyer 0.
Code de test jsFiddle: http://jsfiddle.net/DerekL/zEzZU/
Si 97 caractères (sans compter les espaces et les tabulations) sont convertis en CoffeeScript:
115 caractères si convertis en ES6:
la source
d=(x,y,...)=>{...}
. Dans votre cas, vous pouvez économiser encore plus en utilisant CoffeeScript, qui n'a pas besoin dereturn
: pastebin.com/RVFk1D5k ... et dans tous les cas, vous pouvez enregistrer un octet en utilisant à la<1
place de==0
.R, 23
Inspiré par MATLAB ,
appelé comme
SDMTools::pnt.in.poly(point,triangle)
oùpoint
est un vecteur de longueur 2 ettriangle
est une matrice de sommets 3x2. SDMTools est disponible sur CRAN.la source
Mathematica, 38 caractères
Exemple:
(* Vrai *)
la source
C (gcc) , 108 octets
Essayez-le en ligne!
Prend trois produits croisés et renvoie
1
si le signe duk̂
composant ne change pas.la source