Jaki jest obszar tego wielokąta?

19

Oblicz obszar wielokąta.

Zainspirowany tym wideo z algorytmem sznurowadła.

Zadanie

Twoim zadaniem jest stworzenie programu lub funkcji, która oblicza pole wielokąta. Program lub funkcja jest zdefiniowana zgodnie z domyślną definicją w meta.

Wejście

Otrzymasz współrzędne X i Y każdego wierzchołka wielokąta. Możesz wziąć dane wejściowe jako listę krotek ( [[x1, y1], [x2, y2], etc]), macierzy lub płaskiej listy ( [x1, y1, x2, y2, etc]). Dopuszczalne są również dwie listy zawierające odpowiednio xi ywspółrzędne. Wierzchołki są ponumerowane przeciwnie do ruchu wskazówek zegara, a pierwszy wierzchołek jest taki sam jak ostatni podany wierzchołek, zamykając w ten sposób wielokąt.

Jeśli chcesz, możesz wziąć dane wejściowe bez ostatniego wierzchołka (więc otrzymaj każdą współrzędną tylko raz).

Możesz założyć, że krawędzie wielokątów się nie przecinają. Możesz również założyć, że wszystkie wierzchołki mają współrzędne całkowite.

Wynik

Obszar wielokąta. Wszystkie standardowe metody wyjściowe są dozwolone. Jeśli twój język nie pozwala na dzielenie zmiennoprzecinkowe, a rozwiązaniem nie byłaby liczba całkowita, możesz zwrócić ułamek. Ułamek nie musi być koniecznie uproszczony, więc zwrot 2/4byłby dozwolony.

Kryterium wygranej

Najkrótszy kod wygrywa!

Przypadki testowe

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

wprowadź opis zdjęcia tutaj

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

wprowadź opis zdjęcia tutaj

JAD
źródło
Czy wprowadzanie danych jest [x1, x2, x3], [y1, y2, y3]dozwolone?
programmer5000
@ programmer5000 i Martin Ender, tak, edytuję to za :)
JAD
Zgadzam się, zagłosowałem za ponownym otwarciem.
programmer5000
1
@flawr Zrobiłem to duplikat tego. W rzeczywistości nie jest to duplikat docelowego duplikatu, który zastosowałby tę samą metodę, co tutaj rekurencyjnie, wymagałby znalezienia wierzchołków, które przecinają punkty i wymagałby uporządkowania powstałych podzbiorów w sposób przeciwny do ruchu wskazówek zegara - wydaje się to znacznie bardziej skomplikowane.
Jonathan Allan

Odpowiedzi:

13

Galaretka ,  8  6 bajtów

-1 bajt dzięki Emignie (redundantny , ÆḊma lewą głębokość 2)
-1 bajt dzięki Emignie, znowu (o połowę H, jest zmiennoprzecinkowy nie ma potrzeby ÷2)

ṡ2ÆḊSH

Monadyczny link pobierający listę par współrzędnych w kierunku przeciwnym do ruchu wskazówek zegara, zgodnie z przykładami (z jednym powtórzeniem) i zwracający obszar.

Wypróbuj online!

W jaki sposób?

Stosuje algorytm sznurowadła, dokładnie tak, jak opisano w filmie (który zdarzyło mi się oglądać także innego dnia!)

ṡ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
źródło
Drugi przypadek testowy zwraca dla mnie `-0,5`: o
JAD
Och, muszę to sprawdzić ...
Jonathan Allan
Jest tak, ponieważ jako [x,y]współrzędne są one podawane zgodnie z ruchem wskazówek zegara, a nie przeciwnie do ruchu wskazówek zegara. Wejście [[1,1],[0,1],[1,0],[1,1]]zwróci a 0.5.
Jonathan Allan
1
Ups, zmienię to: D
JAD
1
Ponadto Hzamiast÷2
Emigna
29

Mathematica, 13 bajtów

Area@*Polygon
Martin Ender
źródło
Czy może być bardziej trywialne?
Pan Xcoder,
5
@ Mr.Xcoder Sure.
Martin Ender
o_O - Jestem dosłownie oszołomiony ...
Pan Xcoder
3
To dla ciebie Mathematica. Każda możliwa rzecz jest wbudowana w język.
Brian Minton
19

Oktawa , 9 bajtów

@polyarea

Wejściami są wektor o wartościach x i wektor o wartościach y . Działa to również w MATLAB.

Wypróbuj online!

Luis Mendo
źródło
16

JavaScript (ES6), 69 67 47 bajtów

Dzięki @Rick za zauważenie, że nie potrzebujemy wartości bezwzględnej, jeśli gwarantowane jest sortowanie wierzchołków w kolejności przeciwnej do ruchu wskazówek zegara, oraz za zasugerowanie przyjęcia płaskiej listy jako danych wejściowych, oszczędzając 20 bajtów!

