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!


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

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}

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


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


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.

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


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.


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

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

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


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


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.


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


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


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]

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

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.