Bilardo topları çarpışma


24

Bir çift bilardo topunun 2 boyutlu pozisyonları ve hızları, çarpmadan hemen önce, elastik bir çarpışmadan sonra hızlarını hesaplar . Bilyaların, aynı yarıçap, aynı kütle, homojen yoğunluk ve sürtünme olmadan ideal küreler (veya eşdeğeri: daireler) olduğu varsayılır.

: Girdi 8 sayıdan oluşur ilk topu, merkezidir benzer onun hızına ve ikinci topu için. Sen herhangi bir sırada girdi kabul eder ve bir 2x2x2 dizisi, ya da belki bir 2x2 dizisi gibi mesela, herhangi uygun bir şekilde yapılandırılmış olabilir ve iki uzunluk-2 diziler ve . Ayrıca, xy çiftleri yerine (eğer diliniz destekliyorsa) karmaşık sayılar almanız iyi olur. Bununla birlikte, kartezyen dışındaki bir koordinat sistemine giriş yapmamalısınız, yani kutuplara izin verilmez.p0x,p0y,v0x,v0y,p1x,p1y,v1x,v1yp0x,p0yv0x,v0yp1x,p1y,v1x,v1ypv0v1

Bilardo topunun yarıçapının aradaki mesafenin yarısı olduğunu p0x,p0yve p1x,p1ybu nedenle girişin açık bir parçası olarak verilmediğini unutmayın.

Herhangi bir uygun Kartezyen gösterimi için 4 sayı veren veya döndüren bir program veya işlev yazın: çarpışma sonrası değerleri v0x,v0y,v1x,v1y.

çarpışma diyagramı

Olası bir algoritma:

  • her iki merkezden geçen normal çizgiyi bulmak

  • iki merkez arasındaki orta noktadan geçen ve normal çizgiye dik olan teğet çizgiyi bulun

  • koordinat sistemi ve yıkmak değişir v0x,v0yve v1x,v1ybunların teğet ve normal bileşenlerine v0t,v0nvev1t,v1n

  • teğet bileşenlerini normal bileşenleriyle değiştirerek v0ve bunları v1koruyarak

  • orijinal koordinat sistemine geri dön

Testler (5 ondalık basamağa yuvarlanmış sonuçlar):

   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]

En kısa kazançlar. Boşluk yok.


Diyagramın arka plan renginin düzeltilmesine yardımcı olduğunuz için teşekkürler

Yanıtlar:


16

Python 3 , 67 66 bayt, 53 bayt

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

Çevrimiçi deneyin!

@Ngn sayesinde -1 bayt

@Neil sayesinde -13 bayt

Bu işlev fgiriş olarak dört karmaşık sayıyı alır ve iki karmaşık sayıyı döndürür. Ungolfed versiyonu aşağıda gösterilmiştir.

Ungolfed

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

Çevrimiçi deneyin!

Hesaplama formülü, wiki'deki 2B vektör formülüne dayanarak türetilir . Yana m1=m2 , formül basitleştirilebilir

