Bóng bi-a va chạm


24

Với các vị trí và vận tốc 2 chiều của một cặp bóng bi-a ngay trước khi va chạm, hãy tính vận tốc của chúng sau một va chạm hoàn toàn đàn hồi . Các quả bóng được coi là hình cầu lý tưởng (hoặc tương đương: hình tròn) có cùng bán kính, cùng khối lượng, mật độ đồng đều và không có ma sát.

Đầu vào bao gồm 8 số: p0x,p0y,v0x,v0y,p1x,p1y,v1x,v1ytrong đó p0x,p0ylà tâm của quả bóng thứ nhất, v0x,v0yvận tốc của nó và tương tự p1x,p1y,v1x,v1ycho quả bóng thứ hai. Bạn có thể chấp nhận đầu vào theo bất kỳ thứ tự nào và được cấu trúc theo bất kỳ cách thuận tiện nào, ví dụ như mảng 2x2x2 hoặc có thể là mảng 2x2 cho pvà hai mảng có độ dài 2 cho v0v1. Cũng tốt để lấy số phức (nếu ngôn ngữ của bạn hỗ trợ chúng) thay vì cặp xy. Tuy nhiên, bạn không nên lấy đầu vào trong một hệ tọa độ khác ngoài Cartesian, tức là cực không được phép.

Lưu ý rằng bán kính của một quả bóng bi-a là một nửa khoảng cách giữa p0x,p0yp1x,p1yvì vậy nó không được đưa ra như một phần rõ ràng của đầu vào.

Viết chương trình hoặc hàm xuất hoặc trả về 4 số trong bất kỳ biểu diễn Cartesian thuận tiện nào: các giá trị sau va chạm của v0x,v0y,v1x,v1y.

sơ đồ va chạm

Một thuật toán có thể là:

  • tìm dòng bình thường đi qua cả hai trung tâm

  • tìm đường tiếp tuyến đi qua trung điểm giữa hai tâm và vuông góc với đường bình thường

  • thay đổi hệ tọa độ và phá vỡ v0x,v0yv1x,v1ythành các thành phần tiếp tuyến và bình thường của chúng v0t,v0nv1t,v1n

  • trao đổi các thành phần bình thường của v0v1, bảo quản các thành phần tiếp tuyến của chúng

  • thay đổi trở lại hệ tọa độ ban đầu

Các xét nghiệm (kết quả được làm tròn đến 5 chữ số thập phân):

   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]

Chiến thắng ngắn nhất. Không sơ hở.


cảm ơn @Anush đã giúp sửa màu nền của sơ đồ

Câu trả lời:


16

Python 3 , 67 66 byte, 53 byte

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

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

-1 byte nhờ @ngn

-13 byte nhờ @Neil

Hàm fnày lấy bốn số phức làm đầu vào và trả về hai số phức. Các phiên bản không được trình bày được hiển thị dưới đây.

Bị đánh cắp

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

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

Công thức tính toán được rút ra dựa trên công thức vector 2D trên wiki . Vì m1=m2 , công thức có thể được đơn giản hóa thành

