당구 공 충돌


24

충격 직전에 한 쌍의 당구 공의 2 차원 위치와 속도를 고려할 때, 완전히 탄성 충돌 한 후에 속도를 계산하십시오 . 볼은 동일한 반경, 동일한 질량, 균일 한 밀도 및 마찰이없는 이상적인 구 (또는 이와 동등한 원)로 가정합니다.

: 입력 8 개 숫자로 구성되어 첫 번째 볼의 중심 유사의 속도, 두 번째 공. 당신은 어떤 순서로 입력을 허용하고, 2x2x2 배열, 아니면 2 × 2 배열로 예를 들어, 어떤 편리한 방법으로 구성 할 수 와 두 개의 길이 2 배열 하고 . xy 쌍 대신 복잡한 숫자 (언어가 지원하는 경우)를 사용하는 것도 좋습니다. 그러나 직교 이외의 좌표계에서는 입력을 가져서는 안됩니다. 즉, 극좌표는 허용되지 않습니다.p0x,p0y,v0x,v0y,p1x,p1y,v1x,v1yp0x,p0yv0x,v0yp1x,p1y,v1x,v1ypv0v1

참고 당구 공의 반경 간의 거리의 절반 인 것으로 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

파이썬 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 개의 복소수를 반환합니다. ungolfed 버전은 다음과 같습니다.

언 골프

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

온라인으로 사용해보십시오!

계산 공식은 wiki 의 2D- 벡터 공식을 기반으로합니다 . m1=m2 이기 때문에 공식은

{v1=v1dvv2=v2+dv

하자 x12=x1x2v12=v1v2 , 우리는이

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

ungolfed 프로그램에서, p12, v1 - v2, d대응 x12 , y12 , 및 dv 각각.


1
잘 했어! 이 방법 은 복소수를 사용하는 Ramillies의 perl6 답변 과 는 다르게 보입니다 . 바꿀 경우는 바이트를 절약 할 수 r=p-q와 함께 p-=q추가로 사용 p하는 대신 r에 같은 닐의 JS 대답
NGN

1
@ngn, 다르게 보이지만 Joel이 올바르게 지적한 것과 같습니다. 나는 Perl 6 골프에 적합한 형식으로 공식을 작성했으며 Joel은 아마도 Python에 더 적합한 형식을 사용했을 것입니다. 어쨌든 다른 사람은 복잡한 숫자를 독립적으로 사용하는 솔루션을 생각해 낼 것이라고 생각하지 않았습니다. 잘 했어!
Ramillies

3
좋았지 만 질문에 알고리즘을 사용하면 53 바이트 만 소요됩니다.
Neil

1
@Neil 힌트를 주셔서 감사합니다. 이제 계산이 크게 단순화되었습니다.
Joel

3
나는 당신의 모든 훌륭한 솔루션과 자세한 설명을 정말로 좋아합니다!
xnor

11

자바 스크립트 (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길이의 제곱입니다. v의 내적의 차이 o,ps,t와 함께 q,r, 그래서 v/u위한 스케일링 요소이다 q,r그에서 전송 속도의 양을 제공 o,p하는 방법에 대해 s,t. 편집 : @Arnauld 덕분에 2 바이트가 절약되었습니다.


나는 누군가가 알고리즘을 너무 빨리 단순화 할 것이라고 기대하지 않았습니다. 다음은 솔루션 의 시각화 입니다 (Arnauld의 개선으로)
ngn

@ngn 잘못된 링크?

@Neil gitlab의 파이프 라인 로그에 있어야합니다. Ctrl + F5? 화살표는 빨간 공을 제어합니다. 교대가 가속됩니다. 파이어 폭스와 크롬에서 테스트되었습니다. 경고 : 소리.
ngn

@ngn Ah, 지금 일하고 있습니다, 감사합니다! (저는 404를 받았습니다. 또한 개인 탭을 사용하고 있었기 때문에 기본적으로 소리가 들리지 않았지만 소리가 들리지 않았습니다. 그리고 소행성에서는 쓸모가 없습니다. 그렇지 않으면 "촬영을 요청합니다. "key ...)
Neil

8

펄 6 ,75 64 63 61 바이트

에서 map로 전환 하여 볼 수 있도록 for중간 변수에 물건을 넣을 필요가 없어져 11 바이트가 절약되었습니다 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=p1p0 은 첫 번째 공에서 두 번째 공을 가리 킵니다. 따라서 우리가 모든 속도를 그것에 의해 나누면, 법선 방향은 갑자기 실제 축과 일치하고 접선 방향은 가상 축과 일치합니다. (이것은 크기를 망쳐 놓지 만 우리는 상관하지 않습니다.)

V0/V1/

V0'=(V1+나는V0),V1'=(V0+나는V1)
V0'=(V1+나는V0)=[12(V1+V1)+12(V0V0)]= =2(V0+V1V0V1)=12(V0+V1(V0V1)).
V1'V0V1
V1'=12[V0+V1+(V0V1)].

그리고 그게 다야. 모든 프로그램이하는 것은이 계산 일뿐입니다.


매우 시원하다!
ngn

Perl에 대해서는 잘 모르지만 두 개의 켤레 계산을 하나로 병합하여 바이트를 절약 할 수 있다고 생각합니다.
Joel

1
@Joel — 슬프게도, 나는 확실히 할 수 없다고 확신합니다. 첫 번째 켤레가 작동하고 ($^a-$^c)(이 숫자를 정규화하는 람다 내부에서만) 두 번째 켤레는에서 작동합니다 ($b-$d). 그래서 그들은 실제로 화해 할 수 없습니다. 난 그냥 부를 것이다 함수를 만들 수 .conj있지만 (나는 무겁게 사용하기 때문에 그에만 바이트를 추가합니다 $_: 당신이 그것을 지정하지 않고 메소드를 호출 할 수있는 좋은 속성이 변수를 .conj대신 $_.conj).
Ramillies

@Ramillies 설명해 주셔서 감사합니다.
Joel

δ의 크기는 어떤 관련이 있습니까? δ로 나누고 실제 구성 요소를 전환 한 다음 δ를 다시 곱하면됩니다.


3

C (GCC) , 140 (132) 바이트

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

온라인으로 사용해보십시오!

기본적으로 @Neil의 JavaScript 응답 포트이지만 @ceilingcat는 현명하게 재사용 m하고 n임시 저장 하여 8 바이트를 줄였습니다 .




당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.