Какова площадь этого многоугольника?

19

Рассчитайте площадь многоугольника.

Вдохновленный этим алгоритмом шнурка видео.

задача

Ваша задача - создать программу или функцию, которая вычисляет площадь многоугольника. Программа или функция определяется в соответствии с определением по умолчанию в meta.

вход

Вы получите координаты X и Y каждой вершины многоугольника. Вы можете принять входные данные в виде списка кортежей ( [[x1, y1], [x2, y2], etc]), матрицы или плоского списка ( [x1, y1, x2, y2, etc]). Также допустимы два списка, содержащие xи yкоординаты соответственно. Вершины нумеруются против часовой стрелки, и первая вершина совпадает с последней предоставленной вершиной, таким образом закрывая многоугольник.

Если вы хотите, вы можете взять ввод без последней вершины (поэтому получите каждую координату только один раз).

Вы можете предположить, что ребра многоугольников не пересекаются. Вы также можете предположить, что все вершины имеют целочисленные координаты.

Выход

Площадь многоугольника. Все стандартные методы вывода разрешены. Если ваш язык не допускает деление с плавающей запятой и решение не будет целочисленным, вы можете вернуть дробь. Дробь не обязательно должна быть упрощена, поэтому возврат 2/4будет разрешен.

Критерий победы

Самый короткий код выигрывает!

Контрольные примеры

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

введите описание изображения здесь

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

введите описание изображения здесь

JAD
источник
[x1, x2, x3], [y1, y2, y3]Разрешен ли ввод как ?
programmer5000
@ programmer5000 и Мартин Эндер, да, я его отредактирую :)
JAD
Я согласен, проголосовал за открытие.
programmer5000
1
@flawr Я сделал это обманом этого. На самом деле это не дублирование цели дублирования, поэтому для применения того же метода, который здесь используется рекурсивно, потребуется найти вершины, которые являются точками пересечения, и потребуется упорядочить результирующие подмножества против часовой стрелки, что кажется гораздо более сложным.
Джонатан Аллан

Ответы:

13

Желе ,  8  6 байт

-1 байт благодаря Emigna (избыточный , ÆḊимеет левую глубину 2)
-1 байт благодаря Emigna, опять же (пополам, с Hплавающей запятой нет необходимости ÷2)

ṡ2ÆḊSH

Монадическая ссылка, берущая список пар координат против часовой стрелки согласно примерам (с одним повторением) и возвращающая область.

Попробуйте онлайн!

Как?

Применяет алгоритм шнурка, как описано в видео (которое я тоже смотрел на днях!)

ṡ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
Джонатан Аллан
источник
Второй контрольный пример возвращает `-0.5` для меня: o
JAD
О, мне придется это проверить ...
Джонатан Аллан
Это потому, что в качестве [x,y]координат они даны по часовой стрелке, а не против часовой стрелки. Вход [[1,1],[0,1],[1,0],[1,1]]вернет 0.5.
Джонатан Аллан
1
Woops, я отредактирую это: D
JAD
1
Также Hвместо÷2
Emigna
29

Mathematica, 13 байт

Area@*Polygon
Мартин Эндер
источник
Может ли это стать более тривиальным?
г-н Xcoder
5
@ Mr.Xcoder Конечно.
Мартин Эндер
о_О - Я буквально ошеломлен ...
Мистер Xcoder
3
Это Mathematica для вас. Каждая мыслимая вещь встроена в язык.
Брайан Минтон
16

JavaScript (ES6), 69 67 47 байт

Спасибо @Rick за то, что обратили внимание на то, что нам не нужно абсолютное значение, если вершины гарантированно отсортированы в порядке против часовой стрелки, и за предложение взять плоский список в качестве входных данных, экономя 20 байтов!

Вводит в виде плоского списка вершин, включая последнюю вершину.

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

Попробуйте онлайн!

Как?

N

aреaзнак равно|(Икс0Y1-Y0Икс1)+(Икс1Y2-Y1Икс2)+...+(ИксN-1Y0-YN-1Икс0)2|

