Centrum masy z listy współrzędnych i ich mas

20

Oto szybkie wyzwanie w poniedziałek rano ...

Napisz funkcję lub program w najmniejszej liczbie bajtów, która:

  • Pobiera na wejściu listę [x,y]współrzędnych
  • Pobiera na wejściu listę [x,y]odpowiednich mas współrzędnych
  • Wysyła obliczony środek masy w postaci [xBar,yBar].

Uwaga:

  • Dane wejściowe można przyjmować w dowolnej formie, o ile używana jest tablica.

Środek masy można obliczyć według następującego wzoru: Obliczenia środka masy

W prostym angielskim...

  • Aby znaleźć xBar, pomnóż każdą masę przez odpowiednią współrzędną x, zsumuj wynikową listę i podziel ją przez sumę wszystkich mas.
  • Aby znaleźć yBar, pomnóż każdą masę przez odpowiednią współrzędną y, zsumuj wynikową listę i podziel ją przez sumę wszystkich mas.

Przykład z Trivial 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]

Przypadki testowe:

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

To jest golf golfowy, więc wygrywa najmniej bajtów!

Mr Public
źródło
Ponieważ jest to tylko „obliczenie średniej ważonej wektorów”, byłbym bardzo zaskoczony, gdybyśmy tego wcześniej nie robili. (W tej chwili nic nie mogę znaleźć.)
Martin Ender
@ MartinBüttner Też szukałem i nie mogłem znaleźć. Jeśli jest to duplikat, możesz go jednak zamknąć.
Pan Public
Czy dane wejściowe można podjąć w innej kolejności? Lub w formie [x,y,m],[x,y,m]...:?
FryAmTheEggman
@FryAmTheEggman Pytanie edytowane dla poprawnych danych wejściowych.
Pan Public
@MrPublic: A co z [(x1,y1,m1), (x2,y2,m2)]np. Listą krotek? Czy nie ma znaczenia, czy argumentami są krotki, listy czy tablice? Co z trzema listami / tablicami?
Zeta

Odpowiedzi:

21

MATL , 6 5 bajtów

ys/Y*

Format wejściowy to wektor wiersza z masami, a następnie macierz dwukolumnowa ze współrzędnymi (w których spacje lub przecinki są opcjonalne).

  • Pierwszy przykład:

    [2, 6, 2, 10]
    [0,2; 3,4; 0,1; 1,1]
    
  • Drugi przykład:

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

Wypróbuj online!

Wyjaśnienie

Niech moznaczymy wektor mas (pierwsze wejście) i cmacierz współrzędnych (drugie wejście).

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
źródło
yjest bardzo przydatne !! +1
David
@David Tak! W połączeniu z niejawnymi danymi wejściowymi robi w tym przypadku wiele rzeczy :-)
Luis Mendo,
7

Mathematica, 10 bajtów

#.#2/Tr@#&

Przykład:

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

Out[1]= {7/5, 2}
alephalpha
źródło
1
Nigdy nie używany Dot. Ale zrobię to po zobaczeniu twojego użycia powyżej!
DavidC,
7

Mathcad, 19 „bajtów”

enter image description here

  • Używa tabel Mathcada do wprowadzania danych
  • Korzysta z wbudowanego wektorowego skalarnego wektora Mathcada do mnożenia rzędnych osi i masy
  • Używa wbudowanego operatora sumowania Mathcada dla masy całkowitej

Ponieważ Mathcad używa 2D „tablicy” i operatorów specjalnych (np. Operatora sumowania, operatora całkującego) i zapisuje w formacie XML, rzeczywisty arkusz roboczy może zawierać kilkaset (lub więcej) znaków. Na potrzeby Code Golf podjąłem „liczbę bajtów” Mathcada, która jest liczbą znaków lub operatorów, które użytkownik musi wprowadzić, aby utworzyć arkusz.

Pierwsza (programowa) wersja wyzwania zajmuje 19 „bajtów” przy użyciu tej definicji, a wersja funkcji zajmuje 41 „bajtów”.

Stuart Bruff
źródło
3
Pierwszy raz widziałem tutaj rozwiązanie Matcad. Bardzo dobrze. +1.
rayryeng - Przywróć Monikę
Dziękuję Rayryeng. Prawdopodobnie dlatego, że wykonywanie niektórych „dziur” na „kursie” stanowi wyzwanie, ponieważ Mathcad ma tylko podstawowe funkcje łańcuchowe i nie ma czytelnego dla człowieka, tekstowego kodu źródłowego.
Stuart Bruff,
6

MATLAB / Octave, 18 16 bajtów

Dzięki zlewce użytkownika i Donowi Musli za usunięcie 2 bajtów!

Biorąc pod uwagę, że współrzędne są w N x 2macierzy, xgdzie pierwsza kolumna jest współrzędną X, a druga kolumna jest współrzędną Y, a masy są w 1 x Nmacierzy y(lub wektorze wiersza):

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

Wyjaśnienie tego kodu jest dość proste. Jest to anonimowa funkcja, która przyjmuje dwa wejścia xi y. Wykonujemy ważone sumowanie (wyrażenie licznika każdej współrzędnej) w algebrze liniowej przy użyciu mnożenia macierzy-wektora. Biorąc wektory mas i mnożąc go przez macierz współrzędnych xprzez mnożenie macierzy-wektora, obliczymy indywidualnie ważoną sumę obu współrzędnych, a następnie dzielimy każdą z tych współrzędnych przez sumę mas, w ten sposób znajdując pożądany środek masa zwrócona jako wektor 1 x 2 wierszy odpowiednio dla każdej współrzędnej.

