การปะทะกันของลูกบิลเลียด


24

ได้รับตำแหน่ง 2 มิติและความเร็วของคู่ของลูกบิลเลียดขวาก่อนส่งผลกระทบต่อการคำนวณความเร็วของพวกเขาหลังจากที่ดีที่สุดที่ยืดหยุ่นขัดแย้ง ลูกบอลถูกสันนิษฐานว่าเป็นทรงกลมในอุดมคติ (หรือเทียบเท่า: วงกลม) ที่มีรัศมีเดียวกันมวลเดียวกันความหนาแน่นสม่ำเสมอและไม่มีแรงเสียดทาน

ข้อมูลที่ป้อนประกอบด้วยตัวเลข 8 ตัวp0x,p0y,v0x,v0y,p1x,p1y,v1x,v1yโดยที่p0x,p0yจุดศูนย์กลางของลูกบอลลูกแรกv0x,v0yความเร็วของมันและคล้ายp1x,p1y,v1x,v1yกับลูกที่สอง คุณสามารถยอมรับการป้อนข้อมูลในลำดับใด ๆ และโครงสร้างในวิธีที่สะดวกใด ๆ เช่นเป็น array 2x2x2 หรืออาจจะอาร์เรย์ 2x2 สำหรับpสองยาว 2 อาร์เรย์สำหรับและv0 v1การใช้ตัวเลขที่ซับซ้อน (หากภาษาของคุณรองรับพวกเขา) แทนที่จะเป็นคู่ xy อย่างไรก็ตามคุณไม่ควรป้อนข้อมูลในระบบพิกัดอื่นนอกเหนือจากคาร์ทีเซียนเช่นไม่อนุญาตให้ใช้ขั้ว

โปรดทราบว่ารัศมีของลูกบิลเลียดนั้นอยู่ห่างจากครึ่งหนึ่งของระยะระหว่างp0x,p0yและp1x,p1yดังนั้นจึงไม่ได้ถูกกำหนดให้เป็นส่วนหนึ่งของอินพุตอย่างชัดเจน

เขียนโปรแกรมหรือฟังก์ชั่นที่ผลหรือผลตอบแทนที่ 4 ตัวเลขในการเป็นตัวแทนคาร์ทีเซียนที่สะดวก: v0x,v0y,v1x,v1yค่าหลังการปะทะกันของ

แผนภาพการชนกันของข้อมูล

อัลกอริทึมที่เป็นไปได้คือ:

  • ค้นหาบรรทัดปกติที่ผ่านทั้งสองศูนย์

  • ค้นหาเส้นสัมผัสที่ผ่านจุดกึ่งกลางระหว่างจุดศูนย์กลางสองจุดและตั้งฉากกับเส้นปกติ

  • เปลี่ยนระบบพิกัดและแยกย่อยv0x,v0yและv1x,v1yเป็นองค์ประกอบวงv0t,v0nและปกติv1t,v1n

  • สลับส่วนประกอบปกติของv0และv1รักษาองค์ประกอบวงใน

  • เปลี่ยนกลับเป็นระบบพิกัดเดิม

การทดสอบ (ผลลัพธ์ถูกปัดเศษเป็นทศนิยม 5 ตำแหน่ง):

   p0x   p0y   v0x   v0y   p1x   p1y   v1x   v1y ->      v0x'       v0y'       v1x'       v1y'