Arnauld
источник
Очень впечатляюще! Не могли бы вы объяснить, как это работает?
Ругнир
Вершины во втором тестовом случае были ошибочно упорядочены неправильно. Абс не должен быть необходимым.
Рик
Вы также можете сэкономить 7 байтов, переключаясь на плоский список:a=>(g=([x,y,...a])=>1-a?0:x*a[1]-y*a[0]+g(a))(a)/2
Рик
@ Рик прав - пресс не нужен. Без этого формула вычисляет область со знаком, которая является положительной, поскольку вершины задаются в порядке против часовой стрелки.
Angs
@ Рик Спасибо! Обновлено ... около 10 месяцев спустя: /
Арнаулд
7

R, 54 52 байта

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

Который оценивает функцию:

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

Использует предопределенное F = FALSE = 0. Реализует алгоритм шнурка в связанном видео :)

-2 байта благодаря Джузеппе

JAD
источник
-1 байт для i+-1:0индекса строки
Джузеппе
@ Джузеппе Ницца. Я тоже удалю +;)
JAD
6

Python 3 , 72 71 байт

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

Занимает два списка, как это было разрешено в комментариях

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

Попробуйте онлайн!

Это в основном просто реализация формулы шнурка . Могу ли я получить дополнительные баллы за гольф, который вы на самом деле реализовали бы таким образом? : D

-1, сзади места не нужно x,y:.


П. Зир
источник
Взятие двух списков также упомянуто в теле вопроса сейчас :)
JAD
@JarkoDubbeldam Э-э, я только что увидел, что он должен выводить область. Это решение в настоящее время просто возвращает область. Это также разрешено или будет напечатано?
P.
Функция, возвращающая значение, считается как выходной :)
JAD
Я думаю, что с python вам даже не нужно называть функцию, так что начинать с lambda x,y:нее хорошо.
JAD
@JarkoDubbeldam Есть ли где-нибудь правила для каждого языка?
P.
4

JS (ES6), 98 95 94 93 88 86 82 81 77 73 байта

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

Принимает ввод как [x1, x2, x3], [y1, y2, y3]и пропускает повторенную пару координат.

-3 байта благодаря @JarkoDubbeldam

-4 байта благодаря @JarkoDubbeldam

-1 байт благодаря @ZacharyT

-4 байта благодаря @ZacharyT

-4 байта благодаря @Rick

Тейлор Скотт
источник
3

J, 12 байт

Предполагая, что вход представляет собой список из 2 списков элементов (то есть, таблицы)

-:+/-/ .*2[\
  • 2[\ - разбивает его на шнурки Xs, т. е. перекрывающиеся квадраты по 4 вяза
  • -/ .* - определитель каждого
  • +/ - суммируй
  • -: - разделить на 2

Если мы получим входные данные в виде единого списка, нам нужно сначала преобразовать в таблицу, что даст нам 20 байтов:

-:+/-/ .*2[\ _2&(,\)
Ион
источник
1
«Предполагается, что входные данные представляют собой список из 2 списков элементов (т.
JAD
3

MS-SQL, 66 байт

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

MS SQL 2008 и выше поддерживают Open Geospatial Consortium (OGC) - стандартные пространственные данные / функции, которыми я пользуюсь здесь.

Входные данные хранятся в поле р из уже существующей таблицы г , в соответствии с нашими стандартами ввода .

Ввод - это текстовое поле с упорядоченными парами в следующем формате: (4 4,0 1,-2 5,-6 0,-1 -4,5 -2,4 4)

Теперь просто для удовольствия, если вы позволили моей входной таблице содержать стандартные геометрические объекты Open Geospatial Consortium (а не только текстовые данные), то это становится почти тривиальным:

--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
источник
0

Perl 5 -pa , 62 байта

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

Попробуйте онлайн!

Принимает ввод в виде списка координат X в первой строке, за которым следует список координат Y во второй строке.

Xcali
источник