{v1=v1dvv2=v2+dv

Đặt x12=x1x2v12=v1v2 , ta có

dv=v12,x12x122x12=Re(v12x12¯)x12x12¯x12=Re(v12x12¯x12x12¯)x12=Re(v12x12)x12

Trong chương trình ungolfed, p12, v1 - v2, dtương ứng với x12 , y12 , và dv , tương ứng.


1
làm tốt! Cách tiếp cận này khác với câu trả lời perl6 của Ramillies cũng sử dụng các số phức. bạn có thể tiết kiệm một byte nếu bạn thay thế r=p-qvới p-=qvà tiếp tục sử dụng pthay vì r, giống như trong câu trả lời của Neil js
NGN

1
@ngn, nó trông khác nhau nhưng nó giống nhau, như Joel ghi chú chính xác. Tôi đã viết công thức dưới dạng tốt cho việc chơi gôn Perl 6 và Joel có lẽ đã sử dụng một công thức tốt hơn cho Python. Dù sao, tôi đã không nghĩ rằng bất kỳ ai khác sẽ đưa ra giải pháp bằng cách sử dụng các số phức một cách độc lập. Làm tốt lắm!
Ramillies

3
Rất tuyệt nhưng nếu bạn sử dụng thuật toán trong câu hỏi thì sẽ chỉ mất 53 byte ...
Neil

1
@Neil Cảm ơn gợi ý của bạn. Việc tính toán được đơn giản hóa rất nhiều bây giờ.
Joel

3
Tôi thực sự thích tất cả các giải pháp tuyệt vời của bạn và giải thích chi tiết!
xnor

11

JavaScript (Node.js) , 90 88 byte

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

Hãy thử trực tuyến! Liên kết bao gồm bộ kiểm tra. Giải thích: q,rđược định nghĩa lại là vectơ khác nhau giữa các tâm và ulà bình phương chiều dài của nó. vlà sự khác biệt trong các sản phẩm chấm của o,ps,tvới q,r, do đó, v/uhệ số tỷ lệ cho q,rđó cung cấp lượng vận tốc được truyền từ o,pđến s,t. Chỉnh sửa: Đã lưu 2 byte nhờ @Arnauld.


tôi không mong đợi ai đó sẽ đơn giản hóa thuật toán nhanh đến vậy, hoàn thành tốt! đây là một hình dung về giải pháp của bạn (với sự cải tiến của Arnauld)
ngn

@ngn Liên kết sai?
Neil

Nhật ký đường ống của @Neil gitlab nói rằng nó nên ở đó. ctrl + f5? mũi tên điều khiển quả bóng màu đỏ. sự thay đổi tăng tốc. thử nghiệm trong firefox và crom. cảnh báo: âm thanh.
ngn

@ngn À, làm việc ngay, cảm ơn! (Tôi đã nhận được 404 trước đó. Ngoài ra, tôi đang sử dụng tab riêng tư, do đó tôi không có âm thanh theo mặc định, mặc dù tôi không thấy nó xâm nhập. Và tôi vô dụng tại Asteroid, nếu không tôi sẽ yêu cầu "bắn "chìa khóa ...)
Neil

8

Perl 6 ,75 64 63 61 byte

11 byte được lưu bằng cách chuyển từ mapsang for, phân phối với nhu cầu đặt mọi thứ vào các biến trung gian mapđể xem.

Lưu 1 byte bằng cách thay đổi ($^a-$^c)².&{$_/abs}thành ($^a-$^c).&{$_/.conj}.

Lưu 2 byte nhờ @nwellnhof.

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

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


Giải trình

Khi bài viết gốc nói rằng đầu vào có thể là số phức, quá khó để cưỡng lại ... Vì vậy, điều này cần 4 số phức (vị trí 1, vận tốc 1, vị trí 2, vận tốc 2) và trả về vận tốc là số phức.

d=p1p0

v0/dv1/dd

v0=d(v1d+iv0d),v1=d(v0d+iv1d)
v0=d(v1d+iv0d)=d[12(v1d+v1d)+12(v0dv0d)]= =d2(v0+v1dv0v1d)=12(v0+v1dd(v0v1)).
The result for v1 can be obtained just by switching v0v1. All that does is changing a sign:
v1=12[v0+v1+dd(v0v1)].

And that's it. All the program does is just this calculation, golfed a bit.


very cool!­­­­­
ngn

I don't know much about Perl, but I think you could merge the two conjugate computations into one to save some bytes.
Joel

1
@Joel — Sadly, I'm pretty sure I can't. The first conjugate is acting on ($^a-$^c) (and only inside a lambda that normalizes this number), the second acts on ($b-$d). So they can't really be reconciled. I could make a function that would just call .conj, but that would only add bytes (because I heavily use the $_ variable, which has the nice property that you can call methods on it without specifying it: .conj instead of $_.conj).
Ramillies

@Ramillies Thanks for the explanation.
Joel

How is the δ's magnitude relevant? You're just dividing by δ, switching the real components, and then multiplying by δ again.
Neil

3

Jelly, 16 bytes

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

Try it online!

A dyadic link taking as its left argument a list of the initial positions [[p0x, p0y], [p1x, p1y]] and its right argument the initial velocities [[v0x, v0y], [v1x, v2y]]. Returns a list of the final velocities [[v0x', v0y'], [v1x', v2y']]

Based on the algorithm used by @Neil’s JavaScript answer so be sure to upvote that one too!


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

Try it online!

Basically a port of @Neil's JavaScript answer, but then @ceilingcat shaved off 8 bytes by cleverly reusing m and n to store temporaries.




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.