{v1=v1dvv2=v2+dv

Let x12=x1x2 ve v12=v1v2 , elimizdeki

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

Ungolfed programında, p12, v1 - v2, dkarşılık gelecek şekilde x12 , y12 ve dv sırasıyla.


1
aferin! Bu yaklaşım, Ramillies'in karmaşık sayıları da kullanan perl6 cevabından farklı görünüyor . Neil'in js cevabındaki gibi - yerine ve r=p-qonunla p-=qdaha ileride kullanırsanız bir bayt kaydedebilirsinizpr
ngn

1
@ngn farklı görünüyor, fakat Joel'in dediği gibi aynı. Formülü Perl 6 golf için iyi bir formda yazdım ve Joel muhtemelen Python için daha iyisini kullandı. Neyse, başkasının, karmaşık sayıları bağımsız olarak kullanarak bir çözüm bulacağını düşünmemiştim. Aferin!
Ramillies

3
Güzel ama eğer soruna algoritmayı kullanırsanız sadece 53 bayt alırdı ...
Neil

1
@Neil Püf noktaları için teşekkürler. Hesaplama şimdi büyük ölçüde basitleştirildi.
Joel,

3
Tüm harika çözümlerinizi ve ayrıntılı açıklamalarınızı gerçekten beğeniyorum!
xnor

11

JavaScript (Node.js) , 90 88 bayt

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

Çevrimiçi deneyin! Bağlantı test paketi içerir. Açıklama: q,rmerkezler arasındaki fark vektörü olarak yeniden düzenlenir uve uzunluğunun karesidir.vdot ürünleri farkıdır o,pve s,tile q,r, yani v/uiçin ölçek faktörü olup q,rbu transfer hızının miktarını verir o,piçin s,t. Düzenleme: @Arnauld sayesinde 2 bayt kaydedildi.


Birisinin algoritmayı bu kadar çabuk kolaylaştıracağını düşünmemiştim, aferin! İşte çözümünüzün bir görselleştirmesi (
Arnauld'un

@ngn Yanlış bağlantı?
Neil

@Neil gitlab'ın boru hattı kütüğü orada olması gerektiğini söylüyor. ctrl + f5? oklar kırmızı topu kontrol eder. vardiya hızlandırır. firefox ve kromda test edilmiştir. uyarı: ses
ngn

@ Ah Ah, şimdi çalışıyoruz, teşekkürler! (Daha önce bir 404'üm var. Ayrıca, özel bir sekme kullanıyordum, bu yüzden varsayılan olarak sesim yoktu, ancak müdahaleci bulmamıştım. Asteroids'de işe yaramazım, aksi halde "çekim" "anahtar ...)
Neil

8

Perl 6 ,75 64 63 61 bayt

11 bayt geçiş yaparak kurtardı mapiçin foriçin ara değişkenlere şeyler koymak için gerek duyulmaz, mapgörmek.

1 byte değiştirerek kurtardı ($^a-$^c)².&{$_/abs}için ($^a-$^c).&{$_/.conj}.

@Nwellnhof sayesinde 2 bayt kaydedildi.

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

Çevrimiçi deneyin!


açıklama

Orijinal gönderi, girişin karmaşık sayılar olabileceğini söylediğinde, dayanmak çok zordu ... Yani bu 4 karmaşık sayıları alır (konum 1, hız 1, konum 2, hız 2) ve hızları karmaşık sayılar olarak döndürür.

d=p1p0

v0/dv1/dd

v0'=d(v1d+benv0d),v1'=d(v0d+benv1d)
v0'=d(v1d+benv0d)=d[12(v1d+v1d)+12(v0d-v0d)]= =d2(v0+v1d-v0-v1d)=12(v0+v1-dd(v0-v1)).
v1'v0v1
v1'=12[v0+v1+dd(v0-v1)].

Ve bu kadar. Programın yaptığı sadece bu hesaplama, biraz golf oynadı.


çok havalı!
ngn

Perl hakkında fazla bir şey bilmiyorum ama sanırım iki eşlenik hesaplamayı bir bayttan tasarruf etmek için birleştirebilirsiniz.
Joel,

1
@Joel - Ne yazık ki yapamayacağımdan eminim. İlk eşlenik hareket eder ($^a-$^c)(ve sadece bu sayıyı normalleştiren bir lambda içinde), ikincisi hareket eder ($b-$d). Yani gerçekten uzlaştırılamıyorlar. Sadece çağıracak bir işlev yapabilirim .conj, ama bu sadece bayt ekler (çünkü $_onu belirtmeden yöntemleri çağırabileceğiniz nice özelliğine sahip olan değişkeni yoğun bir şekilde kullanırım : .conjyerine $_.conj).
Ramillies

@Ramillies Açıklama için teşekkürler.
Joel,

Magn'nın büyüklüğü nasıldır? Sadece δ ile bölüyorsunuz, gerçek bileşenleri değiştiriyorsunuz ve sonra tekrar δ ile çarpıyorsunuz.
Neil

3

Jöle , 16 bayt

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

Çevrimiçi deneyin!

Sol argümanı olarak başlangıç ​​konumlarının bir listesini alan [[p0x, p0y], [p1x, p1y]]ve sağ argümanı başlangıç ​​hızlarını belirleyen ikili bir bağlantı [[v0x, v0y], [v1x, v2y]]. Son hızların bir listesini döndürür[[v0x', v0y'], [v1x', v2y']]

@ Neil'in JavaScript cevabının kullandığı algoritmaya bağlı olarak, bunu da mutlaka oyladığınızdan emin olun!


3

C (gcc) , 140 132 bayt

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

Çevrimiçi deneyin!

Temel olarak @ Neil'in JavaScript cevabının bir limanı, ancak daha sonra @ceilingcat akıllıca yeniden kullanarak mve ngeçici olarak depolamak için 8 byte'ı kesti .




Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.