[-34.5,-81.8, 34.7,-76.1, 96.2,-25.2, 59.2,-93.3] [  49.05873, -69.88191,  44.84127, -99.51809]
[ 36.9, 77.7,-13.6,-80.8, -7.4, 34.4, 15.1,-71.8] [   5.57641, -62.05647,  -4.07641, -90.54353]
[-51.0, 17.6, 46.1,-80.1, 68.6, 54.0,-35.1,-73.9] [ -26.48927,-102.19239,  37.48927, -51.80761]
[-21.1,-52.6,-77.7, 91.5, 46.0, 94.1, 83.8, 93.7] [ -48.92598, 154.40834,  55.02598,  30.79166]
[ 91.3, -5.3, 72.6, 89.0, 97.8, 50.5, 36.2, 85.7] [  71.73343,  81.56080,  37.06657,  93.13920]
[-79.9, 54.9, 92.5,-40.7,-20.8,-46.9,-16.4, -0.9] [  47.76727,  36.35232,  28.33273, -77.95232]
[ 29.1, 80.7, 76.9,-85.1,-29.3,-49.5,-29.0,-13.0] [  86.08581, -64.62067, -38.18581, -33.47933]
[ 97.7,-89.0, 72.5, 12.4, 77.8,-88.2, 31.5,-34.0] [  33.42847,  13.97071,  70.57153, -35.57071]
[-22.2, 22.6,-61.3, 87.1, 67.0, 57.6,-15.3,-23.1] [ -58.90816,  88.03850, -17.69184, -24.03850]
[-95.4, 15.0,  5.3, 39.5,-54.7,-28.5, -0.7,  0.8] [  21.80656,  21.85786, -17.20656,  18.44214]
[ 84.0,-26.8,-98.6,-85.6,-90.1, 30.9,-48.1, 37.2] [ -89.76828, -88.52700, -56.93172,  40.12700]
[ 57.8, 90.4, 53.2,-74.1, 76.4,-94.4,-68.1,-69.3] [  51.50525, -57.26181, -66.40525, -86.13819]
[ 92.9, 69.8,-31.3, 72.6,-49.1,-78.8,-62.3,-81.6] [-123.11680, -23.48435,  29.51680,  14.48435]
[-10.3,-84.5,-93.5,-95.6, 35.0, 22.6, 44.8, 75.5] [ -11.12485,  99.15449, -37.57515,-119.25449]
[ -3.9, 55.8,-83.3,  9.1, -2.7,-95.6, 37.7,-47.8] [ -82.84144, -48.75541,  37.24144,  10.05541]
[-76.5,-88.4,-76.7,-49.9, 84.5, 38.0,  4.2, 18.4] [   6.52461,  15.43907, -79.02461, -46.93907]
[ 64.2,-19.3, 67.2, 45.4,-27.1,-28.7, 64.7, -4.3] [  59.66292,  44.62400,  72.23708,  -3.52400]
[  9.8, 70.7,-66.2, 63.0,-58.7, 59.5, 83.7,-10.6] [  68.07646,  84.95469, -50.57646, -32.55469]
[ 62.9, 46.4, 85.0, 87.4, 36.3,-29.0,-63.0,-56.3] [  23.53487, -86.82822,  -1.53487, 117.92822]
[ -5.5, 35.6, 17.6,-54.3, -2.2, 66.8,-15.2, 11.8] [  24.15112,   7.63786, -21.75112, -50.13786]

ชนะสั้นที่สุด ไม่มีช่องโหว่


ขอบคุณ @Anush ที่ช่วยแก้ไขสีพื้นหลังของไดอะแกรม

คำตอบ:


16

Python 3 , 67 66ไบต์, 53 ไบต์

def f(p,v,q,w):p-=q;d=((v-w)/p).real*p;return v-d,w+d

ลองออนไลน์!

-1 ไบต์ขอบคุณ @ngn

-13 ไบต์ขอบคุณ @Neil

ฟังก์ชั่นนี้fใช้จำนวนเชิงซ้อนสี่ตัวเป็นอินพุตและส่งกลับตัวเลขสองจำนวน เวอร์ชั่นที่ไม่ได้แสดงจะแสดงดังต่อไปนี้

Ungolfed

def elastic_collision_complex(p1, v1, p2, v2):
    p12 = p1 - p2
    d = ((v1 - v2) / p12).real * p12
    return v1 - d, v2 + d

ลองออนไลน์!

สูตรการคำนวณที่ได้มาขึ้นอยู่กับสูตร 2D เวกเตอร์ในวิกิพีเดีย ตั้งแต่ม.1=ม.2สูตรสามารถทำให้ง่ายขึ้นถึง

