Quelle est l'aire de ce polygone?


19

Calculez l'aire d'un polygone.

Inspiré par cette vidéo d'algorithme de lacet.

Tâche

Votre travail consiste à créer un programme ou une fonction qui calcule l'aire d'un polygone. Le programme ou la fonction est défini selon la définition par défaut de la méta.

Contribution

Vous recevrez les coordonnées X et Y de chaque sommet du polygone. Vous pouvez prendre l'entrée comme une liste de tuples ( [[x1, y1], [x2, y2], etc]), une matrice ou une liste plate ( [x1, y1, x2, y2, etc]). Deux listes contenant xet ycoordonnées respectivement sont également autorisées. Les sommets sont numérotés dans le sens antihoraire et le premier sommet est le même que le dernier sommet fourni, fermant ainsi le polygone.

Si vous le souhaitez, vous pouvez prendre l'entrée sans le dernier sommet (donc ne recevoir chaque coordonnée qu'une seule fois).

Vous pouvez supposer que les bords des polygones ne se coupent pas. Vous pouvez également supposer que tous les sommets ont des coordonnées entières.

Production

L'aire du polygone. Toutes les méthodes de sortie standard sont autorisées. Si votre langue ne permet pas la division flottante et que la solution ne serait pas un entier, vous êtes autorisé à renvoyer une fraction. La fraction ne doit pas nécessairement être simplifiée, donc le retour 2/4serait autorisé.

Critère gagnant

Le code le plus court gagne!

Cas de test

[[4,4],[0,1],[-2,5],[-6,0],[-1,-4],[5,-2],[4,4]]
55

entrez la description de l'image ici

[[1,1],[0,1],[1,0],[1,1]]
0.5
1/2

entrez la description de l'image ici


L'entrée est-elle [x1, x2, x3], [y1, y2, y3]autorisée?
programmer5000

@ programmer5000 et Martin Ender, oui, je vais le modifier :)
JAD

Je suis d'accord, a voté pour la réouverture.
programmer5000

1
@flawr J'en ai fait une dupe. Ce n'est pas vraiment une dupe de sa cible de dupe, qui, pour appliquer la même méthode qu'ici de manière récursive, nécessiterait de trouver les sommets qui sont des points de croisement et nécessiterait de classer les sous-ensembles résultants dans le sens antihoraire - cela semble beaucoup plus complexe.
Jonathan Allan

Réponses:


13

Gelée ,  8  6 octets

-1 octet grâce à Emigna (redondant , ÆḊa une profondeur à gauche de 2)
-1 octet grâce à Emigna, encore une fois (diviser par deux,, la Hvirgule flottante n'est pas nécessaire ÷2)

ṡ2ÆḊSH

Un lien monadique prenant une liste de paires de coordonnées dans le sens antihoraire selon les exemples (avec une répétition) et retournant la zone.

Essayez-le en ligne!

Comment?

Applique l'algorithme du lacet, tel que décrit dans la vidéo (que j'ai également regardé l'autre jour!)

ṡ2ÆḊSH - Link: list of [x,y] coordinate pairs anticlockwise & wrapped, p
ṡ2     - all overlapping slices of length 2
  ÆḊ   - determinant (vectorises)
    S  - sum
     H - halve

Le deuxième cas de test retourne `-0,5` pour moi: o
JAD

Oh, je vais devoir vérifier ...
Jonathan Allan

C'est parce que les [x,y]coordonnées sont données dans le sens horaire plutôt que dans le sens antihoraire. Une entrée de [[1,1],[0,1],[1,0],[1,1]]renverra a 0.5.
Jonathan Allan

1
Woops, je vais modifier ça: D
JAD

1
Aussi, Hau lieu de÷2
Emigna



16

JavaScript (ES6), 69 67 47 octets

Merci à @Rick d'avoir remarqué que nous n'avons pas besoin de la valeur absolue si les sommets sont garantis pour être triés dans le sens antihoraire et d'avoir suggéré de prendre une liste plate en entrée, économisant 20 octets!

Prend l'entrée comme une liste plate de sommets, y compris le dernier sommet.

f=([x,y,...a])=>1/a[0]?x*a[1]/2-y*a[0]/2+f(a):0

Essayez-le en ligne!

Comment?

n

area=|(x0y1y0x1)+(x1y2y1x2)++(xn1y0yn1x0)2|


Très impressionnant! Pourriez-vous expliquer comment cela fonctionne?
Rugnir

Les sommets du deuxième cas de test ont été mal classés par erreur. Les abdominaux ne devraient pas être nécessaires.
Rick

Vous pouvez également enregistrer 7 octets en passant à une liste plate:a=>(g=([x,y,...a])=>1-a?0:x*a[1]-y*a[0]+g(a))(a)/2
Rick

@Rick a raison - les abs ne sont pas nécessaires. Sans elle, la formule calcule la zone signée, ce qui est positif car les sommets sont donnés dans le sens antihoraire.
Angs

@Rick Merci! Mis à jour ... environ 10 mois plus tard: /
Arnauld

7

R, 54 52 octets

pryr::f({for(i in 2:nrow(x))F=F+det(x[i-1:0,]);F/2})

Qui évalue à la fonction:

function (x) 
{
    for (i in 2:nrow(x)) F = F + det(x[i - 1:0, ])
    F/2
}

Utilise le prédéfini F = FALSE = 0. Implémente l'algorithme de lacet dans la vidéo liée :)

-2 octets grâce à Giuseppe


-1 octet i+-1:0comme index de ligne
Giuseppe

@Giuseppe Nice. J'enlèverai +aussi le;)
JAD

6

Python 3 , 72 71 octets

from numpy import*
g=lambda x,y:(dot(x[:-1],y[1:])-dot(x[1:],y[:-1]))/2

Prend deux listes, comme cela a été autorisé dans les commentaires

x = [x0,x1,x2, ...]
y = [y0,y1,y2, ...] 

Essayez-le en ligne!

Il s'agit essentiellement de la mise en œuvre de la formule du lacet . Puis-je obtenir des points positifs pour un golf que vous mettriez en œuvre comme ça? :RÉ

-1, il n'y a pas besoin d'espace derrière x,y:.



Prendre deux listes est également mentionné dans le corps de la question maintenant :)
JAD

