座標とその質量のリストからの重心


20

これは月曜日の朝の簡単なチャレンジです...

以下の最小バイト数で関数またはプログラムを作成します。

  • 入力として[x,y]座標のリストを取ります
  • 入力として[x,y]座標のそれぞれの質量のリストを取ります
  • 計算された重心をの形式で出力します[xBar,yBar]

注意:

  • 配列が使用されている限り、入力は任意の形式で取得できます。

重心は、次の式で計算できます。 重心計算

平易な英語で...

  • を見つけるにはxBar、各質量にそれぞれのx座標を乗算し、結果のリストを合計し、すべての質量の合計で除算します。
  • を見つけるにはyBar、各質量にそれぞれのy座標を乗算し、結果のリストを合計して、すべての質量の合計で除算します。

簡単な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]

テストケース:

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

これはコードゴルフなので、バイト数が最小になります。


これは単なる「ベクトルの加重平均の計算」であるため、これまでに行ったことがない場合は非常に驚くでしょう。(現時点では、私は何も見つかりません。)
マーティンエンダー

@MartinBüttner私も見たが、見つからなかった。これがだまされている場合は、お気軽に閉じてください。
ミスターパブリック

入力は他の順序で取得できますか?または次の形式:[x,y,m],[x,y,m]...
FryAmTheEggman

有効な入力用に編集された@FryAmTheEggman質問。
パブリック氏

@MrPublic:[(x1,y1,m1), (x2,y2,m2)]タプルのリストなどはどうですか?または、引数がタプル、リスト、配列のどれであるかは問題ではありませんか?3つのリスト/配列はどうですか?
ゼータ

回答:


21

MATL6 5バイト

ys/Y*

入力形式は、質量を含む行ベクトル、次に座標(スペースまたはコンマはオプション)を含む2列の行列です。

  • 最初の例:

    [2, 6, 2, 10]
    [0,2; 3,4; 0,1; 1,1]
    
  • 2番目の例:

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

オンラインでお試しください!

説明

ましょうm質量のベクトル(第一の入力)と表すc座標の行列(第2入力)。

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

yとても便利です!! +1
デビッド

@Davidうん!暗黙的な入力と組み合わせると、この場合は多くのことが行われます:-)
ルイスメンドー

7

Mathematica、10バイト

#.#2/Tr@#&

例:

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

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

1
私は使用しDotたことがない。しかし、上記の使用法を見た後!
DavidC

7

Mathcad、19「バイト」

enter image description here

  • データ入力にMathcadのテーブルを使用
  • Mathcadの組み込みベクトルスカラー積を使用して、軸の縦座標と質量を乗算します
  • Mathcadの組み込みの合計演算子を使用して、総質量を計算します

Mathcadは2D「ホワイトボード」と特別な演算子(加算演算子、整数演算子など)を使用し、XML形式で保存するため、実際のワークシートには数百(またはそれ以上)の文字が含まれる場合があります。コードゴルフの目的で、Mathcadの「バイトカウント」を、ユーザーがワークシートを作成するために入力する必要のある文字または演算子の数とみなしました。

チャレンジの最初の(プログラム)バージョンはこの定義を使用して19「バイト」かかり、関数バージョンは41「バイト」かかります。


3
ここで初めてMatcadソリューションを見たことがあります。非常に素晴らしい。+1。
rayryeng-モニカの復活

ありがとう、rayryeng。Mathcadには基本的な文字列関数のみがあり、人間が読めるテキストのみのソースコードがないため、「コース」の「穴」のいくつかを行うのが少し難しいためでしょう。
スチュアートブラフ

6

MATLAB /オクターブ、18 16バイト

2バイトを削除してくれたユーザービーカーとDon Muesliに感謝します!

座標がN x 2行列にxあり、最初の列がX座標で、2番目の列がY座標であり、質量が1 x N行列y(または行ベクトル)にあるとします。

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