{โวลต์1'=โวลต์1-dโวลต์โวลต์2'=โวลต์2+dโวลต์

ให้x12=x1-x2และโวลต์12=โวลต์1-โวลต์2เรามี

dโวลต์=โวลต์12,x12x122x12=Rอี(โวลต์12x12¯)x12x12¯x12=Rอี(โวลต์12x12¯x12x12¯)x12=Rอี(โวลต์12x12)x12

ในโปรแกรม ungolfed, p12, v1 - v2, dสอดคล้องกับ ,และตามลำดับx12Y12dโวลต์


1
ทำได้ดี! วิธีนี้ดูแตกต่างจากคำตอบ perl6 ของ Ramilliesซึ่งใช้ตัวเลขที่ซับซ้อนด้วย คุณสามารถบันทึกไบต์ได้ถ้าคุณแทนที่r=p-qด้วยp-=qและใช้งานต่อไปpแทนrเช่นในคำตอบ js ของ Neil
ngn

1
@ngn มันดูแตกต่าง แต่เหมือนกันกับ Joel บันทึกอย่างถูกต้อง ฉันเขียนสูตรในรูปแบบที่ดีสำหรับการเล่นกอล์ฟ Perl 6 และโจเอลก็ใช้สูตรที่ดีกว่าสำหรับ Python อย่างไรก็ตามฉันไม่คิดว่าจะมีใครแก้ปัญหาโดยใช้ตัวเลขที่ซับซ้อนได้อย่างอิสระ เยี่ยมมาก!
Ramillies

3
ดี แต่ถ้าคุณใช้อัลกอริทึมในคำถามมันจะใช้เวลา 53 ไบต์เท่านั้น ...
Neil

1
@ Neil ขอบคุณสำหรับคำแนะนำของคุณ การคำนวณง่ายขึ้นอย่างมากในขณะนี้
โจเอล

3
ฉันชอบโซลูชั่นที่ยอดเยี่ยมและคำอธิบายโดยละเอียดของคุณจริงๆ!
xnor

11

JavaScript (Node.js) , 90 88 ไบต์

(m,n,o,p,q,r,s,t,u=(q-=m)*q+(r-=n)*r,v=o*q+p*r-s*q-t*r)=>[o-(q*=v/u),p-(v*=r/u),s+q,t+v]

ลองออนไลน์! การเชื่อมโยงรวมถึงชุดทดสอบ คำอธิบาย:q,rรับการ repurposed เป็นเวกเตอร์ส่วนต่างระหว่างศูนย์และuเป็นกำลังสองของความยาว vคือความแตกต่างในผลิตภัณฑ์ดอทของo,pและs,tด้วยq,rดังนั้นv/uปัจจัยการปรับสเกลq,rที่ให้ปริมาณความเร็วที่ถ่ายโอนจากo,pไปs,tเป็น แก้ไข: บันทึก 2 ไบต์ขอบคุณ @Arnauld


ฉันไม่ได้คาดหวังว่าใครบางคนจะลดความซับซ้อนของอัลกอริทึมได้เร็วมากทำได้ดีมาก! นี่คือการสร้างภาพของโซลูชันของคุณ (พร้อมการปรับปรุงของ Arnauld)
ngn

@ngn ลิงก์ผิด
Neil

บันทึกการทำงานของท่อ @Neil gitlab บอกว่าควรจะอยู่ที่นั่น Ctrl + F5? ลูกศรควบคุมลูกบอลสีแดง เร่งความเร็ว ทดสอบใน Firefox และโครเมียม คำเตือน: เสียง
ngn

@ngn Ah ทำงานได้แล้วขอบคุณ! (ฉันได้ 404 ก่อนหน้านี้นอกจากนี้ฉันกำลังใช้แท็บส่วนตัวดังนั้นฉันจึงไม่มีเสียงเป็นค่าเริ่มต้นแม้ว่าฉันจะไม่พบว่าเป็นการรบกวนและฉันก็ไม่มีประโยชน์ที่ Asteroids มิฉะนั้นฉันจะขอให้ "ยิง" "คีย์ ... )
Neil

8

เพิร์ล 6 ,75 64 63 61 ไบต์

บันทึก 11 ไบต์โดยเปลี่ยนจากmapเป็นforจ่ายด้วยความจำเป็นที่จะต้องใส่สิ่งต่าง ๆ ลงในตัวแปรกลางสำหรับmapให้เห็น

บันทึก 1 ไบต์โดยเปลี่ยน($^a-$^c)².&{$_/abs}เป็น($^a-$^c).&{$_/.conj}ไป

บันทึก 2 ไบต์ด้วย @nwellnhof

{(.($^b+$^d,{$_/.conj}($^a-$^c)*($b-$d).conj)/2 for *-*,*+*)}

ลองออนไลน์!


คำอธิบาย

เมื่อโพสต์ต้นฉบับบอกว่าอินพุตอาจเป็นจำนวนเชิงซ้อนมันยากเกินกว่าที่จะต้านทานได้ ... ดังนั้นจึงต้องใช้ 4 จำนวนเชิงซ้อน (ตำแหน่ง 1, ความเร็ว 1, ตำแหน่ง 2, ความเร็ว 2) และส่งกลับความเร็วเป็นตัวเลขที่ซับซ้อน

d=p1p0

v0/dv1/dd

โวลต์0'=d(โวลต์1d+ผมโวลต์0d),โวลต์1'=d(โวลต์0d+ผมโวลต์1d)
โวลต์0'=d(โวลต์1d+ผมโวลต์0d)=d[12(โวลต์1d+โวลต์1d)+12(โวลต์0d-โวลต์0d)]= =d2(โวลต์0+โวลต์1d-โวลต์0-โวลต์1d)=12(โวลต์0+โวลต์1-dd(โวลต์0-โวลต์1)).
โวลต์1'โวลต์0โวลต์1
โวลต์1'=12[โวลต์0+โวลต์1+dd(โวลต์0-โวลต์1)].

และนั่นคือมัน โปรแกรมทั้งหมดเป็นเพียงการคำนวณนี้ golfed เล็กน้อย


เด็ดมาก!
ngn

ฉันไม่ค่อยรู้อะไรเกี่ยวกับ Perl แต่ฉันคิดว่าคุณสามารถรวมการคำนวณทั้งสองคอนจูเกตเข้าด้วยกันเพื่อบันทึกไบต์
โจเอล

1
@Joel - น่าเศร้าฉันค่อนข้างแน่ใจว่าฉันทำไม่ได้ ผันครั้งแรกที่ทำหน้าที่เกี่ยวกับ($^a-$^c)(และเฉพาะภายในแลมบ์ดาที่ normalizes จำนวนนี้) ($b-$d)ที่สองทำหน้าที่เกี่ยวกับ ดังนั้นพวกเขาจึงไม่สามารถคืนดีได้ ฉันสามารถสร้างฟังก์ชั่นที่เพิ่งจะเรียก.conjได้ แต่นั่นจะเพิ่มไบต์เท่านั้น (เพราะฉันใช้$_ตัวแปรมากซึ่งมีคุณสมบัติที่ดีที่คุณสามารถเรียกใช้เมธอดได้โดยไม่ต้องระบุ: .conjแทน$_.conj)
Ramillies

@Ramillies ขอบคุณสำหรับคำอธิบาย
โจเอล

ขนาดของ relevant สัมพันธ์กันอย่างไร? คุณแค่หารด้วยδสลับองค์ประกอบจริงแล้วคูณด้วยδอีกครั้ง
Neil

3

เยลลี่ขนาด 16 ไบต์

_/×ḋ÷²S¥_/ʋ¥N,$+

ลองออนไลน์!

การเชื่อมโยง dyadic การเป็นอาร์กิวเมนต์ซ้ายของรายการของตำแหน่งที่เริ่มต้นและการโต้แย้งสิทธิของความเร็วเริ่มต้น[[p0x, p0y], [p1x, p1y]] [[v0x, v0y], [v1x, v2y]]ส่งคืนรายการความเร็วสุดท้าย[[v0x', v0y'], [v1x', v2y']]

ตามอัลกอริทึมที่ตอบกลับโดยJavaScript ของ @ Neilดังนั้นอย่าลืมอัปเกรดด้วยเช่นกัน!


3

C (gcc) , 140 132 bytes

f(m,n,o,p,q,r,s,t,a)float*a,m,n,o,p,q,r,s,t;{q-=m;r-=n;m=q*q+r*r,n=o*q+p*r-s*q-t*r;q*=n/m;*a++=o-q;n*=r/m;*a++=p-n;*a++=s+q;*a=t+n;}

ลองออนไลน์!

โดยทั่วไปแล้วพอร์ตของคำตอบ JavaScript ของ @ Neil แต่จากนั้น @ceilingcat จะตัดออกไป 8 ไบต์โดยการใช้ซ้ำอย่างชาญฉลาดmและnเก็บชั่วคราว




โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.