# ビリヤードボールの衝突

24

ビリヤードボールの半径はp0x,p0yとの間の距離の半分であることに注意してください。そのp1x,p1yため、入力の明示的な部分としては与えられません。

• 両方の中心を通る法線を見つける

• 2つの中心の中間点を通り、法線に垂直な接線を見つける

• 変更は、システムを調整し、打破v0x,v0yし、v1x,v1yその接線と通常の成分へv0t,v0nv1t,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

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

@ngnのおかげで-1バイト

@Neilのおかげで-13バイト

この関数fは、4つの複素数を入力として受け取り、2つの複素数を返します。未使用のバージョンを以下に示します。

## 非ゴルフ

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

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

$\left\{\begin{array}{l}{v}_{1}^{\prime }={v}_{1}-dv\\ {v}_{2}^{\prime }={v}_{2}+dv\end{array}$

ましょう$$x12=x1−x2x12=x1−x2x_{12}=x_1-x_2$$及び$$v12=v1−v2v12=v1−v2v_{12}=v_1-v_2$$、我々が持っています、



$dv=\frac{⟨{v}_{12},{x}_{12}⟩}{‖{x}_{12}{‖}^{2}}{x}_{12}=\frac{Re\left({v}_{12}\cdot \overline{{x}_{12}}\right)}{{x}_{12}\cdot \overline{{x}_{12}}}{x}_{12}=Re\left(\frac{{v}_{12}\cdot \overline{{x}_{12}}}{{x}_{12}\cdot \overline{{x}_{12}}}\right){x}_{12}=Re\left(\frac{{v}_{12}}{{x}_{12}}\right){x}_{12}$

ungolfedプログラムにおいて、p12v1 - v2d対応する$$x12x12x_{12}$$$$y12y12y_{12}$$、及び$$dvdvdv$$はそれぞれ、。

1
よくやった！このアプローチは、複素数も使用するRamilliesのperl6の回答とは異なります。あなたが交換する場合は、バイトを救うことができるr=p-qp-=q、さらに使用pの代わりrのように、ニールのJS答え
NGN

1
@ngn、見た目は異なりますが、Joelが正しく指摘しているように同じです。Perl 6のゴルフに適した形式で式を作成しましたが、JoelはPythonに適した式を使用したと考えられます。とにかく、私は他のだれかが複素数を独立して使用する解決策を思い付くとは思わなかった。よくやった！
ラミリーズ

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は、中心間の差ベクトルとして再利用され、uその長さの2乗です。vドット積の差であるo,ps,tとは、q,rそう、v/uのスケーリングファクタであるq,rから転送速度の量与えることo,pにはs,t。編集：@Arnauldのおかげで2バイト保存されました。

NGN

@ngn間違ったリンク？
ニール

@Neil gitlabのパイプラインログには、それがあるはずだと書かれています。ctrl + f5？矢印は赤いボールを制御します。シフトが加速します。FirefoxおよびChromeでテスト済み。警告：音。
ngn

@ngnああ、今働いています、ありがとう！（前に404を取得しました。また、プライベートタブを使用していたため、デフォルトではサウンドがありませんでしたが、邪魔になりませんでした。また、Asteroidsでは役に立たないため、「シュート」を要求しました。 "キー...）
ニール

8

# Perl 6、756463 61バイト

からmapに切り替えることで11バイトが節約さforれ、map見るために中間変数に物を入れる必要がなくなります。

に変更($^a-$^c)².&{$_/abs}することで1バイト節約され($^a-$^c).&{$_/.conj}ます。

@nwellnhofのおかげで2バイト節約されました。

{(.($^b+$^d,{$_/.conj}($^a-$^c)*($b-$d).conj)/2 for *-*,*+*)} オンラインでお試しください！ # 説明 元の投稿が入力が複素数である可能性があると言ったとき、抵抗するのは難しすぎました...したがって、これは4つの複素数（位置1、速度1、位置2、速度2）を取り、速度を複素数として返します。 $$d=p1−p0d=p1−p0d = p_1 - p_0$$ $$v0/dv0/dv_0/d$$$$v1/dv1/dv_1/d$$$$ddd$$ $\begin{array}{rl}{v}_{0}^{\prime }& =d\left(\mathrm{\Re }\frac{{v}_{1}}{d}+\mathrm{i}\mathrm{\Im }\frac{{v}_{0}}{d}\right),\\ {v}_{1}^{\prime }& =d\left(\mathrm{\Re }\frac{{v}_{0}}{d}+\mathrm{i}\mathrm{\Im }\frac{{v}_{1}}{d}\right)\end{array}$ (where $$Rℜ\Re$$ = real part, $$Iℑ\Im$$ = imaginary part). Let's shuffle the first one a bit (using $$⋆⋆\star$$ for complex conjugation): $$v′0=d(Rv1d+iIv0d)=d[12(v1d+v⋆1d⋆)+12(v0d−v⋆0d⋆)]= =d2(v0+v1d−v⋆0−v⋆1d⋆)=12(v0+v1−dd⋆(v⋆0−v⋆1)).v0′=d(ℜv1d+iℑv0d)=d[12(v1d+v1⋆d⋆)+12(v0d−v0⋆d⋆)]= =d2(v0+v1d−v0⋆−v1⋆d⋆)=12(v0+v1−dd⋆(v0⋆−v1⋆)). v_0' = d \left( \Re \frac{v_1}{d} + \mathrm{i} \Im \frac{v_0}{d} \right) = d \left[ \frac 1 2 \left( \frac{v_1}{d} + \frac{v_1^\star}{d^\star} \right) + \frac 1 2 \left( \frac{v_0}{d} - \frac{v_0^\star}{d^\star} \right) \right] =\ = \frac d 2 \left( \frac{v_0 + v_1}{d} - \frac{v_0^\star - v_1^\star}{d^\star} \right) = \frac 1 2 \left( v_0 + v_1 - \frac{d}{d^\star} (v_0^\star - v_1^\star) \right).$$ The result for $$v′1v1′v_1'$$ can be obtained just by switching $$v0↔v1v0↔v1v_0 \leftrightarrow v_1$$. All that does is changing a sign: $$v′1=12[v0+v1+dd⋆(v⋆0−v⋆1)].v1′=12[v0+v1+dd⋆(v0⋆−v1⋆)]. v_1' = \frac 1 2 \left[ v_0 + v_1 + \frac{d}{d^\star} \left(v_0^\star - v_1^\star\right) \right].$$ 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.

2

# Python 2, 97 92 bytes

m,n,o,p,q,r,s,t=input()
q-=m
r-=n
a=o*q+p*r-s*q-t*r
a/=q*q+r*r
print o-a*q,p-a*r,s+a*q,t+a*r

Try it online!

Modified version of Neil's approach.

1

# C (gcc), 77 72 bytes

f(p,v,q,w,a)_Complex*a,p,v,q,w;{p-=q;p*=creal((v-w)/p);*a=v-p;a[1]=w+p;}

Try it online!

Based on the python implementation of @Joel

0

# APL (Dyalog Classic), 21 bytes

⊢/-{,∘-⍨×/(9○÷⍨)\-⌿⍵}

Try it online!