Trung tâm thánh lễ từ một danh sách tọa độ và khối lượng của chúng


20

Đây là một thử thách sáng thứ Hai nhanh chóng ...

Viết hàm hoặc chương trình với số byte ít nhất:

  • Đưa vào danh sách [x,y]tọa độ
  • Đưa vào danh sách [x,y]khối lượng tương ứng của tọa độ
  • Xuất ra tâm khối lượng tính toán dưới dạng [xBar,yBar].

Chú thích:

  • Đầu vào có thể được thực hiện dưới mọi hình thức, miễn là một mảng được sử dụng.

Trung tâm khối lượng có thể được tính theo công thức sau: Trung tâm tính toán khối lượng

Nói một cách dễ hiểu ...

  • Để tìm xBar, nhân mỗi khối lượng với tọa độ x tương ứng của nó, tính tổng danh sách kết quả và chia nó cho tổng của tất cả các khối lượng.
  • Để tìm yBar, nhân mỗi khối lượng với tọa độ y tương ứng của nó, tính tổng danh sách kết quả và chia nó cho tổng của tất cả các khối lượng.

Ví dụ tầm thường 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]

Các trường hợp thử nghiệm:

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

Đây là môn đánh gôn, vì vậy số byte ít nhất sẽ thắng!


Vì đây chỉ là "tính toán trung bình các vectơ", tôi sẽ khá ngạc nhiên nếu chúng ta chưa từng làm điều đó trước đây. (Hiện tại, tôi không thể tìm thấy bất cứ điều gì.)
Martin Ender

@ MartinBüttner Tôi cũng nhìn như vậy, và không thể tìm thấy bất kỳ. Nếu đây là một bản dupe, hãy đóng nó lại.
Mr Public

Đầu vào có thể được thực hiện theo thứ tự khác? Hoặc ở dạng : [x,y,m],[x,y,m]...?
FryAmTheEggman

@FryAmTheEggman Câu hỏi được chỉnh sửa cho đầu vào hợp lệ.
Mr Public

@MrPublic: Thế còn [(x1,y1,m1), (x2,y2,m2)]một danh sách các bộ dữ liệu thì sao? Hoặc không quan trọng cho dù các đối số là bộ dữ liệu, danh sách hoặc mảng? Thế còn ba danh sách / mảng?
Zeta

Câu trả lời:


21

MATL , 6 5 byte

ys/Y*

Định dạng đầu vào là một vectơ hàng có khối lượng, sau đó là ma trận hai cột có tọa độ (trong đó khoảng trắng hoặc dấu phẩy là tùy chọn).

  • Ví dụ đầu tiên:

    [2, 6, 2, 10]
    [0,2; 3,4; 0,1; 1,1]
    
  • Ví dụ thứ hai:

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

Hãy thử trực tuyến!

Giải trình

Hãy mbiểu thị vectơ khối lượng (đầu vào đầu tiên) và cma trận tọa độ (đầu vào thứ hai).

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

ylà khá hữu ích !! +1
David

@David Vâng! Kết hợp với đầu vào ngầm, nó thực hiện rất nhiều thứ trong trường hợp này :-)
Luis Mendo

7

Toán học, 10 byte

#.#2/Tr@#&

Thí dụ:

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

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

1
Tôi không bao giờ sử dụng Dot. Nhưng tôi sẽ sau khi thấy cách sử dụng của bạn ở trên!
DavidC

7

Mathcad, 19 "byte"

nhập mô tả hình ảnh ở đây

  • Sử dụng các bảng của Mathcad để nhập dữ liệu
  • Sử dụng sản phẩm vô hướng vectơ tích hợp của Mathcad để nhân khối lượng và khối lượng trục
  • Sử dụng toán tử tổng hợp tích hợp của Mathcad cho tổng khối lượng

Vì Mathcad sử dụng "bảng trắng" 2D và các toán tử đặc biệt (ví dụ: toán tử tổng, toán tử tích phân) và lưu ở định dạng XML, một bảng tính thực tế có thể chứa hàng trăm (hoặc hơn) ký tự. Với mục đích của Code Golf, tôi đã lấy "số byte" của Mathcad là số lượng ký tự hoặc toán tử mà người dùng phải nhập để tạo bảng tính.

Phiên bản (chương trình) đầu tiên của thử thách mất 19 "byte" bằng cách sử dụng định nghĩa này và phiên bản hàm mất 41 "byte".


3
Lần đầu tiên tôi từng thấy một giải pháp Matcad ở đây. Rất đẹp. +1.
rayryeng - Phục hồi Monica

Cảm ơn bạn, rayryeng. Có lẽ bởi vì có một chút thách thức khi thực hiện một số "lỗ hổng" trong "khóa học" do Mathcad chỉ có các hàm chuỗi cơ bản và không có mã nguồn chỉ có văn bản, có thể đọc được.
Stuart Bruff 7/03/2016

6

MATLAB / Octave, 18 16 byte

Cảm ơn người dùng cốc và Don Muesli đã xóa 2 byte!

Cho rằng các tọa độ nằm trong một N x 2ma trận xtrong đó cột đầu tiên là tọa độ X và cột thứ hai là tọa độ Y và các khối lượng nằm trong một 1 x Nma trận y(hoặc một vectơ hàng):

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

