质量中心,来自坐标及其质量列表


20

这是星期一早上的快速挑战...

用最少的字节数写一个函数或程序:

  • 输入[x,y]坐标列表
  • 输入[x,y]坐标各自质量的列表作为输入
  • 以形式输出计算出的质心[xBar,yBar]

注意:

  • 输入可以采用任何形式,只要使用数组即可。

质心可以通过以下公式计算: 重心计算

用简单的英语...

  • 为了找到xBar,将每个质量乘以其相应的x坐标,对结果列表求和,然后将其除以所有质量的总和。
  • 要找到yBar,将每个质量乘以其各自的y坐标,对结果列表求和,然后将其除以所有质量的总和。

简单的Python 2.7示例:

def center(coord, mass):
    sumMass = float(reduce(lambda a, b: a+b, mass))
    momentX = reduce(lambda m, x: m+x, (a*b for a, b in zip(mass, zip(*coord)[0])))
    momentY = reduce(lambda m, y: m+y, (a*b for a, b in zip(mass, zip(*coord)[1])))
    xBar = momentX / sumMass
    yBar = momentY / sumMass
    return [xBar, yBar]

测试用例:

> center([[0, 2], [3, 4], [0, 1], [1, 1]], [2, 6, 2, 10])
[1.4, 2.0]

> center([[3, 1], [0, 0], [1, 4]], [2, 4, 1])
[1.0, 0.8571428571428571]

这是代码高尔夫球,因此最少的字节数获胜!


由于这只是“计算向量的加权平均值”,如果我们以前没有做过的话,我会感到非常惊讶。(目前,我什么也找不到。)
马丁·恩德

@MartinBüttner我也看了,找不到任何东西。如果这是骗子,请随时将其关闭。
先生先生

可以按其他顺序输入吗?或形式:[x,y,m],[x,y,m]...
FryAmTheEggman

已编辑@FryAmTheEggman问题以获取有效输入。
先生先生

@MrPublic:怎么样[(x1,y1,m1), (x2,y2,m2)],例如元组列表?还是参数是元组,列表还是数组都没关系吗?那三个列表/数组呢?
Zeta

Answers:


21

MATL6 5字节

ys/Y*

输入格式是带有质量的行向量,然后是带有坐标的两列矩阵(空格或逗号是可选的)。

  • 第一个例子:

    [2, 6, 2, 10]
    [0,2; 3,4; 0,1; 1,1]
    
  • 第二个例子:

    [2, 4, 1]
    [3,1; 0,0; 1,4]
    

在线尝试!

说明

令其m表示质量矢量(第一个输入)和c坐标矩阵(第二个输入)。

y     % implicitly take two inputs. Duplicate the first.
      % (Stack contains, bottom to top: m, c, m)
s     % sum of m.
      % (Stack: m, c, sum-of-m)
/     % divide.
      % (Stack: m, c-divided-by-sum-of-m)
Y*    % matrix multiplication.
      % (Stack: final result)
      % implicitly display

y非常有用!+1
大卫

@David是的!结合隐式输入,在这种情况下,它可以完成很多工作:-)
Luis Mendo

7

Mathematica,10个字节

#.#2/Tr@#&

例:

In[1]:= #.#2/Tr@#&[{2,6,2,10},{{0,2},{3,4},{0,1},{1,1}}]

Out[1]= {7/5, 2}

1
我没用过Dot。但是我会在上面看到你的用法之后!
DavidC

7

Mathcad,19个“字节”

在此处输入图片说明

  • 使用Mathcad的表进行数据输入
  • 使用Mathcad的内置矢量标量乘积将轴纵坐标和质量相乘
  • 使用Mathcad的内置求和运算符计算总质量

由于Mathcad使用2D“白板”和特殊运算符(例如,求和运算符,积分运算符)并以XML格式保存,因此实​​际的工作表可能包含数百个(或更多)字符。出于Code Golf的目的,我将Mathcad的“字节数”作为用户创建工作表时必须输入的字符或运算符的数量。

使用此定义,质询的第一个(程序)版本需要19个“字节”,而功能版本需要41个“字节”。


3
我第一次见过这里的Matcad解决方案。非常好。+1。
rayryeng-恢复莫妮卡

谢谢rayryeng。考虑到Mathcad仅具有基本的字符串函数并且没有人类可读的纯文本源代码,这可能是在“课程”上进行一些“漏洞”的挑战,这有点挑战。
Stuart Bruff

6

MATLAB /八度,18 16字节