このコードの説明は非常に単純です。これは、2つの入力xとを受け取る匿名関数ですy。行列とベクトルの乗算を使用して、線形代数アプローチで加重合計(各座標の分子表現)を実行します。y質量のベクトルを取得し、これにxマトリックスとベクトルの乗算により座標のマトリックスを乗算することにより、両方の座標の加重和を個別に計算し、これらの各座標を質量の和で除算することにより、各座標の1 x 2行ベクトルとして返される質量。

実行例

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

オンラインでお試しください!

https://ideone.com/BzbQ3e


1
を削除し;'入力形式(x行ベクトルとして)を適切に選択することによっても
ルイスメンドー

@DonMuesli感謝:) 2でバイト数を削減
rayryeng -復活モニカ

6

ゼリー、6バイト

S÷@×"S

または

÷S$×"S

入力は、2つのコマンドライン引数を介して行われます。最初に質量、次に座標を指定します。

オンラインでお試しください!

説明

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

または

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

6

ジュリア、25 17バイト

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

/コールのように:明白なアプローチを逃しましたf([3 1;0 0;1 4], [2 4 1])


5

CJam、14バイト

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

を持つ名前のない関数は、スタック上の座標ペアのリストと質量のリストを(この順序で)期待し、その場所に重心を残します。

ここでテストしてください。

説明

_    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

真剣に、16バイト

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

入力を受け取ります [x-coords]\n[y-coords]\n[masses]、出力をxbar\nybar

オンラインでお試しください!

説明:

╩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バイト

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

これは、f次のように使用されるバイナリ関数を定義します。

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

両方のテストケースに合格することを確認してください。

説明

Haskellは多次元リストの処理にはあまり適していないため、ここでいくつかのフープを見ていきます。最初の行は、の短いエイリアスを定義し、zipWith2回必要です。基本的に、f重みのリストを取る関数であるaと生成しf a、位置のリストを受け取り、質量中心を生成する機能。 f aは3つの機能の組み合わせです。

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バイト

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

(x、y、mass)「トリプル」の配列を受け入れ、「タプル」を返します。


括弧は[x,y,m]必要ですか?iirc、矢印関数への入力引数が1つしかない場合は必要ありません。
パトリックロバーツ

@PatrickRobertsはい、それらはすべての場合に必要です。ただし、厳密に1つの標準的な引数のうちの1つだけです。
ニール

3

R、32 25バイト

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

行列代数に切り替えて-7バイトを編集します(@ Sp3000 Juliaの回答に感謝)

配列(2列、x、yの行列)を座標とm重みのベクトルとして渡し、必要な座標を持つ配列を返します


2

PHP、142バイト

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)];}
分解図
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) ];
}
必要な入力
Array[Array]: [ [ mass1, mass2, ... ],
                [ xpos1, xpos2, ... ],
                [ ypos1, ypos2, ... ] ]
戻る

Array: [ xbar, ybar ]


このp()関数は、各[m]値に対応する[x]or [y]値を乗算する基本的なマップです。c()機能が取り込んでArray[Array]、プレゼントarray_sumarray_mapスペースのための機能は、その後、計算Σmx/ΣmΣmy/Σm

計算自体をスペース用の関数に変換できる可能性があります。


2

Mathcad、8「バイト」

前回の回答で私が考えていなかったことがわかりません。行列乗算を適切に使用するより短い方法を次に示します。変数pにはデータが含まれています。変数カウントを合計に設定する場合、さらに2バイトを追加します(入力テーブルの作成= 1バイト、変数名= 1バイト)。

ここに画像の説明を入力してください


1

Python 3、63バイト

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

リストのベクトル操作は長いです:/

これは匿名のラムダ関数です-名前を付けてのように呼び出します f([[0,2],[3,4],[0,1],[1,1]],[2,6,2,10])


1

Python 3、95 90 88バイト

溶液

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

結果

>>> 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バイトを節約したおかげで


楽しみのための再帰的ソリューション(95バイト)

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]

結果

>>> 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
*([c]+[m])短縮できると思います*[c,m]
ズガルブ

0

公理、158バイト

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

ウンゴルフそれ

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

結果

(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

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.