Qual é a área desse polígono?


19

Calcule a área de um polígono.

Inspirado neste vídeo do algoritmo do cadarço.

Tarefa

Seu trabalho é criar um programa ou função que calcule a área de um polígono. Programa ou função é definido de acordo com a definição padrão no meta.

Entrada

Você receberá as coordenadas X e Y de cada vértice do polígono. Você pode considerar a entrada como uma lista de tuplas ( [[x1, y1], [x2, y2], etc]), uma matriz ou uma lista simples ( [x1, y1, x2, y2, etc]). Também são permitidas duas listas contendo xe ycoordenadas, respectivamente. Os vértices são numerados no sentido anti-horário e o primeiro vértice é o mesmo que o último vértice fornecido, fechando o polígono.

Se você quiser, pode pegar a entrada sem o último vértice (então receba cada coordenada apenas uma vez).

Você pode supor que as arestas dos polígonos não se cruzam. Você também pode assumir que todos os vértices têm coordenadas inteiras.

Resultado

A área do polígono. Todos os métodos de saída padrão são permitidos. Se o seu idioma não permitir a divisão de flutuação e a solução não for um número inteiro, você poderá retornar uma fração. A fração não precisa necessariamente ser simplificada, portanto o retorno 2/4seria permitido.

Critério de vitória

O código mais curto vence!

Casos de teste

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

insira a descrição da imagem aqui

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

insira a descrição da imagem aqui


A entrada é como [x1, x2, x3], [y1, y2, y3]permitida?
programmer5000

@ programmer5000 e Martin Ender, sim, eu vou editá-lo no :)
JAD

Concordo, votei para reabrir.
programmer5000

11
Flawr @ eu fiz isso um burro disso. Não é realmente um engano de seu alvo enganador, que para aplicar o mesmo método que aqui recursivamente exigiria encontrar os vértices que são pontos de cruzamento e exigiria ordenar os subconjuntos resultantes no sentido anti-horário - isso parece muito mais complexo.
Jonathan Allan

Respostas:


13

Geléia ,  8  6 bytes

-1 byte graças a Emigna (redundante , ÆḊtem uma profundidade esquerda de 2)
-1 byte graças a Emigna, novamente (metade,, Hé ponto flutuante, não é necessário ÷2)

ṡ2ÆḊSH

Um link monádico que obtém uma lista de pares de coordenadas no sentido anti-horário, conforme os exemplos (com uma repetição) e retorna a área.

Experimente online!

Quão?

Aplica o algoritmo do cadarço, conforme descrito no vídeo (que aconteceu também no outro dia!)

ṡ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

O segundo caso de teste retorna `-0,5` para mim: o
JAD

Ah, eu vou ter que dar uma olhada ...
Jonathan Allan

Isso porque, como [x,y]coordenadas, elas são dadas no sentido horário, e não no sentido anti-horário. Uma entrada de [[1,1],[0,1],[1,0],[1,1]]retornará a 0.5.
Jonathan Allan

11
Woops, eu vou editar isso: D
JAD

11
Além disso, em Hvez de÷2
Emigna 14/06



16

JavaScript (ES6), 69 67 47 bytes

Agradecemos ao @Rick por perceber que não precisamos do valor absoluto se os vértices tiverem a classificação ordenada no sentido anti-horário e por sugerir uma lista simples como entrada, economizando 20 bytes!

Recebe a entrada como uma lista plana de vértices, incluindo o último vértice.

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

Experimente online!

Quão?

n

area=|(x0y1y0x1)+(x1y2y1x2)+...+(xn-1 1y0 0-yn-1 1x0 0)2|


Muito impressionante! Você poderia explicar como isso funciona?
Rugnir

Os vértices no segundo caso de teste foram ordenados incorretamente incorretamente. Os abdominais não devem ser necessários.
Rick

Você também pode salvar 7 bytes alternando para uma lista simples:a=>(g=([x,y,...a])=>1-a?0:x*a[1]-y*a[0]+g(a))(a)/2
Rick

@ Rick está certo - o abs não é necessário. Sem ela, a fórmula calcula a área assinada, o que é positivo porque os vértices são dados na ordem anti-horária.
Angs

@ Rick Obrigado! Atualizado ... cerca de 10 meses depois: /
Arnauld 25/04

7

R, 54 52 bytes

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

Que avalia a função:

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

Faz uso do predefinido F = FALSE = 0. Implementa o algoritmo do cadarço no vídeo vinculado :)

-2 bytes graças a Giuseppe


-1 byte para i+-1:0o índice de linha
Giuseppe

@Giuseppe Nice. Vou remover o +bem;)
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

Leva duas listas, como foi permitido nos comentários

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

Experimente online!

Isso é basicamente apenas a implementação da fórmula do cadarço . Posso obter pontos positivos para um golfe que você realmente implementaria assim? : D

-1, não há necessidade de espaço atrás x,y:.



Tomar duas listas também é mencionado no corpo da questão agora :)
JAD

@JarkoDubbeldam Uh, acabei de ver, que ele tem que produzir a área. Esta solução atualmente apenas retorna a área. Isso também é permitido ou deve ser impresso?
P. Siehr

Uma função retornando um valor conta como saída :)
JAD

Eu acho que com o python você nem precisa nomear a função, então basta começar lambda x,y:.
JAD

@JarkoDubbeldam Existem regras em algum 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}

Aceita entrada [x1, x2, x3], [y1, y2, y3]e pula o par coordenado repetido.

-3 bytes graças a @JarkoDubbeldam

-4 bytes graças a @JarkoDubbeldam

-1 byte graças a @ZacharyT

-4 bytes graças a @ZacharyT

-4 bytes graças a @Rick


3

J, 12 bytes

Supondo que a entrada seja uma lista de 2 listas de elementos (ou seja, uma tabela)

-:+/-/ .*2[\
  • 2[\ - divide-o no cadarço Xs, ou seja, quadrados sobrepostos de 4 olmos
  • -/ .* - o determinante de cada
  • +/ - soma
  • -: - divida por 2

Se obtivermos a entrada como uma lista única, precisamos primeiro nos transformar em uma tabela, fornecendo 20 bytes:

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

11
"Assumindo que a entrada é uma lista de 2 lista de elementos (ou seja, uma mesa)" Este é permitido :)
JAD

3

MS-SQL, 66 bytes

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

O MS SQL 2008 e superior oferecem suporte a dados / funções espaciais padrão do Open Geospatial Consortium (OGC), dos quais estou aproveitando aqui.

Os dados de entrada são armazenados no campo p da tabela preexistente g , de acordo com nossos padrões de entrada .

Entrada é um campo de texto com pares ordenados no seguinte formato: (4 4,0 1,-2 5,-6 0,-1 -4,5 -2,4 4)

Agora, apenas por diversão, se você permitiu que minha tabela de entrada contivesse objetos de geometria padrão do Open Geospatial Consortium (em vez de apenas dados de texto), torna-se quase 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

Experimente online!

Recebe a entrada como uma lista de coordenadas X na primeira linha, seguida por uma lista de coordenadas Y na segunda.

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.