Giải thích về mã này là khá thẳng về phía trước. Đây là một chức năng ẩn danh có hai đầu vào xy. Chúng tôi thực hiện phép tính tổng (trọng số của biểu thức của mỗi tọa độ) theo cách tiếp cận đại số tuyến tính bằng cách sử dụng phép nhân vectơ ma trận. Bằng cách lấy vectơ ykhối lượng và nhân số này với ma trận tọa độ xbằng phép nhân vectơ ma trận, bạn sẽ tính tổng trọng số của cả hai tọa độ, sau đó chúng ta chia mỗi tọa độ này cho tổng khối lượng do đó tìm được tâm của khối lượng được trả về dưới dạng một vectơ 1 x 2 cho mỗi tọa độ tương ứng.

Ví dụ chạy

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

Hãy thử trực tuyến!

https://ideone.com/BzbQ3e


1
Bạn có thể xóa ;và cũng 'bằng cách chọn đúng định dạng đầu vào (dưới dạng xvectơ hàng)
Luis Mendo 7/03/2016

@DonMuesli Cảm ơn :) Giảm số byte xuống 2.
rayryeng - Tái lập lại Monica

6

Thạch, 6 byte

S÷@×"S

hoặc là

÷S$×"S

Đầu vào là thông qua hai đối số dòng lệnh, khối lượng đầu tiên, tọa độ thứ hai.

Hãy thử trực tuyến!

Giải trình

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

hoặc là

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

Bỏ lỡ cách tiếp cận rõ ràng: / Gọi như thế f([3 1;0 0;1 4], [2 4 1]).


5

CJam, 14 byte

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

Một hàm không tên với mong muốn danh sách các cặp tọa độ và danh sách khối lượng trên ngăn xếp (theo thứ tự đó) và để lại tâm khối lượng ở vị trí của chúng.

Kiểm tra nó ở đây.

Giải trình

_    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

Nghiêm túc, 16 byte

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

Lấy đầu vào là [x-coords]\n[y-coords]\n[masses]và đầu ra làxbar\nybar

Hãy thử trực tuyến!

Giải trình:

╩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

Điều này định nghĩa một hàm nhị phân f, được sử dụng như sau:

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

Xem nó vượt qua cả hai trường hợp thử nghiệm.

Giải trình

Haskell không phù hợp để xử lý các danh sách đa chiều, vì vậy tôi đang nhảy qua một số vòng ở đây. Dòng đầu tiên xác định một bí danh ngắn zipWith, mà chúng ta cần hai lần. Về cơ bản, flà một hàm lấy danh sách các trọng số avà tạo ra f a, một hàm lấy danh sách các vị trí và tạo ra tâm khối lượng. f alà một thành phần của ba chức năng:

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]

Chấp nhận một mảng (x, y, khối lượng) "bộ ba" và trả về một "bộ".


Là dấu ngoặc đơn xung quanh [x,y,m]cần thiết? iirc, chúng không bắt buộc nếu chỉ có một đối số đầu vào cho hàm mũi tên.
Patrick Roberts

@PatrickRoberts Có, chúng cần thiết trong mọi trường hợp ngoại trừ một đối số tầm thường trong một đối số chính xác.
Neil

3

R, 32 25 byte

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

chỉnh sửa -7 byte bằng cách chuyển sang đại số ma trận (cảm ơn @ Sp3000 Julia trả lời)

truyền một mảng (ma trận có 2 cột, x, y) làm tọa độ và vectơ mtrọng số, trả về một mảng có tọa độ cần thiết


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)];}
Khung nhìn bùng nổ
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) ];
}
Yêu cầu đầu vào
Array[Array]: [ [ mass1, mass2, ... ],
                [ xpos1, xpos2, ... ],
                [ ypos1, ypos2, ... ] ]
Trở về

Array: [ xbar, ybar ]


Các p()chức năng là một bản đồ cơ bản, nhân mỗi [m]giá trị với tương ứng [x]hoặc [y]giá trị. Các c()chức năng có trong Array[Array], trình bày array_sumarray_map chức năng cho không gian, sau đó tính toán Σmx/ΣmΣmy/Σm.

Có thể biến chính phép tính thành hàm cho không gian, sẽ thấy.


2

Mathcad, 8 "byte"

Tôi không biết những gì tôi đã không nghĩ về câu trả lời trước đây của tôi. Đây là một cách ngắn hơn để sử dụng đúng cách nhân ma trận. Biến p chứa dữ liệu - nếu đặt biến số đếm theo tổng, sau đó thêm 2 "byte" khác (tạo bảng đầu vào = 1 byte, tên biến = 1 byte).

nhập mô tả hình ảnh ở đây


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

Các hoạt động của vectơ trong danh sách dài: /

Đây là một hàm lambda ẩn danh - đặt tên và gọi như thế f([[0,2],[3,4],[0,1],[1,1]],[2,6,2,10]).


1

Python 3, 95 90 88 byte

Dung dịch

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

Các kết quả

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

nhờ @Zgarb tiết kiệm 2 byte


Một giải pháp đệ quy cho vui (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]

Các kết quả

>>> 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
Tôi nghĩ rằng *([c]+[m])có thể được rút ngắn để *[c,m].
Zgarb

0

Tiên đề, 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])

không có nó

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

các kết quả

(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

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.