Koordinatlar listesinden Kütle Merkezi ve kütleleri


20

İşte Pazartesi sabahı hızlı bir meydan okuma ...

Bir işlevi veya programı en az sayıda baytla yazın:

  • Girdi olarak bir [x,y]koordinat listesi alır
  • Girdi olarak [x,y]koordinatların ilgili kütlelerinin bir listesini alır
  • Hesaplanan kütle merkezini [xBar,yBar].

Not:

  • Dizi kullanıldığı sürece giriş herhangi bir biçimde alınabilir.

Kütle merkezi aşağıdaki formülle hesaplanabilir: Kütle Merkezi hesaplamaları

Sade ingilizce...

  • Bulmak için xBar, her kütleyi ilgili x koordinatıyla çarpın, elde edilen listeyi toplayın ve tüm kütlelerin toplamına bölün.
  • Bulmak için yBar, her kütleyi ilgili y koordinatıyla çarpın, elde edilen listeyi toplayın ve tüm kütlelerin toplamına bölün.

Önemsiz Python 2.7 örneği:

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]

Test Durumları:

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

Bu kod golf, bu yüzden en az bayt sayısı kazanır!


Bu sadece "ağırlıklı ortalama vektörleri hesapla" olduğundan daha önce yapmamış olsaydım oldukça şaşırırdım. (Şu anda hiçbir şey bulamıyorum.)
Martin Ender

@ MartinBüttner Ben de baktım ve bulamadım. Bu bir dupe ise, kapatmaktan çekinmeyin.
Bay Public

Girdi diğer sırada alınabilir mi? Ya da formda: [x,y,m],[x,y,m]...?
FryAmTheEggman

@FryAmTheEggman Geçerli girişler için düzenlenmiş soru.
Bay Public

@MrPublic: Peki ya [(x1,y1,m1), (x2,y2,m2)]örneğin bir tuples listesi? Yoksa argümanların tuples, listeler veya diziler olması önemli değil mi? Üç liste / diziye ne dersiniz?
Zeta

Yanıtlar:


21

MATL , 6 5 bayt

ys/Y*

Girdi biçimi, kütleleri olan bir satır vektörü, ardından koordinatlarla (boşlukların veya virgüllerin isteğe bağlı olduğu) iki sütunlu bir matristir.

  • İlk örnek:

    [2, 6, 2, 10]
    [0,2; 3,4; 0,1; 1,1]
    
  • İkinci örnek:

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

Çevrimiçi deneyin!

açıklama

Let mkitlelerin vektörü (birinci giriş) ve göstermektedirler ckoordinatlar matrisi (ikinci giriş).

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

yoldukça yararlı !! +1
David

@David Evet! Örtük girdi ile birleştiğinde, bu durumda bir çok şey yapar :-)
Luis Mendo

7

Mathematica, 10 bayt

#.#2/Tr@#&

Örnek:

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

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

1
Hiç kullanmadım Dot. Ama yukarıdaki kullanımınızı gördükten sonra göreceğim!
DavidC

7

Mathcad, 19 "bayt"

resim açıklamasını buraya girin

  • Mathcad'ın veri girişi için tablolarını kullanır
  • Eksen koordinat ve kütlesini çarpmak için Mathcad'ın yerleşik vektör skaler ürününü kullanır
  • Toplam kütle için Mathcad'ın yerleşik toplama işlecini kullanır

Mathcad bir 2B "beyaz tahta" ve özel işleçler (örn. Toplama işleci, tümleşik işleci) kullandığından ve XML biçiminde kaydedildiğinden, gerçek bir çalışma sayfasında birkaç yüz (veya daha fazla) karakter bulunabilir. Code Golf amacıyla, kullanıcının çalışma sayfasını oluşturmak için girmesi gereken karakter veya operatör sayısı olarak bir Mathcad "bayt sayısı" aldım.

Sorunun ilk (program) sürümü bu tanımı kullanarak 19 "bayt" alır ve fonksiyon sürümü 41 "bayt" alır.


3
İlk kez burada bir Matcad çözümü gördüm. Çok hoş. +1.
rayryeng - Monica

Teşekkürler, rayryeng. Muhtemelen Mathcad'ın sadece basit dize işlevlerine sahip olduğu ve insan tarafından okunabilen, salt metin kaynak koduna sahip olmadığı göz önüne alındığında, "kurs" üzerindeki bazı "delikleri" yapmak biraz zor.
Stuart Bruff

6

MATLAB / Oktav, 18 16 bayt

2 bayt kaldırmak için kullanıcı beher ve Don Muesli sayesinde!

Koordinatların , birinci sütunun X koordinatı ve ikinci sütunun Y koordinatı olduğu ve kütlelerin bir matriste (veya bir satır vektörü) olduğu bir N x 2matriste xolduğu göz önüne alındığında :1 x Ny

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

