ศูนย์กลางของมวลจากรายการพิกัดและมวลของพวกมัน


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]

นี่คือโค้ดกอล์ฟดังนั้นจำนวนไบต์น้อยที่สุดจึงจะชนะ!


เนื่องจากนี่เป็นเพียง "คำนวณค่าเฉลี่ยถ่วงน้ำหนักของเวกเตอร์" ฉันค่อนข้างประหลาดใจถ้าเราไม่ได้ทำมาก่อน (ในขณะนี้ฉันไม่พบอะไรเลย)
Martin Ender

@ MartinBüttnerฉันดูดีและไม่สามารถหาได้ หากนี่เป็นคนล่อลวงอย่าลังเลที่จะปิด
นายสาธารณะ

สามารถนำเข้าตามลำดับอื่น ๆ ได้ไหม? หรือในรูปแบบ: [x,y,m],[x,y,m]...?
FryAmTheEggman

@FryAmTheEggman คำถามถูกแก้ไขสำหรับอินพุตที่ถูกต้อง
นายสาธารณะ

@MrPublic: [(x1,y1,m1), (x2,y2,m2)]แล้วเช่นรายการของสิ่งอันดับ? หรือไม่สำคัญว่าข้อโต้แย้งนั้นจะเป็นสิ่งอันดับรายการหรืออาร์เรย์หรือไม่ มีสามรายการ / อะเรย์
Zeta

คำตอบ:


21

MATL , 6 5 ไบต์

ys/Y*

รูปแบบอินพุตเป็นเวกเตอร์แถวที่มีมวลจากนั้นเมทริกซ์สองคอลัมน์พร้อมพิกัด (ซึ่งช่องว่างหรือเครื่องหมายจุลภาคเป็นตัวเลือก)

  • ตัวอย่างแรก:

    [2, 6, 2, 10]
    [0,2; 3,4; 0,1; 1,1]
    
  • ตัวอย่างที่สอง:

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

ลองออนไลน์!

คำอธิบาย

อนุญาตmแสดงว่าเวกเตอร์ของมวล (อินพุตแรก) และcเมทริกซ์ของพิกัด (อินพุตที่สอง)

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

@ David Yeah! เมื่อรวมกับอินพุตโดยนัยมันทำสิ่งต่าง ๆ มากมายในกรณีนี้ :-)
Luis Mendo

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 "ไบต์"

ป้อนคำอธิบายรูปภาพที่นี่

  • ใช้ตาราง Mathcad สำหรับการป้อนข้อมูล
  • ใช้ผลิตภัณฑ์สเกลาร์เวคเตอร์ในตัวของ Mathcad สำหรับการคูณแกนและมวล
  • ใช้ตัวดำเนินการรวมในตัวของ Mathcad สำหรับมวลรวมทั้งหมด

เนื่องจาก Mathcad ใช้ 2D "ไวท์บอร์ด" และตัวดำเนินการพิเศษ (เช่นตัวดำเนินการ summation ตัวดำเนินการรวม) และบันทึกในรูปแบบ XML แผ่นงานจริงอาจมีอักขระหลายร้อย (หรือมากกว่า) สำหรับจุดประสงค์ของ Code Golf ฉันได้นำ Mathcad "byte count" เป็นจำนวนอักขระหรือตัวดำเนินการที่ผู้ใช้ต้องป้อนเพื่อสร้างแผ่นงาน

เวอร์ชันแรกของโปรแกรม (ความท้าทาย) ใช้เวลา 19 "ไบต์" โดยใช้คำจำกัดความนี้และรุ่นฟังก์ชั่นใช้เวลา 41 "ไบต์"


3
ครั้งแรกที่ฉันเคยเห็นโซลูชัน Matcad ที่นี่ ดีมาก. +1
rayryeng - Reinstate Monica

ขอขอบคุณ rayryeng อาจเป็นเพราะมันเป็นเรื่องท้าทายที่จะทำ "หลุม" บางอย่างใน "หลักสูตร" เนื่องจาก Mathcad มีฟังก์ชันสตริงพื้นฐานเท่านั้นและไม่มีซอร์สโค้ดแบบข้อความที่มนุษย์อ่านได้เท่านั้น
Stuart Bruff

6

MATLAB / Octave, 18 16 ไบต์

ขอขอบคุณผู้ใช้บีกเกอร์และ Don Muesli สำหรับการลบ 2 ไบต์!

ระบุว่าพิกัดอยู่ในN x 2เมทริกซ์xโดยที่คอลัมน์แรกคือพิกัด X และคอลัมน์ที่สองคือพิกัด Y และมวลอยู่ใน1 x Nเมทริกซ์y(หรือเวกเตอร์แถว):

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

คำอธิบายของรหัสนี้ค่อนข้างตรงไปตรงมา นี้เป็นฟังก์ชั่นที่ไม่ระบุชื่อที่จะใช้ในสองปัจจัยการผลิตและ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เป็นเวกเตอร์แถว) ได้อย่างถูกต้อง
Luis Mendo

@ DonMuesli ขอบคุณ :) ลดจำนวน byte ลง 2
rayryeng - Reinstate Monica

6

เยลลี่ 6 ไบต์

S÷@×"S

หรือ

÷S$×"S

อินพุตคือผ่านอาร์กิวเมนต์บรรทัดรับคำสั่งสองรายการมวลก่อนพิกัดที่สอง

ลองออนไลน์!

คำอธิบาย

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

Julia, 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 ไม่เหมาะสำหรับการประมวลผลรายการหลายมิติดังนั้นฉันจึงกระโดดผ่านห่วงที่นี่ บรรทัดแรกกำหนดนามแฝงสั้น ๆzipWithซึ่งเราต้องการสองครั้ง โดยพื้นฐานแล้วfเป็นฟังก์ชั่นที่รับรายการของน้ำหนักaและสร้างf aเป็นฟังก์ชันที่รับรายการของตำแหน่งและสร้างศูนย์กลางของมวล f aเป็นองค์ประกอบของสามฟังก์ชั่น:

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, มวล) "triples" และส่งคืน "tuple"


วงเล็บ[x,y,m]จำเป็นหรือไม่? iirc ไม่จำเป็นถ้ามันมีอาร์กิวเมนต์อินพุตเพียงอันเดียวสำหรับฟังก์ชันลูกศร
Patrick Roberts

@PatrickRoberts ใช่พวกเขามีความจำเป็นในทุกกรณียกเว้นหนึ่งเรื่องเล็กน้อยที่เป็นหนึ่งในอาร์กิวเมนต์มาตรฐาน
Neil

3

R, 32 25 ไบต์

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

แก้ไข -7 ไบต์โดยเปลี่ยนเป็นพีชคณิตเมทริกซ์ (ขอบคุณ @ Sp3000 Julia answer)

ผ่านอาร์เรย์ (เมทริกซ์ที่มี 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]หรือ[y]ค่า c()ฟังก์ชั่นใช้เวลาในArray[Array]นำเสนอarray_sumและarray_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)]

การดำเนินการของ Vector ในรายการมีความยาว: /

นี่คือฟังก์ชั่นแลมบ์ดานิรนาม - ตั้งชื่อและการโทร 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]
Zgarb

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.