感谢用户烧杯和Don Muesli删除了2个字节!

假设坐标在N x 2矩阵中x,其中第一列是X坐标,第二列是Y坐标,质量在1 x N矩阵y(或行向量)中:

@(x,y)y*x/sum(y)

这段代码的解释很简单。这是一个匿名函数,接受两个输入xy。我们使用矩阵向量乘法以线性代数方法执行加权求和(每个坐标的分子表达式)。通过取y质量矢量并将其与坐标x矩阵乘以矩阵矢量相乘,可以分别计算两个坐标的加权和,然后将每个坐标除以质量之和,从而找到所需的质量中心。每个坐标分别返回1 x 2行向量的质量。

运行示例

>> A=@(x,y)y*x/sum(y)

A = 

    @(x,y)y*x/sum(y)

>> x = [0 2; 3 4; 0 1; 1 1];
>> y = [2 6 2 10];
>> A(x,y)

ans =

    1.4000    2.0000

>> x = [3 1; 0 0; 1 4];
>> y = [2 4 1];
>> A(x,y)

ans =

    1.0000    0.8571

在线尝试!

https://ideone.com/BzbQ3e


1
您可以删除;,也可以'通过正确选择输入格式(x作为行向量)来删除
Luis Mendo,

@DonMuesli谢谢:)由2.减少的字节数
rayryeng -恢复莫妮卡

6

果冻,6个字节

S÷@×"S

要么

÷S$×"S

输入是通过两个命令行参数进行的,首先是质量,其次是坐标。

在线尝试!

说明

S       Sum the masses.
   x"   Multiply each vector by the corresponding mass.
 ÷@     Divide the results by the sum of masses.
     S  Sum the vectors.

要么

÷S$     Divide the masses by their sum.
   ×"   Multiply each vector by the corresponding normalised mass.
     S  Sum the vectors.

6

朱莉娅,25 17字节

f(c,m)=m*c/sum(m)

错过了明显的方法:/呼叫一样f([3 1;0 0;1 4], [2 4 1])


5

CJam,14个字节

{_:+df/.f*:.+}

具有的未命名函数期望坐标对列表和堆栈上的质量列表(按此顺序),并在它们的位置保留质心。

在这里测试。

说明

_    e# Duplicate list of masses.
:+d  e# Get sum, convert to double.
f/   e# Divide each mass by the sum, normalising the list of masses.
.f*  e# Multiply each component of each vector by the corresponding weight.
:.+  e# Element-wise sum of all weighted vectors.

5

Perl 6,36 33 30字节

{[Z+](@^a Z»*»@^b) X/sum @b}

4

严重的是16个字节

╩2└Σ;╛2└*/@╜2└*/

将输入作为[x-coords]\n[y-coords]\n[masses],将输出作为xbar\nybar

在线尝试!

说明:

╩2└Σ;╛2└*/@╜2└*/
╩                 push each line of input into its own numbered register
 2└Σ;             push 2 copies of the sum of the masses
     ╛2└*/        push masses and y-coords, dot product, divide by sum of masses
          @       swap
           ╜2└*/  push masses and x-coords, dot product, divide by sum of masses

3

哈斯克尔, 55 50字节

z=zipWith
f a=map(/sum a).foldr1(z(+)).z(map.(*))a

这定义了一个二进制函数 f,其用法如下:

> f [1,2] [[1,2],[3,4]]
[2.3333333333333335,3.333333333333333]

看到它通过了两个测试用例。

说明

Haskell不太适合处理多维列表,因此我在这里跳过了一些麻烦。第一行为定义了一个简短的别名zipWith,我们需要两次。基本上,f是一个获取权重列表a并生成质量f a的函数,一个获取位置清单并生成质心的函数。 f a由三个功能组成:

z(map.(*))a      -- First sub-function:
z         a      --   Zip the list of positions with the mass list a
  map.(*)        --   using the function map.(*), which takes a mass m
                 --   and maps (*m) over the corresponding position vector
foldr1(z(+))     -- Second sub-function:
foldr1           --   Fold (reduce) the list of mass-times-position vectors
       z(+)      --   using element-wise addition
map(/sum a)      -- Third sub-function:
map              --   Map over both coordinates:
   (/sum a)      --     Divide by the sum of all masses

3

JavaScript(ES6),60个字节

a=>a.map(([x,y,m])=>{s+=m;t+=x*m;u+=y*m},s=t=u=0)&&[t/s,u/s]

