¿Cuál es el área de este polígono?


19

Calcular el área de un polígono.

Inspirado en este video del algoritmo de cordones.

Tarea

Su trabajo es crear un programa o función que calcule el área de un polígono. El programa o función se define según la definición predeterminada en meta.

Entrada

Recibirá las coordenadas X e Y de cada vértice del polígono. Puede tomar la entrada como una lista de tuplas ( [[x1, y1], [x2, y2], etc]), una matriz o una lista plana ( [x1, y1, x2, y2, etc]). También se permiten dos listas que contienen xy ycoordenadas respectivamente. Los vértices están numerados en sentido antihorario y el primer vértice es el mismo que el último vértice proporcionado, cerrando así el polígono.

Si lo desea, puede tomar la entrada sin el último vértice (así que reciba cada coordenada solo una vez).

Puede suponer que los bordes de los polígonos no se cruzan. También puede suponer que todos los vértices tienen coordenadas enteras.

Salida

El área del polígono. Todos los métodos de salida estándar están permitidos. Si su idioma no permite la división flotante y la solución no sería un número entero, puede devolver una fracción. La fracción no necesariamente tiene que simplificarse, por 2/4lo que se permitiría el retorno .

Criterio ganador

¡El código más corto gana!

Casos de prueba

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

ingrese la descripción de la imagen aquí

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

ingrese la descripción de la imagen aquí


¿Se [x1, x2, x3], [y1, y2, y3]permite la entrada como ?
programmer5000

@ programmer5000 y Martin Ender, sí, lo editaré en :)
JAD

Estoy de acuerdo, voté para reabrir.
programmer5000

1
@flawr Lo hice un engaño de esto. No es realmente un engaño de su objetivo de engaño, que aplicar el mismo método que aquí recursivamente requeriría encontrar los vértices que son puntos de cruce y requeriría ordenar los subconjuntos resultantes en sentido antihorario, lo que parece mucho más complejo.
Jonathan Allan

Respuestas:


13

Jalea ,  8  6 bytes

-1 byte gracias a Emigna (redundante , ÆḊtiene una profundidad izquierda de 2)
-1 byte gracias a Emigna, nuevamente (reducir a la mitad H, es punto flotante no es necesario ÷2)

ṡ2ÆḊSH

Un enlace monádico que toma una lista de pares de coordenadas en sentido antihorario según los ejemplos (con una repetición) y devuelve el área.

Pruébalo en línea!

¿Cómo?

Aplica el algoritmo de cordones de los zapatos, tal como se describe en el video (¡que también vi el otro día!)

ṡ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

El segundo caso de prueba devuelve `-0.5` para mí: o
JAD

Oh, tendré que echarle un vistazo ...
Jonathan Allan

Esto se debe a que las [x,y]coordenadas se dan en sentido horario en lugar de hacerlo en sentido antihorario. Una entrada de [[1,1],[0,1],[1,0],[1,1]]devolverá a 0.5.
Jonathan Allan

1
Woops, lo editaré: D
JAD

1
Además, en Hlugar de÷2
Emigna



16

JavaScript (ES6), 69 67 47 bytes

Gracias a @Rick por notar que no necesitamos el valor absoluto si se garantiza que los vértices estén ordenados en sentido antihorario y por sugerir tomar una lista plana como entrada, ¡ahorrando 20 bytes!

Toma la entrada como una lista plana de vértices, incluido el último vértice.

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

Pruébalo en línea!

¿Cómo?

norte

unrmiun=El |(X0 0y1-y0 0X1)+(X1y2-y1X2)+...+(Xnorte-1y0 0-ynorte-1X0 0)2El |


¡Muy impresionante! ¿Podrías explicar cómo funciona?
Rugnir

Los vértices en el segundo caso de prueba se ordenaron por error de forma incorrecta. Los abdominales no deberían ser necesarios.
Rick

También puede guardar 7 bytes cambiando a una lista plana:a=>(g=([x,y,...a])=>1-a?0:x*a[1]-y*a[0]+g(a))(a)/2
Rick

@Rick tiene razón: los abdominales no son necesarios. Sin ella, la fórmula calcula el área firmada, lo cual es positivo porque los vértices se dan en el sentido contrario a las agujas del reloj.
Angs

@ Rick Gracias! Actualizado ... unos 10 meses después: /
Arnauld

7

R, 54 52 bytes

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

Lo que evalúa la función:

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

Hace uso de lo predefinido F = FALSE = 0. Implementa el algoritmo de cordones en el video vinculado :)

-2 bytes gracias a Giuseppe


-1 byte i+-1:0como índice de fila
Giuseppe

@Giuseppe Nice. También lo quitaré +;)
JAD

6

Python 3 , 72 71 bytes

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

Toma dos listas, como se permitió en los comentarios

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

Pruébalo en línea!

Esto es básicamente solo la implementación de la fórmula del cordón . ¿Puedo obtener puntos adicionales para un golf que realmente implementaría de esa manera? :RE

-1, no hay necesidad de un espacio detrás x,y:.



Tomar dos listas también se menciona en el cuerpo de la pregunta ahora :)
JAD

@JarkoDubbeldam Uh, acabo de ver que tiene que dar salida al área. Esta solución actualmente solo devuelve el área. ¿Eso también está permitido o se imprimirá?
P. Siehr

Una función que devuelve un valor cuenta como salida :)
JAD

Creo que con python ni siquiera tiene que nombrar la función, por lo que solo comenzar lambda x,y:está bien.
JAD

@JarkoDubbeldam ¿Hay reglas en algún lugar para cada idioma?
P. Siehr


4

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

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

Toma como entrada [x1, x2, x3], [y1, y2, y3]y omite el par coordinado repetido.

-3 bytes gracias a @JarkoDubbeldam

-4 bytes gracias a @JarkoDubbeldam

-1 byte gracias a @ZacharyT

-4 bytes gracias a @ZacharyT

-4 bytes gracias a @Rick


3

J, 12 bytes

Suponiendo que la entrada es una lista de 2 listas de elementos (es decir, una tabla)

-:+/-/ .*2[\
  • 2[\ - lo descompone en el cordón X, es decir, cuadrados superpuestos de 4 olmos
  • -/ .* - el determinante de cada
  • +/ - suma
  • -: - dividir por 2

Si obtenemos la entrada como una lista única, primero debemos transformarnos en una tabla, lo que nos da 20 bytes:

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

1
"Suponiendo que la entrada es una lista de 2 listas de elementos (es decir, una tabla)" Esto está permitido :)
JAD

3

MS-SQL, 66 bytes

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

MS SQL 2008 y superior son compatibles con los datos / funciones espaciales estándar del Open Geospatial Consortium (OGC), que estoy aprovechando aquí.

Los datos de entrada se almacenan en el campo p de la tabla g preexistente , según nuestros estándares de entrada .

La entrada es un campo de texto con pares ordenados en el siguiente formato: (4 4,0 1,-2 5,-6 0,-1 -4,5 -2,4 4)

Ahora, solo por diversión, si permitiste que mi tabla de entrada contenga objetos de geometría estándar del Consorcio Geoespacial Abierto (en lugar de solo datos de texto), entonces se vuelve casi 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 bytes

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

Pruébalo en línea!

Toma la entrada como una lista de coordenadas X en la primera línea seguida de una lista de coordenadas Y en la segunda.

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.