Contexte
La coque convexe d'un nombre fini de points est le plus petit polygone convexe qui contient tous les points, soit sous forme de sommets, soit à l'intérieur. Pour plus d'informations, consultez cette question sur PGM qui la définit très bien .
Contribution
N+1
Les coordonnées 2D ( N >= 3
) sont passées STDIN
(avec d'autres entrées de golf habituelles également autorisées) dans le format suivant (le nombre de décimales peut varier mais vous pouvez supposer qu'il reste "raisonnable" et chaque nombre peut être représenté comme un flottant):
0.00;0.00000
1;0.00
0.000;1.0000
-1.00;1.000000
Production
Une valeur véridique imprimée sur STDOUT
(ou équivalent) si le premier point de la liste ( (0.00;0.00000)
dans l'exemple ci-dessus) se trouve dans la coque convexe des N autres points, et une valeur fausse sinon.
Il s'agit de code-golf , donc la solution la plus courte en octets l'emporte.
Cas frontaliers : vous pouvez renvoyer n'importe quelle valeur (mais ne vous écrasez pas) si le point se trouve sur le bord de la coque convexe (c'est-à-dire sur un côté ou sur un sommet à la frontière extérieure de la coque), car il s'agit d'une probabilité nulle événement (selon toute probabilité raisonnable).
Interdit : tout (langage, opérateur, structure de données, intégré ou package) qui existe uniquement pour résoudre des problèmes géométriques (par exemple ConvexHull de Mathematica ). Les outils mathématiques à usage général (vecteurs, matrices, nombres complexes, etc.) sont autorisés.
Les tests
- Devrait revenir
TRUE
: spiralTest1-TRUE , squareTest1-TRUE - Devrait revenir
FALSE
: spiralTest2-FALSE , squareTest2-FALSE
sort
ouround
. Je pense qu'il est plus clair de simplement dire que rien de spécifiquement conçu pour la géométrie n'est autorisé. Mais qu'en est-il d'une fonction pour ajouter deux listes comme vecteurs? Ou une fonction pour trouver l'argument (angle) d'un nombre complexe?Réponses:
J,
403934 octetsUne fonction dyadique anonyme, prenant un point, p , comme l'un de ses arguments, et une liste de points, P , comme l'autre argument (peu importe quel argument est lequel), et renvoyant
0
ou1
, si p est à l'extérieur ou à l'intérieur de la coque convexe de P , respectivement. Le point p et les points de P sont considérés comme des nombres complexes.Exemple
ou...
Python 2, fonction,
121103, programme complet,162Python 3, 149 octets
Prend l'entrée, dans le même format que le message d'origine, via STDIN, et imprime une valeur booléenne indiquant si p est dans la coque convexe de P
Explication
Le programme teste si la différence entre les angles maximum et minimum (signés) entre tout point r dans P , p et un point arbitraire fixe q dans P (nous utilisons simplement le premier point dans P ), est inférieure à 180 °. En d'autres termes, il teste si tous les points de P sont contenus dans un angle de 180 ° ou moins, autour de p . p est dans la coque convexe de P si et seulement si cette condition est fausse.
Au prix de quelques octets supplémentaires, nous pouvons utiliser une méthode similaire qui ne nous oblige pas à calculer explicitement les angles: Notez que la condition ci-dessus équivaut à dire que p est en dehors de la coque convexe de P si et seulement s'il existe une ligne l à p , de telle sorte que tous les points de P soient du même côté de l . Si une telle ligne existe, alors il y a aussi une telle ligne qui est incidente à un (ou plusieurs) des points de P (nous pouvons faire pivoter l jusqu'à ce qu'elle touche l'un des points de P ).
Pour (provisoirement) trouver cette ligne, nous commençons par laisser l être la ligne par p et le premier point P . Nous répétons ensuite le reste des points de P ; si l'un des points est à gauche de l (nous supposons que la directionnalité est partout, gauche ou droite n'a pas vraiment d'importance), nous remplaçons l par la ligne passant par p et ce point, et continuons. Après avoir itéré sur tout P , si (et seulement si) p est en dehors de la coque convexe, alors tous les points de P devraient être à droite de (ou sur) l . On vérifie qu'en utilisant un deuxième passage sur les points de P.
Python 2, 172 octets
Alternativement, pour faire la même chose en une seule passe, soit à gauche une représentation entre deux points quelconques, q et r , dans P , de telle sorte que q soit à gauche de r si q est à gauche de la ligne passant par p et r . On notera que to-the-gauche-de est une relation d'ordre sur P si et seulement si tous les points P sont du même côté d' une partie droite passant par p , qui est, si p est en dehors de l'enveloppe convexe de P . La procédure décrite ci-dessus trouve le point minimum dans Ppar rapport'a cet ordre, à savoir la « gauche » point P . Au lieu d'effectuer deux passes, nous pouvons trouver le maximum (c'est-à-dire, le point "le plus à droite"), ainsi que le minimum, les points en P par rapport au même ordre en une seule passe, et vérifier que le minimum est à gauche de la maximum, c'est-à-dire effectivement que celui de gauche est transitif.
Cela fonctionnerait bien si p est en dehors de la coque convexe de P , auquel cas à gauche est en fait une relation d'ordre, mais peut se casser lorsque p est à l'intérieur de la coque convexe (par exemple, essayez de comprendre ce qui va arriver si nous avons exécuté cet algorithme où les points dans P sont les sommets d'un pentagone régulier, dans le sens inverse des aiguilles d'une montre, et p est son centre.) Pour s'adapter, nous modifions légèrement l'algorithme: Nous sélectionnons un point q dans P , et bissectons P le long de la ligne passant par p et q (c'est-à-dire que nous partitionnons P autour de qpar rapport à gauche.) Nous avons maintenant une "partie gauche" et une "partie droite" de P , chacune contenue dans un demi-plan, de sorte que à gauche est une relation d'ordre sur chacune; nous trouvons le minimum de la partie gauche et le maximum de la partie droite et les comparons comme décrit ci-dessus. Bien sûr, nous n'avons pas à diviser physiquement P , nous pouvons simplement classer chaque point dans P en recherchant le minimum et le maximum, en une seule passe.
Python 2, 194 octets
la source
Octave,
8272 octetsL'idée est de vérifier si le programme linéaire min {c'x: Ax = b, e'x = 1, x> = 0} a une solution, où e est un vecteur de tous, les colonnes de A sont les coordonnées de le nuage de points, et b est le point de test, et c est arbitraire. En d'autres termes, nous essayons de représenter b comme une combinaison convexe de colonnes de A.
Pour exécuter le script, utilisez
octave -f script.m <input.dat
la source
R, 207 octets
Le script prend ses entrées de STDIN, par exemple
Rscript script.R < inputFile
.Il génère tous les triangles à partir des
N
derniers points (la dernière ligneapply(combn(...
) et vérifie si le premier point est dans le triangle à l'aide de lat
fonction.t
utilise la méthode area pour décider siU
est dansABC
: (écrire(ABC)
pour la zone deABC
)U
est dansABC
iff(ABC) == (ABU) + (ACU) + (BCU)
. De plus, les surfaces sont calculées en utilisant la formule déterminante (voir ici pour une belle démo de Wolfram).Je soupçonne que cette solution est plus sujette aux erreurs numériques que mon autre, mais elle fonctionne sur mes cas de test.
la source
R, 282 octets
Le script prend ses entrées de STDIN, par exemple
Rscript script.R < inputFile
.Il génère tous les triangles à partir des
N
derniers points (la dernière ligneapply(combn(...
) et vérifie si le premier point est dans le triangle à l'aide de lat
fonction.t
utilise la méthode barycentrique pour décider siU
est enABC
: (écritureXY
pour leX
auY
vecteur) depuis(AB,AC)
une base pour le plan ( à l' exception des cas dégénérés où A, B, C sont alignés),AU
peut être écrite commeAU = u.AB + v.AC
etU
est dans le triangle ssiu > 0 && v > 0 && u+v < 1
. Voir par exemple ici pour une explication plus détaillée et un joli graphique interactif. NB: pour enregistrer quelques caractères et éviter les erreurs DIV0, nous calculons uniquement un raccourci versu
etv
et un test modifié (min(u*k,v*k,k-u-v)>0
).Les seuls opérateurs mathématiques utilisés sont
+
,-
,*
,min()>0
.la source