Pusat Misa dari daftar koordinat dan massa mereka

20

Berikut ini tantangan Senin pagi yang cepat ...

Tulis fungsi atau program dengan jumlah byte paling sedikit yang:

  • Dibawa sebagai input daftar [x,y]koordinat
  • Dibawa sebagai input daftar [x,y]massa masing-masing koordinat
  • Menghasilkan pusat massa yang dihitung dalam bentuk [xBar,yBar].

catatan:

  • Input dapat diambil dalam bentuk apa pun, selama array digunakan.

Pusat massa dapat dihitung dengan rumus berikut: Pusat perhitungan Massa

Dalam bahasa Inggris ...

  • Untuk menemukan xBar, gandakan setiap massa dengan koordinat x masing-masing, jumlahkan daftar yang dihasilkan, dan bagi dengan jumlah semua massa.
  • Untuk menemukan yBar, gandakan setiap massa dengan koordinat y masing-masing, jumlahkan daftar yang dihasilkan, dan bagi dengan jumlah semua massa.

Trivial Python 2.7 contoh:

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]

Kasus uji:

> 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]

Ini adalah kode-golf, jadi jumlah byte terkecil yang menang!

Tuan Umum
sumber
Karena ini hanya "menghitung rata-rata tertimbang vektor", saya akan sangat terkejut jika kita belum melakukannya sebelumnya. (Saat ini, saya tidak dapat menemukan apa pun.)
Martin Ender
@ MartinBüttner Saya melihat juga, dan tidak dapat menemukan. Jika ini sebuah penipuan, jangan ragu untuk menutupnya.
Tuan Umum
Bisakah input diambil dalam urutan lain? Atau dalam bentuk [x,y,m],[x,y,m]...:?
FryAmTheEggman
@FryAmTheEggman Pertanyaan diedit untuk input yang valid.
Tn. Public
@ McPublic: Bagaimana dengan [(x1,y1,m1), (x2,y2,m2)], misalnya daftar tupel? Atau tidak masalah apakah argumennya adalah tupel, daftar atau array? Bagaimana dengan tiga daftar / array?
Zeta

Jawaban:

21

MATL , 6 5 byte

ys/Y*

Format input adalah vektor baris dengan massa, kemudian matriks dua kolom dengan koordinat (di mana spasi atau koma adalah opsional).

  • Contoh pertama:

    [2, 6, 2, 10]
    [0,2; 3,4; 0,1; 1,1]
    
  • Contoh kedua:

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

Cobalah online!

Penjelasan

Biarkan mmenunjukkan vektor massa (input pertama) dan cmatriks koordinat (input kedua).

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
Luis Mendo
sumber
ysangat berguna !! +1
David
@ David Ya! Dikombinasikan dengan input implisit, ia melakukan banyak hal dalam hal ini :-)
Luis Mendo
7

Mathematica, 10 byte

#.#2/Tr@#&

Contoh:

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

Out[1]= {7/5, 2}
alephalpha
sumber
1
Saya tidak pernah menggunakan Dot. Tapi saya akan setelah melihat penggunaan Anda di atas!
DavidC
7

Mathcad, 19 "byte"

masukkan deskripsi gambar di sini

  • Menggunakan tabel Mathcad untuk input data
  • Menggunakan produk skalar vektor bawaan Mathcad untuk mengalikan ordinat dan massa
  • Menggunakan operator penjumlahan bawaan Mathcad untuk massa total

Karena Mathcad menggunakan "papan tulis" 2D dan operator khusus (misalnya, operator penjumlahan, operator integral), dan menyimpan dalam format XML, lembar kerja yang sebenarnya mungkin berisi beberapa ratus (atau lebih) karakter. Untuk keperluan Code Golf, saya telah mengambil "byte byte" Mathcad untuk menjadi jumlah karakter atau operator yang harus dimasukkan pengguna untuk membuat lembar kerja.

Versi (program) pertama dari tantangan membutuhkan 19 "byte" menggunakan definisi ini dan versi fungsi mengambil 41 "byte".

Stuart Bruff
sumber
3
Pertama kali saya pernah melihat solusi Matcad di sini. Sangat bagus. +1.
rayryeng
Terima kasih, rayryeng. Itu mungkin karena itu sedikit tantangan melakukan beberapa "lubang" pada "kursus" mengingat bahwa Mathcad hanya memiliki fungsi string dasar dan tidak memiliki kode sumber yang dapat dibaca manusia, hanya teks.
Stuart Bruff
6

MATLAB / Oktaf, 18 16 byte

Terima kasih kepada pengguna beaker dan Don Muesli karena telah menghapus 2 byte!

Mengingat bahwa koordinat berada dalam N x 2matriks di xmana kolom pertama adalah koordinat X dan kolom kedua adalah koordinat Y, dan massa berada dalam 1 x Nmatriks y(atau vektor baris):

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

Penjelasan kode ini cukup mudah. Ini adalah fungsi anonim yang mengambil dua input xdan y. Kami melakukan penjumlahan berbobot (ekspresi pembilang dari setiap koordinat) dalam pendekatan aljabar linier menggunakan perkalian matriks-vektor. Dengan mengambil vektor ymassa dan mengalikannya dengan matriks koordinatx dengan perkalian matriks-vektor, Anda akan menghitung jumlah tertimbang dari kedua koordinat secara individual, kemudian kami membagi masing-masing koordinat ini dengan jumlah massa sehingga menemukan pusat yang diinginkan dari massa dikembalikan sebagai vektor baris 1 x 2 untuk masing-masing koordinat.

