Berapa luas poligon ini?

19

Hitung luas poligon.

Terinspirasi oleh video algoritme tali sepatu ini .

Tugas

Tugas Anda adalah membuat program atau fungsi yang menghitung luas poligon. Program atau fungsi didefinisikan sesuai dengan definisi default dalam meta.

Memasukkan

Anda akan menerima koordinat X dan Y dari setiap simpul poligon. Anda dapat mengambil input sebagai daftar tupel ( [[x1, y1], [x2, y2], etc]), matriks, atau daftar datar ( [x1, y1, x2, y2, etc]). Dua daftar yang berisi xdan ykoordinat masing-masing juga diizinkan. Verteks diberi nomor berlawanan arah jarum jam dan simpul pertama sama dengan simpul terakhir yang disediakan, sehingga menutup poligon.

Jika mau, Anda dapat mengambil input tanpa simpul terakhir (jadi terima setiap koordinat hanya sekali).

Anda dapat mengasumsikan bahwa ujung-ujung poligon tidak berpotongan. Anda juga dapat mengasumsikan bahwa semua simpul memiliki koordinat bilangan bulat.

Keluaran

Area poligon. Semua metode keluaran standar diizinkan. Jika bahasa Anda tidak memungkinkan pembagian float dan solusinya tidak akan menjadi bilangan bulat, Anda diizinkan untuk mengembalikan sebagian kecil. Fraksi tidak harus disederhanakan, jadi pengembalian 2/4akan diizinkan.

Menang kriteria

Kode terpendek menang!

Uji kasus

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

masukkan deskripsi gambar di sini

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

masukkan deskripsi gambar di sini

JAD
sumber
Apakah input seperti [x1, x2, x3], [y1, y2, y3]diizinkan?
programmer5000
@ programmer5000 dan Martin Ender, ya, saya akan mengeditnya :)
JAD
Saya setuju, memilih untuk membuka kembali.
programmer5000
1
@ flawr Saya membuat duplikat ini. Ini sebenarnya bukan dupe dari target dupe-nya, yang untuk menerapkan metode yang sama seperti di sini secara rekursif akan membutuhkan menemukan simpul yang melintasi titik dan akan membutuhkan memesan subset yang dihasilkan ke mode berlawanan arah jarum jam - yang tampaknya jauh lebih kompleks.
Jonathan Allan

Jawaban:

13

Jelly ,  8  6 byte

-1 byte terima kasih kepada Emigna (redundan , ÆḊmemiliki kedalaman kiri 2)
-1 byte terima kasih kepada Emigna, lagi (membagi dua,, Hfloating point tidak perlu ÷2)

ṡ2ÆḊSH

Tautan monadik yang mengambil daftar pasangan koordinat dengan arah berlawanan arah jarum jam sesuai contoh (dengan satu pengulangan) dan mengembalikan area.

Cobalah online!

Bagaimana?

Menerapkan algoritme tali sepatu, seperti yang dijelaskan dalam video (yang kebetulan juga saya tonton kemarin!)

ṡ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
Jonathan Allan
sumber
Kasing uji kedua mengembalikan `-0.5` untuk saya: o
JAD
Oh, aku harus memeriksanya ...
Jonathan Allan
Itu karena sebagai [x,y]koordinat mereka diberikan searah jarum jam daripada berlawanan arah jarum jam. Input [[1,1],[0,1],[1,0],[1,1]]akan mengembalikan a 0.5.
Jonathan Allan
1
Woops, saya akan mengeditnya: D
JAD
1
Juga, Hbukannya÷2
Emigna
29

Mathematica, 13 byte

Area@*Polygon
Martin Ender
sumber
Bisakah itu menjadi lebih sepele?
Tn. Xcoder
5
@ Mr.Xcoder Tentu.
Martin Ender
o_O - Saya benar-benar mindblown ...
Tn. Xcoder
3
Itu Mathematica untukmu. Setiap hal yang mungkin ada dibangun ke bahasa.
Brian Minton
19

Oktaf , 9 byte

@polyarea

Input adalah vektor dengan nilai x dan vektor dengan nilai y . Ini berfungsi di MATLAB juga.

Cobalah online!

Luis Mendo
sumber
16

JavaScript (ES6), 69 67 47 byte

Terima kasih kepada @Rick karena memperhatikan bahwa kami tidak memerlukan nilai absolut jika simpul dijamin akan diurutkan dalam urutan berlawanan arah jarum jam dan untuk menyarankan untuk mengambil daftar datar sebagai input, menghemat 20 byte!

