R + sp (46 байт)
Предполагает a + b*j
package is installed (https://cran.r-project.org/web/packages/sp/)
Принимает список вершин (например | a b |
| c d |
)
Использует тот факт, что «labpt» полигона является центроидом.
a*d - b*c
||answer||
JavaScript (ES6), 102
Прямая реализация формулы
[c, d]
Тест
[a, b]
x + y*j
[x, y]
||answer||
Питон 2, 153 байта
Не использует комплексные числа.
def f(points):
n = len(points)
points = points + [points[0]]
determinantSum = 0
for i in range(n):
determinant = (points[i].conjugate() * points[i+1]).imag
determinantSum += determinant
points[i] = (points[i] + points[i+1]) * determinant
print sum(points[:n]) / determinantSum / 3
Попробуйте онлайн
Не в гольфе:
def f(p):n=len(p);p=p+p[:1];i=s=0;exec'd=(p[i].conjugate()*p[i+1]).imag;s+=d;p[i]=(p[i]+p[i+1])*d;i+=1;'*n;print sum(p[:n])/s/3
||answer||
На самом деле 45 40 39 байт
Здесь используется алгоритм, аналогичный ответ Майлза Джелли. Существует более короткий способ вычисления определителей с использованием скалярного произведения, но в настоящее время существует ошибка в скалярном произведении Фактически, из-за которой оно не работает со списками чисел с плавающей запятой. Предложения по игре в гольф приветствуются. Попробуйте онлайн!
(SUMinCx, SUMinCy) / SUMinA / 3
Унгольфинг
*2/6
Более короткая, неконкурентная версия.
Это еще одна 24-байтовая версия, в которой используются комплексные числа. Оно неконкурентноспособно, поскольку основано на исправлениях ошибок, появившихся после этого испытания. Попробуйте онлайн!
A
Унгольфинг
Cy
||answer||
С++14, 241 байт
Cx
Результатом является вспомогательная структура Cy
,
Не в гольфе:
Cx
Использование:
c(sum((x+X)*p),sum((y+Y)*p))/sum(p)*2/6
||answer||
Clojure, 177 156 143 байт
Обновление: вместо обратного вызова я использую f=function(l){s=sapply; # Alias for sapply
x=s(l,`[`,1); # Split list of tuples into vector of first elements
y=s(l,`[`,2); # =||= but for second element
X=c(x[-1],x[1]); # Generate a vector for x(i+1)
Y=c(y[-1],y[1]); # Generate a vector for y(i+1)
p=x*Y-X*y; # Calculate the outer product used in both A, Cx and Cy
c(sum((x+X)*p),sum((y+Y)*p))/sum(p)/3 # See post for explanation
}
as a function and the argument is just a list of indexes to this vector. f(list(c(-15.21,0.8),c(10.1,-0.3),c(-0.07,23.55)))
используется в качестве контрольного значения при расчете function(l){s=sapply;x=s(l,`[`,1);y=s(l,`[`,2);X=c(x[-1],x[1]);Y=c(y[-1],y[1]);p=x*Y-X*y;c(sum((x+X)*p),sum((y+Y)*p))/sum(p)/3}
.
Обновление 2: отсутствие предварительных расчетов '(-1.7266666666666677 8.01666666666667)
'(5.8010476997538465 15.067381276150996)
at (f '[(-15.21 0.8) (10.1 -0.3) (-0.07 23.55)] )
(f '[(-39.00 -55.94) (-56.08 -4.73) (-72.64 12.12) (-31.04 53.58)
(-30.36 28.29) (17.96 59.17) (0.00 0.00) (10.00 0.00)
(20.00 0.00) (148.63 114.32) (8.06 -41.04) (-41.25 34.43)])
, с использованием (define(f l)
(let* ((lr list-ref)
(getx (lambda(i)(lr (lr l i)0)))
(gety (lambda(i)(lr (lr l i)1)))
(n (length l))
(j (lambda(i) (if (= i (sub1 n)) 0 (add1 i))))
(A (/(for/sum ((i n))
(-(* (getx i) (gety (j i)))
(* (getx (j i)) (gety i))))
2))
(cx (/(for/sum ((i n))
(*(+(getx i)(getx (j i)))
(-(*(getx i)(gety (j i)))
(*(getx (j i))(gety i)))))
(* 6 A)))
(cy (/(for/sum ((i n))
(*(+(gety i)(gety (j i)))
(-(*(getx i)(gety (j i)))
(*(getx (j i))(gety i)))))
(* 6 A))))
(list cx cy)))
to get input vectors offset by one.
(let*((lr list-ref)(getx(lambda(i)(lr(lr l i)0)))(gety(lambda(i)(lr(lr l i)1)))(n(length l))(j(λ(i)(if(= i(sub1 n))0(add1 i))))
(A(/(for/sum((i n))(-(*(getx i)(gety(j i)))(*(getx(j i))(gety i))))2))
(cx(/(for/sum((i n))(*(+(getx i)(getx(j i)))(-(*(getx i)(gety(j i)))(*(getx(j i))(gety i)))))(* 6 A)))
(cy(/(for/sum((i n))(*(+(gety i)(gety(j i)))(-(*(getx i)(gety(j i)))(*(getx(j i))(gety i)))))(* 6 A))))
(list cx cy))
Оригинальная версия:
(%i6) f([[-15.21,0.8], [10.1,-0.3], [-0.07,23.55]]);
(%o6) [- 1.726666666666668, 8.016666666666668]
На менее играющей в гольф стадии:
f(l):=(l:endcons(l[1],l),l:sum([3,l[i-1]+l[i]]*determinant(matrix(l[i-1],l[i])),i,2,length(l)),l[2]/l[1]);
Создает вспомогательную функцию 2+/@(+/\(*%3*1#.])-/ .*\)],{. Input: 2d array of points P [[x1 y1] [x2 y2] ...]
{. Head of P
] Get P
, Join, makes the end cycle back to the front
2 The constant 2
2 \ For each pair of points
-/ .* Take the determinant
2 +/\ Sum each pair of points
* Multiply the sum of each pair by its determinant
% Divide each by
1#.] The sum of the determinants
3* Multiplied by 3
+/@ Sum and return
which implements the summation with any callback f =: 2+/@(+/\(*%3*1#.])-/ .*\)],{.
f 0 0 , 1 0 , 1 1 ,: 0 1
0.5 0.5
f _15.21 0.8 , 10.1 _0.3 ,: _0.07 23.55
_1.72667 8.01667
f _39 _55.94 , _56.08 _4.73 , _72.64 12.12 , _31.04 53.58 , _30.36 28.29 , 17.96 59.17 , 0 0 , 10 0 , 20 0 , 148.63 114.32 , 8.06 _41.04 ,: _41.25 34.43
5.80105 15.0674
. Для 2+/@(+/\(*%3*1#.])-/ .*\)],{.
the callback returns constantly S×3÷@×" Helper link. Input: determinants on LHS, sum of pairs on RHS
S Sum the determinants
×3 Multiply by 3
×" Vectorized multiply between determinants and sums
÷@ Divide that by the determinant sum multipled by 3 and return
ṙ-żµÆḊçS€S Main link. Input: 2d list of points
ṙ- Rotate the list of points by 1 to the right
ż Interleave those with the original points
This creates all overlapping slices of length 2
µ Start new monadic chain
ÆḊ Get the determinant of each slice
S€ Get the sum of each slice (sum of pairs of points)
ç Call the helper link
S Sum and return
тогда как координаты X и Y имеют свои собственные функции. S×3÷@×"
ṙ-żµÆḊçS€S
drops the first element and appends to the end, this way it is easy to keep track of RegionCentroid
and Polygon
. Maybe there is still some repetition to be eliminated, especially at the last RegionCentroid@*Polygon
.