接受(x,y,mass)“ triples”的数组,并返回一个“ tuple”。


圆括号是否[x,y,m]必要?iirc,如果arrow函数只有一个输入参数,则不需要它们。
Patrick Roberts

@PatrickRoberts是的,在所有情况下它们都是必需的,只是一个标准参数中的一个琐碎之一。
尼尔

3

R,32 25字节

function(a,m)m%*%a/sum(m)

通过切换到矩阵代数来编辑-7个字节(感谢@ Sp3000 Julia回答)

传递一个数组(具有2列x,y的矩阵)作为坐标和m权重向量,返回具有所需坐标的数组


2

PHP,142字节

function p($q,$d){return$q*$d;}function c($f){$s=array_sum;$m=array_map;$e=$f[0];return[$s($m(p,$e,$f[1]))/$s($e),$s($m(p,$e,$f[2]))/$s($e)];}
分解图
function p($q, $d) {
  return $q * $d;
}

function c($f) {
  $s = array_sum;
  $m = array_map;
  $e = $f[0];
  return [ $s($m(p,$e,$f[1])) / $s($e),
           $s($m(p,$e,$f[2])) / $s($e) ];
}
必填项
Array[Array]: [ [ mass1, mass2, ... ],
                [ xpos1, xpos2, ... ],
                [ ypos1, ypos2, ... ] ]
返回

Array: [ xbar, ybar ]


p()函数是一个基本映射,将每个[m]值与相应的[x][y]值相乘。该c()函数接受的Array[Array],提出了array_sumarray_map空间的功能,然后计算Σmx/ΣmΣmy/Σm

可能会发现将计算本身转换为空间函数。


2

Mathcad,8个“字节”

我不知道我以前的回答中没有在想什么。这是一种正确使用矩阵乘法的较短方法。变量p包含数据-如果将变量计数设置为总数,则再加上2个“字节”(输入表的创建= 1字节,变量名= 1字节)。

在此处输入图片说明


1

Python 3,63个字节

lambda a,b:[sum(x*y/sum(b)for x,y in zip(L,b))for L in zip(*a)]

列表上的向量操作很长:/

这是一个匿名的lambda函数-给它起一个名字,然后调用like f([[0,2],[3,4],[0,1],[1,1]],[2,6,2,10])


1

Python 3,95 90 88字节

lambda c,m:list(map(sum,zip(*[[i[0]*j/sum(m),i[1]*j/sum(m)]for i,j in zip(*([c,m]))])))

结果

>>> f([[0,2],[3,4],[0,1],[1,1]],[2,6,2,10])
[1.3999999999999999, 2.0]
>>> f([[3,1],[0,0],[1,4]],[2,4,1])
[1.0, 0.8571428571428571]

感谢@Zgarb节省2个字节


有趣的递归解决方案(95个字节)

f=lambda c,m,x=0,y=0,s=0:f(c[1:],m[1:],x+c[0][0]*m[0],y+c[0][1]*m[0],s+m[0])if c else[x/s,y/s]

结果

>>> f([[0,2],[3,4],[0,1],[1,1]],[2,6,2,10])
[1.4, 2.0]
>>> f([[3,1],[0,0],[1,4]],[2,4,1])
[1.0, 0.8571428571428571]

2
我认为*([c]+[m])可以缩短为*[c,m]
Zgarb

0

公理,158字节

c(a:List List Float):List Float==(x:=y:=m:=0.;for i in 1..#a repeat(~index?(3,a.i)=>return[];x:=x+a.i.3*a.i.1;y:=y+a.i.3*a.i.2;m:=m+a.i.3);m=0.=>[];[x/m,y/m])

解开它

-- Input List of Coordinate and masses as [[xi,yi,mi]]
-- Return center of mass for the list a as [x,y] Float coordinates
-- or [] if some error occur [for example masses are all 0]
cc(a:List List Float):List Float==
    x:=y:=m:=0.
    for i in 1..#a repeat
         ~index?(3,a.i)=>return []
         x:=x+a.i.3*a.i.1
         y:=y+a.i.3*a.i.2
         m:=m+a.i.3
    m=0.=>return []
    return[x/m,y/m]

结果

(21) -> c([[0,2,2],[3,4,6],[0,1,2],[1,1,10]])
   (21)  [1.4,2.0]
                                                         Type: List Float
(22) -> c([[3,1,2],[0,0,4],[1,4,1]])
   (22)  [1.0,0.8571428571 4285714286]
                                                         Type: List Float

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.