Pobiera dane wejściowe jako płaską listę wierzchołków, w tym ostatni wierzchołek.

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

Wypróbuj online!

W jaki sposób?

n

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

Arnauld
źródło
Bardzo imponujące! Czy możesz wyjaśnić, jak to działa?
Rugnir
Wierzchołki w drugim przypadku testowym zostały błędnie uporządkowane nieprawidłowo. Brzuch nie powinien być konieczny.
Rick
Możesz także zapisać 7 bajtów przełączając się na płaską listę:a=>(g=([x,y,...a])=>1-a?0:x*a[1]-y*a[0]+g(a))(a)/2
Rick
@ Ric ma rację - abs nie jest konieczne. Bez niego formuła oblicza podpisany obszar, co jest dodatnie, ponieważ wierzchołki są podawane w kolejności przeciwnej do ruchu wskazówek zegara.
Angs,
@Rick Thanks! Zaktualizowano ... około 10 miesięcy później: /
Arnauld
7

R, 54 52 bajtów

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

Który ocenia się na funkcję:

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

Wykorzystuje predefiniowane F = FALSE = 0. Implementuje algorytm sznurowadła w połączonym wideo :)

-2 bajty dzięki Giuseppe

JAD
źródło
-1 bajt dla i+-1:0jako indeksu wiersza
Giuseppe
@Giuseppe Nice. Ja też usunę +;)
JAD
6

Python 3 , 72 71 bajtów

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

Pobiera dwie listy, jak to było dozwolone w komentarzach

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

Wypróbuj online!

Jest to w zasadzie tylko wdrożenie formuły sznurowadła . Czy mogę uzyskać dodatkowe punkty za golfa, który faktycznie wprowadzilibyście w ten sposób? :RE

-1, nie ma potrzeby odstępu x,y:.


P. Siehr
źródło
Biorąc dwie listy, wspomniano teraz również w treści pytania :)
JAD
@JarkoDubbeldam Uh, właśnie widziałem, że musi generować obszar. To rozwiązanie obecnie zwraca tylko obszar. Czy to również dozwolone, czy też powinno zostać wydrukowane?
P. Siehr,
Funkcja zwracająca wartość liczy się jako wynik :)
JAD
Myślę, że w Pythonie nie musisz nawet nazywać tej funkcji, więc rozpoczęcie od niej lambda x,y:jest w porządku.
JAD
@JarkoDubbeldam Czy istnieją reguły dla każdego języka?
P. Siehr
4

JS (ES6), 98 95 94 93 88 86 82 81 77 73 bajtów

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

Pobiera dane wejściowe [x1, x2, x3], [y1, y2, y3]i pomija powtarzającą się parę współrzędnych.

-3 bajty dzięki @JarkoDubbeldam

-4 bajty dzięki @JarkoDubbeldam

-1 bajt dzięki @ZacharyT

-4 bajty dzięki @ZacharyT

-4 bajty dzięki @Rick

Taylor Scott
źródło
3

J, 12 bajtów

Zakładając, że dane wejściowe to lista 2 list elementów (tj. Tabela)

-:+/-/ .*2[\
  • 2[\ - rozkłada go na sznurowadło Xs, tzn. nakładające się kwadraty 4 wiązów
  • -/ .* - wyznacznik każdego z nich
  • +/ - podsumuj to
  • -: - podzielić przez 2

Jeśli otrzymamy dane wejściowe jako pojedynczą listę, musimy najpierw przekształcić się w tabelę, dając nam 20 bajtów:

-:+/-/ .*2[\ _2&(,\)
Jonasz
źródło
1
„Zakładając, że dane wejściowe to lista 2 list elementów (tj. Tabela)” Jest to dozwolone :)
JAD
3

MS-SQL, 66 bajtów

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

MS SQL 2008 i nowsze wersje obsługują dane przestrzenne / funkcje Open Geospatial Consortium (OGC), z których korzystam.

Dane wejściowe są przechowywane w polu p istniejącej tabeli g , zgodnie z naszymi standardami wejściowymi .

Dane wejściowe to pole tekstowe z uporządkowanymi parami w następującym formacie: (4 4,0 1,-2 5,-6 0,-1 -4,5 -2,4 4)

Teraz dla zabawy, jeśli pozwolisz, aby moja tabela wprowadzania zawierała obiekty geometrii zgodne ze standardem Open Geospatial Consortium (zamiast tylko danych tekstowych), staje się to prawie banalne:

--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
źródło
0

Perl 5 -pa , 62 bajty

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

Wypróbuj online!

Pobiera dane wejściowe jako listę współrzędnych X w pierwszym wierszu, a następnie listę współrzędnych Y w drugim wierszu.

Xcali
źródło