Учитывая двумерные положения и скорости пары бильярдных шаров непосредственно перед ударом, рассчитайте их скорости после идеально упругого столкновения . Предполагается, что шары являются идеальными сферами (или, что то же самое, кругами) с одинаковым радиусом, одинаковой массой, однородной плотностью и без трения.
Вход состоит из 8 чисел: p0x,p0y,v0x,v0y,p1x,p1y,v1x,v1y
где p0x,p0y
находится центр первого шара, v0x,v0y
его скорость и аналогично p1x,p1y,v1x,v1y
для второго шара. Вы можете принимать входные данные в любом порядке и структурировать их любым удобным способом, например, в виде массива 2x2x2 или, возможно, массива 2x2 для p
и двух массивов длины-2 для v0
и v1
. Также хорошо брать комплексные числа (если ваш язык их поддерживает) вместо пар ху. Однако вы не должны принимать входные данные в системе координат, отличной от декартовой, т. Е. Полярная не допускается.
Обратите внимание, что радиус бильярдного шара равен половине расстояния между 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 за помощь в исправлении цвета фона диаграммы
r=p-q
сp-=q
и в дальнейшем использоватьp
вместоr
, как в ответ Нейла расслоение плотнойJavaScript (Node.js) ,
9088 байтПопробуйте онлайн! Ссылка включает тестовый набор. Пояснение:
q,r
перенумерованы как разностный вектор между центрами, иu
это квадрат его длины.v
Разница в точечных произведенияхo,p
иs,t
сq,r
, такv/u
что коэффициент масштабирования дляq,r
этого дает количество скорости, передаваемой изo,p
вs,t
. Редактировать: 2 байта сохранены благодаря @Arnauld.источник
Perl 6 ,
75646361 байт11 байтов сохраняются при переключении с
map
наfor
, без необходимости помещать вещи в промежуточные переменные, чтобы ихmap
можно было увидеть.1 байт сохранен путем изменения
($^a-$^c)².&{$_/abs}
на($^a-$^c).&{$_/.conj}
.2 байта сохранены благодаря @nwellnhof.
Попробуйте онлайн!
объяснение
Когда в оригинальном сообщении говорилось, что входные данные могут быть комплексными числами, сопротивляться было слишком сложно ... Так что для этого требуется 4 комплексных числа (позиция 1, скорость 1, позиция 2, скорость 2) и возвращает скорости в виде комплексных чисел.
Программа использует точно такой же алгоритм, как описано в ОП. Однако с комплексными числами это довольно просто. Во-первых, давайте заметим, что комплексное числоd= р1- р0 указывает от первого мяча ко второму. Таким образом, если мы разделим все скорости на него, то нормальное направление внезапно совпадет с действительной осью, а направление касательной - с мнимой осью. (Это портит величины, но нам все равно.)
Теперь нам нужно переключить нормальные (то есть реальные) части скоростейv0/ д а также v1/ д и после этого умножьте это на d again to make the normal (and the velocities) point in the correct direction (and to unmess the magnitudes). So we need to calculate
v′0v′1=d(Rv1d+iIv0d),=d(Rv0d+iIv1d)
(where R = real part, I = imaginary part). Let's shuffle the first one a bit (using ⋆ 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)).
The result for v′1 can be obtained just by switching v0↔v1 . All that does is changing a sign:
v′1=12[v0+v1+dd⋆(v⋆0−v⋆1)].
And that's it. All the program does is just this calculation, golfed a bit.
источник
($^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
).Jelly, 16 bytes
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!
источник
C (gcc),
140132 bytesTry it online!
Basically a port of @Neil's JavaScript answer, but then @ceilingcat shaved off 8 bytes by cleverly reusing
m
andn
to store temporaries.источник
Python 2,
9792 bytesTry it online!
Modified version of Neil's approach.
источник
C (gcc),
7772 bytesTry it online!
Based on the python implementation of @Joel
источник
APL (Dyalog Classic), 21 bytes
Try it online!
based on @Joel's answer
in: 2x2 complex matrix, out: complex pair
источник