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


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

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



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|


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


-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: .



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


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&(,\)

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


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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.