@JarkoDubbeldam Euh, je viens de voir, qu'il doit sortir la zone. Cette solution ne renvoie actuellement que la zone. Est-ce également permis ou faut-il l'imprimer?
P. Siehr

Une fonction renvoyant une valeur compte comme sortie :)
JAD

Je pense qu'avec python, vous n'avez même pas besoin de nommer la fonction, donc commencer avec lambda x,y:est bien.
JAD

@JarkoDubbeldam Existe-t-il des règles quelque part pour chaque langue?
P. Siehr


4

JS (ES6), 98 95 94 93 88 86 82 81 77 73 octets

(X,Y)=>{for(i in X){a+=(X[i]+X[i-1])*(Y[i]-Y[i-1]);if(!+i)a=0}return a/2}

Prend l'entrée comme [x1, x2, x3], [y1, y2, y3]et ignore la paire de coordonnées répétée.

-3 octets grâce à @JarkoDubbeldam

-4 octets grâce à @JarkoDubbeldam

-1 octet grâce à @ZacharyT

-4 octets grâce à @ZacharyT

-4 octets grâce à @Rick


3

J, 12 octets

En supposant que l'entrée est une liste de 2 listes d'éléments (c'est-à-dire un tableau)

-:+/-/ .*2[\
  • 2[\ - le décompose en lacet Xs, c'est-à-dire en carrés superposés de 4 ormes
  • -/ .* - le déterminant de chacun
  • +/ - résume
  • -: - diviser par 2

Si nous obtenons l'entrée comme une seule liste, nous devons d'abord nous transformer en table, en nous donnant 20 octets:

-:+/-/ .*2[\ _2&(,\)

1
"En supposant que l'entrée est une liste de 2 listes d'éléments (c'est-à-dire une table)" Ceci est autorisé :)
JAD

3

MS-SQL, 66 octets

SELECT geometry::STPolyFromText('POLYGON('+p+')',0).STArea()FROM g

MS SQL 2008 et les versions supérieures prennent en charge les données / fonctions spatiales standard du Open Geospatial Consortium (OGC), dont je profite ici.

Les données d'entrée sont stockées dans le champ p du tableau g préexistant , selon nos normes d'entrée .

La saisie est un champ de texte avec des paires ordonnées au format suivant: (4 4,0 1,-2 5,-6 0,-1 -4,5 -2,4 4)

Maintenant, juste pour le plaisir, si vous autorisez ma table d' entrée à contenir des objets de géométrie standard Open Geospatial Consortium (au lieu de simplement des données de texte), cela devient presque trivial:

--Create and populate input table, not counted in byte total
CREATE TABLE g (p geometry)
INSERT g VALUES (geometry::STPolyFromText('POLYGON((5 5, 10 5, 10 10, 5 5))', 0))

--23 bytes!
SELECT p.STArea()FROM g


0

Perl 5 -pa , 62 octets

map$\+=$F[$i]*($a[($i+1)%@a]-$a[$i++-1]),@a=eval<>}{$\=abs$\/2

Essayez-le en ligne!

Prend la saisie sous la forme d'une liste de coordonnées X sur la première ligne suivie d'une liste de coordonnées Y sur la seconde.

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.