Qual è l'area di questo poligono?


19

Calcola l'area di un poligono.

Ispirato da questo video dell'algoritmo del laccio.

Compito

Il tuo compito è creare un programma o una funzione che calcoli l'area di un poligono. Il programma o la funzione sono definiti in base alla definizione predefinita in meta.

Ingresso

Riceverai le coordinate X e Y di ciascun vertice del poligono. Puoi prendere l'input come un elenco di tuple ( [[x1, y1], [x2, y2], etc]), una matrice o un elenco piatto ( [x1, y1, x2, y2, etc]). Due liste contenenti xe ycoordinate rispettivamente sono consentiti pure. I vertici sono numerati in senso antiorario e il primo vertice è lo stesso dell'ultimo vertice fornito, chiudendo così il poligono.

Se vuoi puoi prendere l'input senza l'ultimo vertice (quindi ricevi ogni coordinata una sola volta).

Puoi presumere che i bordi dei poligoni non si intersecano. Puoi anche supporre che tutti i vertici abbiano coordinate intere.

Produzione

L'area del poligono. Sono consentiti tutti i metodi di output standard. Se la tua lingua non consente la divisione float e la soluzione non sarebbe un numero intero, puoi restituire una frazione. La frazione non deve necessariamente essere semplificata, quindi il ritorno 2/4sarebbe consentito.

Criteri vincenti

Vince il codice più corto!

Casi test

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

inserisci qui la descrizione dell'immagine

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

inserisci qui la descrizione dell'immagine


L'input è [x1, x2, x3], [y1, y2, y3]consentito?
programmatore

@ programmer5000 e Martin Ender, sì, lo modificherò in :)
JAD

Sono d'accordo, ho votato per riaprire.
programmatore

1
@flawr L'ho trasformato in un inganno. Non è in realtà un duplicato del suo target dupe, che per applicare lo stesso metodo qui ricorsivamente richiederebbe di trovare i vertici che attraversano i punti e richiederebbe di ordinare i sottoinsiemi risultanti in modo antiorario - sembra molto più complesso.
Jonathan Allan,

Risposte:


13

Gelatina ,  8  6 byte

-1 byte grazie a Emigna (ridondante , ÆḊha una profondità sinistra di 2)
-1 byte grazie a Emigna, di nuovo (dimezzare H, è in virgola mobile non è necessario ÷2)

ṡ2ÆḊSH

Un collegamento monadico che prende un elenco di coppie di coordinate in senso antiorario come da esempi (con una ripetizione) e restituisce l'area.

Provalo online!

Come?

Applica l'algoritmo del laccio, proprio come descritto nel video (che mi è capitato di vedere anche l'altro giorno!)

ṡ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

Il secondo test-case restituisce `-0.5` per me: o
JAD

Oh, dovrò dare un'occhiata ...
Jonathan Allan,

Questo perché le [x,y]coordinate vengono fornite in senso orario anziché in senso antiorario. Un input di [[1,1],[0,1],[1,0],[1,1]]restituirà a 0.5.
Jonathan Allan,

1
Accidenti, lo modificherò: D
JAD

1
Inoltre, Hinvece di÷2
Emigna il



16

JavaScript (ES6), 69 67 47 byte

Grazie a @Rick per aver notato che non abbiamo bisogno del valore assoluto se i vertici sono garantiti per essere ordinati in senso antiorario e per aver suggerito di prendere una lista piatta come input, risparmiando 20 byte!

Accetta l'input come un elenco semplice di vertici, incluso l'ultimo vertice.

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

Provalo online!

Come?

n

un'reun'=|(X0y1-y0X1)+(X1y2-y1X2)+...+(Xn-1y0-yn-1X0)2|


Molto impressionante! Potresti spiegare come funziona?
Rugnir,

I vertici nel secondo caso di test sono stati erroneamente ordinati in modo errato. Gli addominali non dovrebbero essere necessari.
Rick,

Puoi anche salvare 7 byte passando a un elenco semplice:a=>(g=([x,y,...a])=>1-a?0:x*a[1]-y*a[0]+g(a))(a)/2
Rick

@Rick ha ragione: gli addominali non sono necessari. Senza di essa la formula calcola l'area con segno, il che è positivo perché i vertici sono indicati in senso antiorario.
Angs

@Rick Grazie! Aggiornato ... circa 10 mesi dopo: /
Arnauld

7

R, 54 52 byte

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

Che valuta la funzione:

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

Utilizza il predefinito F = FALSE = 0. Implementa l'algoritmo del laccio nel video collegato :)

-2 byte grazie a Giuseppe


-1 byte per i+-1:0come indice di riga
Giuseppe

@Giuseppe Nice. Rimuoverò +anche quello;)
JAD

6

Python 3 , 72 71 byte

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

Prende due elenchi, come era consentito nei commenti

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

Provalo online!

Questo è fondamentalmente solo l'implementazione della formula del laccio . Posso ottenere punti positivi per un golf che realizzeresti in questo modo? : D

-1, non è necessario uno spazio dietro x,y:.



Prendere due liste è anche menzionato nel corpo della domanda ora :)
JAD

@JarkoDubbeldam Uh, ho appena visto, che deve emettere l'area. Questa soluzione attualmente restituisce solo l'area. Anche quello è permesso o deve essere stampato?
P. Siehr,

Una funzione che restituisce un valore conta come output :)
JAD

Penso che con Python non sia nemmeno necessario nominare la funzione, quindi solo iniziare con lambda x,y:va bene.
JAD,

@JarkoDubbeldam Esistono regole per ogni lingua?
P. Siehr,


4

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

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

Accetta input simili [x1, x2, x3], [y1, y2, y3]e salta la coppia di coord ripetute.

-3 byte grazie a @JarkoDubbeldam

-4 byte grazie a @JarkoDubbeldam

-1 byte grazie a @ZacharyT

-4 byte grazie a @ZacharyT

-4 byte grazie a @Rick


3

J, 12 byte

Supponendo che l'ingresso sia un elenco di 2 elenchi di elementi (ovvero una tabella)

-:+/-/ .*2[\
  • 2[\ - lo scompone nei lacci delle scarpe Xs, cioè quadrati sovrapposti di 4 elmi
  • -/ .* - il determinante di ciascuno
  • +/ - riassumilo
  • -: - dividere per 2

Se riceviamo l'input come un unico elenco, dobbiamo prima trasformarci in una tabella, dandoci 20 byte:

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

1
"Supponendo che l'input sia un elenco di 2 elenchi di elementi (ovvero una tabella)" Questo è consentito :)
JAD

3

MS-SQL, 66 byte

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

MS SQL 2008 e versioni successive supportano dati / funzioni spaziali standard Open Geospatial Consortium (OGC), di cui sto approfittando qui.

I dati di input sono memorizzati nel campo p della tabella g preesistente , secondo i nostri standard di input .

L'input è un campo di testo con coppie ordinate nel seguente formato: (4 4,0 1,-2 5,-6 0,-1 -4,5 -2,4 4)

Ora, solo per divertimento, se hai permesso alla mia tabella di input di contenere oggetti geometrici standard del Consorzio Open Geospatial (anziché solo dati di testo), allora diventa quasi banale:

--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 byte

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

Provalo online!

Prende l'input come un elenco di coordinate X sulla prima riga seguito da un elenco di coordinate Y sulla seconda.

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.