Contoh berjalan

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

Cobalah online!

https://ideone.com/BzbQ3e

rayryeng - Reinstate Monica
sumber
1
Anda dapat menghapus ;, dan juga 'dengan memilih format input dengan benar ( xsebagai vektor baris)
Luis Mendo
@DonMuesli Terima kasih :) Mengurangi jumlah byte 2.
rayryeng - Reinstate Monica
6

Jelly, 6 byte

S÷@×"S

atau

÷S$×"S

Input adalah melalui dua argumen baris perintah, massa pertama, koordinat kedua.

Cobalah online!

Penjelasan

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

atau

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

Julia, 25 17 byte

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

Kehilangan pendekatan yang jelas: / Sebut suka f([3 1;0 0;1 4], [2 4 1]).

Sp3000
sumber
5

CJam, 14 byte

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

Fungsi yang tidak disebutkan namanya dengan mengharapkan daftar pasangan koordinat dan daftar massa pada tumpukan (dalam urutan itu) dan meninggalkan pusat massa di tempatnya.

Uji di sini.

Penjelasan

_    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.
Martin Ender
sumber
5

Perl 6, 36 33 30 byte

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

Serius, 16 byte

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

Mengambil input as [x-coords]\n[y-coords]\n[masses], dan output asxbar\nybar

Cobalah online!

Penjelasan:

╩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
Mego
sumber
3

Haskell, 55 50 byte

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

Ini mendefinisikan fungsi biner f, digunakan sebagai berikut:

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

Lihat lulus kedua kasus uji.

Penjelasan

Haskell tidak cocok untuk memproses daftar multidimensi, jadi saya melompati beberapa lingkaran di sini. Baris pertama mendefinisikan alias pendek untuk zipWith, yang kita butuhkan dua kali. Pada dasarnya, fadalah fungsi yang mengambil daftar bobot adan menghasilkan f a, fungsi yang mengambil daftar posisi dan menghasilkan pusat massa. f aadalah komposisi dari tiga fungsi:

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
Zgarb
sumber
3

JavaScript (ES6), 60 byte

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

Menerima larik (x, y, massa) "tiga kali lipat" dan mengembalikan "tuple".

Neil
sumber
Apakah tanda kurung [x,y,m]diperlukan? iirc, mereka tidak diperlukan jika hanya ada satu argumen input ke fungsi panah.
Patrick Roberts
@ PatrickRoberts Ya, mereka diperlukan dalam semua kasus kecuali satu yang sepele dari satu argumen standar.
Neil
3

R, 32 25 byte

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

sunting -7 bytes dengan beralih ke aljabar matriks (terima kasih @ Sp3000 Julia jawaban)

melewatkan array (matriks dengan 2 kolom, x, y) sebagai koordinat dan vektor mbobot, mengembalikan array dengan koordinat yang diperlukan

mnel
sumber
2

PHP, 142 byte

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)];}
Tampilan meledak
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) ];
}
Input yang dibutuhkan
Array[Array]: [ [ mass1, mass2, ... ],
                [ xpos1, xpos2, ... ],
                [ ypos1, ypos2, ... ] ]
Kembali

Array: [ xbar, ybar ]


The p()fungsi peta dasar, mengalikan setiap [m]nilai dengan yang sesuai [x]atau [y]nilai. The c()fungsi mengambil di Array[Array], hadiah yang array_sumdan array_mapfungsi untuk ruang, kemudian menghitung Σmx/Σmdan Σmy/Σm.

Mungkin akan mengubah perhitungan itu sendiri menjadi fungsi untuk ruang, akan melihat.

ricdesi
sumber
2

Mathcad, 8 "byte"

Saya tidak tahu apa yang tidak saya pikirkan dalam jawaban saya sebelumnya. Inilah cara yang lebih singkat untuk menggunakan perkalian matriks dengan tepat. Variabel p berisi data - jika mengatur jumlah variabel terhadap total, maka tambahkan 2 "byte" lainnya (pembuatan tabel input = 1 byte, nama variabel = 1 byte).

masukkan deskripsi gambar di sini

Stuart Bruff
sumber
1

Python 3, 63 byte

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

Operasi vektor pada daftar panjang: /

Ini adalah fungsi lambda anonim - berikan nama dan panggilan seperti f([[0,2],[3,4],[0,1],[1,1]],[2,6,2,10]).

Sp3000
sumber
1

Python 3, 95 90 88 byte

Larutan

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

Hasil

>>> 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]

terima kasih kepada @Zgarb yang menghemat 2 byte


Solusi rekursif untuk bersenang-senang (95 byte)

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]

Hasil

>>> 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]
Erwan
sumber
2
Saya pikir *([c]+[m])bisa disingkat *[c,m].
Zgarb
0

Aksioma, 158 byte

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])

ungolf itu

-- 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]

hasil

(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
RosLuP
sumber
0

k, 13 byte

{(+/x*y)%+/y}

Cobalah online!

zgrep
sumber