Bu kodun açıklaması oldukça basittir. Bu iki giriş alır anonim fonksiyondur xve y. Ağırlıklı toplamı (her koordinatın pay ifadesi) matris-vektör çarpımı kullanarak doğrusal bir cebir yaklaşımında gerçekleştiriyoruz. Kütle vektörü alarak yve bunu xmatris-vektör çarpımı ile koordinat matrisi ile çarparak , her iki koordinatın ağırlıklı toplamını ayrı ayrı hesaplarsınız, daha sonra bu koordinatların her birini kütlelerin toplamına böleriz, böylece istenen merkez kütle, sırasıyla her koordinat için 1 x 2 sıra vektörü olarak geri döndü.

Örnek çalıştırmalar

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

Çevrimiçi deneyin!

https://ideone.com/BzbQ3e


1
Çıkarılabilir ;ve ayrıca 'giriş biçimini ( xsatır vektörü olarak) doğru bir şekilde seçerek
Luis Mendo

@DonMuesli Thanks :) Bayt sayısını 2
azalttı

6

Jöle, 6 bayt

S÷@×"S

veya

÷S$×"S

Girdi iki komut satırı argümanı ile yapılır, önce kütleler, ikinci koordinatlar.

Çevrimiçi deneyin!

açıklama

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

veya

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

6

Julia, 25 17 bayt

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

Açık yaklaşımı kaçırdım: / Gibi arayın f([3 1;0 0;1 4], [2 4 1]).


5

CJam, 14 bayt

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

Adsız bir işlev, koordinat çiftlerinin listesini ve yığındaki kütle listesini (bu sırayla) bekler ve kütle merkezini yerinde bırakır.

Burada test edin.

açıklama

_    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

Ciddi, 16 bayt

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

Girişi alır [x-coords]\n[y-coords]\n[masses]ve çıktısını alırxbar\nybar

Çevrimiçi deneyin!

Açıklama:

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

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

Bu, faşağıdaki gibi kullanılan bir ikili işlevi tanımlar :

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

Her iki test vakasını geçtiğine bakın.

açıklama

Haskell çok boyutlu listeleri işlemek için uygun değil, bu yüzden burada bazı halkalar atlıyorum. İlk satır, zipWithiki kez ihtiyacımız olan kısa bir takma ad tanımlar . Temel olarak, fağırlıkların listesini oluşturan ave üreten f abir fonksiyon, pozisyon listesini alan ve kütle merkezini üreten bir fonksiyondur. f aüç fonksiyonun bir bileşimidir:

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 bayt

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

(X, y, kütle) "üçlü" dizisini kabul eder ve bir "demet" döndürür.


Etrafta parantez [x,y,m]gerekli mi? iirc, ok işlevinde yalnızca bir girdi bağımsız değişkeni varsa bunlara gerek yoktur.
Patrick Roberts

@PatrickRoberts Evet, tek bir standart argümanın önemsiz biri dışında her durumda gereklidirler.
Neil

3

R, 32 25 bayt

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

matris cebirine göre -7 bayt değiştir (teşekkürler @ Sp3000 Julia cevap)

bir dizi (2 sütunlu matris, x, y) koordinat ve mağırlık vektörü olarak geçirir, gerekli koordinatlara sahip bir dizi döndürür


2

PHP, 142 bayt

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)];}
Parçalarına ayrıştırılmış görünüm
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) ];
}
Gerekli giriş
Array[Array]: [ [ mass1, mass2, ... ],
                [ xpos1, xpos2, ... ],
                [ ypos1, ypos2, ... ] ]
Dönüş

Array: [ xbar, ybar ]


p()Fonksiyonu, her çarpılmasıyla temel bir haritasıdır [m]karşılık gelen bir değer [x]veya [y]değer. c()Fonksiyonun içinde tuttuğu Array[Array], hediye array_sumve array_mapalan için fonksiyonlar, daha sonra hesaplar Σmx/Σmve Σmy/Σm.

Hesaplamanın kendisini alan için bir fonksiyona dönüştürmek mümkün olabilir, göreceksiniz.


2

Mathcad, 8 "bayt"

Önceki cevabımda ne düşünmediğimi bilmiyorum. İşte matris çarpımını doğru şekilde kullanmanın daha kısa bir yolu. P değişkeni verileri içerir - eğer değişken sayılarını toplama doğru ayarlarsanız, başka bir 2 "bayt" ekler (giriş tablosunun oluşturulması = 1 bayt, değişken adı = 1 bayt).

resim açıklamasını buraya girin


1

Python 3, 63 bayt

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

Listelerdeki vektör işlemleri uzun: /

Bu anonim bir lambda fonksiyonudur - ona bir isim verin ve böyle çağırın f([[0,2],[3,4],[0,1],[1,1]],[2,6,2,10]).


1

Python 3, 95 90 88 bayt

Çözüm

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

Sonuçlar

>>> 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 bayt tasarruf sayesinde


Eğlence için özyinelemeli bir çözüm (95 bayt)

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]

Sonuçlar

>>> 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
Bence *([c]+[m])kısaltılabilir *[c,m].
Zgarb

0

Aksiyom, 158 bayt

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

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

Sonuçlar

(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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.