Przykład działa

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

Wypróbuj online!

https://ideone.com/BzbQ3e

rayryeng - Przywróć Monikę
źródło
1
Możesz usunąć ;, a także 'odpowiednio wybierając format wejściowy ( xjako wektor wiersza)
Luis Mendo
@DonMuesli Dzięki :) Zmniejszono liczbę bajtów o 2.
rayryeng - Przywróć Monikę
6

Galaretka, 6 bajtów

S÷@×"S

lub

÷S$×"S

Wprowadzanie odbywa się za pomocą dwóch argumentów wiersza polecenia, najpierw masy, a druga koordynuje.

Wypróbuj online!

Wyjaśnienie

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

lub

÷S$     Divide the masses by their sum.
   ×"   Multiply each vector by the corresponding normalised mass.
     S  Sum the vectors.
Martin Ender
źródło
6

Julia, 25 17 bajtów

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

Pominięto oczywiste podejście: / Call like f([3 1;0 0;1 4], [2 4 1]).

Sp3000
źródło
5

CJam, 14 bajtów

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

Bezimienna funkcja z oczekuje listy par współrzędnych i listy mas na stosie (w tej kolejności) i pozostawia środek masy na swoim miejscu.

Sprawdź to tutaj.

Wyjaśnienie

_    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
źródło
5

Perl 6, 36 33 30 bajtów

{[Z+](@^a Z»*»@^b) X/sum @b}
Skróty klawiszowe
źródło
4

Poważnie, 16 bajtów

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

Pobiera dane wejściowe jako [x-coords]\n[y-coords]\n[masses] , a dane wyjściowe jakoxbar\nybar

Wypróbuj online!

Wyjaśnienie:

╩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
źródło
3

Haskell, 55 50 bajtów

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

Definiuje to funkcję binarną f, używaną w następujący sposób:

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

Zobacz, jak przejdzie oba przypadki testowe.

Wyjaśnienie

Haskell nie nadaje się do przetwarzania list wielowymiarowych, więc przeskakuję tutaj przez kilka obręczy. Pierwszy wiersz określa krótki alias, do zipWithktórego potrzebujemy dwa razy. Zasadniczo fjest to funkcja, która pobiera listę wag ai tworzy f a, funkcja, która przyjmuje listę pozycji i tworzy środek masy. f ato kompozycja trzech funkcji:

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
źródło
3

JavaScript (ES6), 60 bajtów

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

Akceptuje tablicę „x, y, masa” „trzykrotnie” i zwraca „krotkę”.

Neil
źródło
Czy nawiasy wokół są [x,y,m]konieczne? iirc, nie są wymagane, jeśli do funkcji strzałki jest tylko jeden argument wejściowy.
Patrick Roberts,
@PatrickRoberts Tak, są one konieczne we wszystkich przypadkach, z wyjątkiem tego, że jeden trywialny z dokładnie jednego standardowego argumentu.
Neil,
3

R, 32 25 bajtów

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

edytuj -7 bajtów przełączając na algebrę macierzy (dzięki @ Sp3000 odpowiedź Julii)

przekazać tablicę (macierz z 2 kolumnami, x, y) jako współrzędne i wektor mwag, zwraca tablicę z wymaganymi współrzędnymi

mnel
źródło
2

PHP, 142 bajty

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)];}
Widok rozstrzelony
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) ];
}
Wymagane dane wejściowe
Array[Array]: [ [ mass1, mass2, ... ],
                [ xpos1, xpos2, ... ],
                [ ypos1, ypos2, ... ] ]
Powrót

Array: [ xbar, ybar ]


Ta p()funkcja jest mapą podstawową, pomnożącą każdą [m]wartość z odpowiednią [x]lub [y]wartością. c()Funkcja przyjmuje w Array[Array], prezentuje array_sumiarray_map funkcje przestrzeni, a następnie oblicza Σmx/Σmi Σmy/Σm.

Zobaczysz, że może być możliwe przekształcenie samego obliczenia w funkcję przestrzeni.

ricdesi
źródło
2

Mathcad, 8 „bajtów”

Nie wiem, o czym nie myślałem w mojej poprzedniej odpowiedzi. Oto krótszy sposób właściwego wykorzystania mnożenia macierzy. Zmienna p zawiera dane - jeśli ustawienie zmiennej liczy się do sumy, to dodaj kolejne 2 „bajty” (tworzenie tabeli wprowadzania = 1 bajt, nazwa zmiennej = 1 bajt).

wprowadź opis zdjęcia tutaj

Stuart Bruff
źródło
1

Python 3, 63 bajty

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

Operacje wektorowe na listach są długie: /

Jest to anonimowa funkcja lambda - nadaj jej nazwę i wywołaj jak f([[0,2],[3,4],[0,1],[1,1]],[2,6,2,10]).

Sp3000
źródło
1

Python 3, 95 90 88 bajtów

Rozwiązanie

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

Wyniki

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

dzięki @Zgarb oszczędza 2 bajty


Rekurencyjne rozwiązanie dla zabawy (95 bajtów)

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]

Wyniki

>>> 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
źródło
2
Myślę, że *([c]+[m])można go skrócić *[c,m].
Zgarb,
0

Aksjomat, 158 bajtów

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

zagrać w golfa

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

wyniki

(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
źródło