Mengambil input sebagai daftar datar simpul, termasuk simpul terakhir.

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

Cobalah online!

Bagaimana?

n

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

Arnauld
sumber
Sangat mengesankan! Bisakah Anda menjelaskan cara kerjanya?
Rugnir
Verteks dalam kasus uji kedua salah dipesan secara tidak benar. Perut seharusnya tidak perlu.
Rick
Anda juga dapat menyimpan 7 byte beralih ke daftar datar:a=>(g=([x,y,...a])=>1-a?0:x*a[1]-y*a[0]+g(a))(a)/2
Rick
@ Rick benar - abs tidak perlu. Tanpanya rumus menghitung area yang ditandatangani, yang positif karena simpul diberikan dalam urutan berlawanan arah jarum jam.
Angs
@ Rick Terima kasih! Diperbarui ... sekitar 10 bulan kemudian: /
Arnauld
7

R, 54 52 byte

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

Yang mengevaluasi fungsi:

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

Memanfaatkan yang telah ditentukan F = FALSE = 0. Menerapkan algoritma tali sepatu di video yang ditautkan :)

-2 byte terima kasih kepada Giuseppe

JAD
sumber
-1 byte untuk i+-1:0sebagai indeks baris
Giuseppe
@Giuseppe Bagus. Saya akan menghapus +juga;)
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

Membawa dua daftar, seperti yang diizinkan dalam komentar

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

Cobalah online!

Ini pada dasarnya hanya implementasi dari shoelace-formula . Bolehkah saya mendapatkan poin plus untuk golf yang sebenarnya akan Anda terapkan seperti itu? : D

-1, tidak perlu ada ruang di belakang x,y: .


P. Siehr
sumber
Mengambil dua daftar juga disebutkan dalam isi pertanyaan sekarang :)
JAD
@JarkoDubbeldam Uh, saya baru saja melihat, bahwa ia harus menampilkan area. Solusi ini saat ini baru saja mengembalikan area. Apakah itu diperbolehkan juga, atau haruskah dicetak?
P. Siehr
Sebuah fungsi yang mengembalikan nilai dianggap sebagai output :)
JAD
Saya pikir dengan python Anda bahkan tidak perlu menyebutkan nama fungsinya, jadi hanya memulainya dengan lambda x,y:baik.
JAD
@JarkoDubbeldam Apakah ada aturan di mana saja untuk setiap bahasa?
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}

Mengambil input like [x1, x2, x3], [y1, y2, y3], dan melewatkan pasangan coord yang diulang.

-3 byte terima kasih kepada @JarkoDubbeldam

-4 byte terima kasih kepada @JarkoDubbeldam

-1 byte terima kasih kepada @ZacharyT

-4 byte terima kasih kepada @ZacharyT

-4 byte terima kasih kepada @Rick

Taylor Scott
sumber
3

J, 12 byte

Dengan asumsi input adalah daftar 2 daftar elemen (yaitu, tabel)

-:+/-/ .*2[\
  • 2[\ - memecahnya menjadi tali sepatu Xs, yaitu, kotak 4 elm yang tumpang tindih
  • -/ .* - penentu masing-masing
  • +/ - jumlahkan itu
  • -: - bagi dengan 2

Jika kita mendapatkan input sebagai satu daftar, kita harus mentransformasikannya menjadi sebuah tabel, memberikan kita 20 byte:

-:+/-/ .*2[\ _2&(,\)
Jonah
sumber
1
"Dengan asumsi input adalah daftar dari 2 elemen daftar (yaitu, sebuah tabel)" Ini diperbolehkan :)
JAD
3

MS-SQL, 66 byte

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

MS SQL 2008 dan dukungan yang lebih tinggi Open Geospatial Consortium (OGC) standar-data / fungsi spasial, yang saya manfaatkan di sini.

Input data disimpan dalam bidang p dari yang sudah ada meja g , per standar masukan kami .

Input adalah bidang teks dengan pasangan berurutan dalam format berikut: (4 4,0 1,-2 5,-6 0,-1 -4,5 -2,4 4)

Sekarang hanya untuk bersenang-senang, jika Anda mengizinkan tabel input saya untuk menahan objek geometri standar Geospatial Konsorsium Terbuka (bukan hanya data teks), maka itu menjadi hampir sepele:

--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
BradC
sumber
0

Perl 5 -pa , 62 byte

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

Cobalah online!

Mengambil input sebagai daftar koordinat X pada baris pertama diikuti oleh daftar koordinat Y pada baris kedua.

Xcali
sumber