Відстань між двома точками, які подорожують на полярній графіці


23

Коротка пояснення проблеми

Напишіть програму, щоб знайти мінімальну відстань між двома точками, які проїжджають лише на променях, що виходять від початку і кругами, орієнтованими на початок.

Пояснення Приміщення

Тепер давайте уявимо, що ми в літаку, і в цьому літаку нам дозволяється лише подорожувати спеціальними шляхами. Нам дозволяється подорожувати будь-яким променем, що випливає з походження.

Променями ми можемо подорожувати далі

Ми також можемо подорожувати будь-яким колом, зосередженим у колі

Кола, по яких ми можемо подорожувати

Тепер наша мета - подорожувати з однієї точки на цій площині в іншу. Однак ми не можемо просто подорожувати простою евклідовою стежкою, ми можемо це зробити, лише якщо точки трапляються на промінь, що виходить від центру.

введіть тут опис зображення

Ми можемо подорожувати цим, тому що він падає на один із наших променів.

введіть тут опис зображення

Ми також можемо подорожувати по колах, орієнтованих на походження.

введіть тут опис зображення

Приклади

Тепер ось завдання:

Ми повинні дістатися від однієї точки до іншої за найкоротший шлях; часто це поєднання подорожей по колах і променях.

введіть тут опис зображення

Це, однак, також може подорожувати двома променями.

введіть тут опис зображення

Іноді існують два шляхи, які проїжджають мінімальну відстань.

введіть тут опис зображення

Проблема

Ваше завдання полягає в тому, щоб написати програму, яка, даючи два бали, дасть нам мінімальну відстань між ними, якщо ми будемо слідувати цим правилам. Входи можуть бути задані у прямокутній або полярній формі, а вихід повинен бути одним числом, відстань між ними.

Випробування

(з прямокутним входом)

(1,1) (1,-1) -> ~ 2.22144
(0,0) (1, 1) -> ~ 1.41421
(1,0) (-0.4161 , 0.90929) -> ~ 2
(1,1) (1, 0) -> ~ 1.19961
(1,2) (3, 4) -> ~ 3.16609

Чи є приклади тестів у прямокутній чи полярній формах? Також: bewteen
Angs

Вони у прямокутній формі, я повинен уточнити це
Андо Бандо

Чи правильний останній приклад? Я отримую ~
3.166

6
@ Peter Taylor Тому що вони насправді не той самий шлях. Аналогічним чином шлях від 0,0 до 1,1 на площині xy невеликими кроками, що чергуються в напрямку x і y, видається ідентичним прямого діагонального шляху, оскільки довжина кроку має тенденцію до нуля. Але діагональна стежка має довжину sqrt (2), тоді як крок шлях завжди матиме довжину 2.
Penguino

1
Я думаю, що виклик виглядав би краще, якби зображення не були такими великими. Наразі їм важко слідкувати за текстом
Луїс Мендо

Відповіді:


5

Haskell, 49 48 байт

(a!q)c r=min(q+r)$abs(q-r)+acos(cos$a-c)*min q r

Використання:

> let rect2polar (x,y)=(atan2 y x, sqrt(x^2+y^2))
> let test c1 c2=let [(a1,r1),(a2,r2)]=rect2polar<$>[c1,c2] in (a1!r1)a2 r2
> test (1,0) (-0.4161, 0.90929)
1.9999342590038496

Дякуємо @Zgarb за збереження байта


Ви можете зберегти байт, визначивши (a!q)c rзамість d a q c r.
Згарб

4

JavaScript (ES6), 65 байт

with(Math)(r,t,s,u,v=acos(cos(t-u)))=>v<2?abs(r-s)+v*min(r,s):r+s

Бере полярні координати. Використовує хитрість @Angs для зменшення кута до 0 і π. Для прямокутних координат працює щось подібне:

with(Math)g=(r,t,s,u,v=acos(cos(t-u)))=>v<2?abs(r-s)+v*min(r,s):r+s
with(Math)f=(x,y,v,w)=>g(hypot(y,x),atan2(y,x),hypot(w,v),atan2(y,v))

3

MATL , 22 байти

|ttsGZ}/X/bX<*|bd|+hX<

Вхід - це масив з двох складних чисел.

Спробуйте в Інтернеті! Або перевірити всі тестові випадки .

Пояснення

|       % Implicitly input array and take absolute value of its entries
tt      % Duplicate twice
s       % Sum. This is the length of the path that follows the two radii
GZ}     % Push input again and split into the two numbers
/X/     % Divide and compute angle. This gives the difference of the angles
        % of the two points, between -pi and pi
bX<     % Bubble up a copy of the array of radii and compute minimum
*|      % Multiply and take absolute value. This is the arc part of the
        % path that follows one arc and the difference of radii
bd|     % Bubble up a copy of the array of radii and compute absolute
        % difference. This is the other part of the second path
+       % Add. This gives the length of second path
hX<     % Concatenate and take minimum to produce the smallest length.
        % Implicitly display

2

Рубін, 64 байти

По-перше, моє подання. Функція лямбда з аргументами distance 1, angle 1, distance 2, angle2.

->r,a,s,b{([d=(b-a).abs,?i.to_c.arg*4-d,2].min-2)*[r,s].min+s+r}

Ось два варіанти з 66 байтів (без призначення f=) з наступним моїм фактичним поданням знову на 64 байти.

Solution 1:Using include Math, 66 bytes excluding f=
include Math;f=->r,a,s,b{[acos(cos(b-a)),2].min*[r,s].min+(s-r).abs}

Solution 2:Using complex number to define PI instead, 66 bytes excluding f=
f=->r,a,s,b{[d=(b-a).abs,?i.to_c.arg*4-d,2].min*[r,s].min+(s-r).abs}

SUBMISSION AGAIN, 64 bytes excluding f=
f=->r,a,s,b{([d=(b-a).abs,?i.to_c.arg*4-d,2].min-2)*[r,s].min+s+r}

Подача базується на рішенні 2, але використовує ідентифікацію (s-r).abs= s+r-[s,r].min*2для скорочення коду на 2 байти, отже, -2внутрішні дужки.

Інша примітна особливість - вираз ?i.to_c.arg*4= 2 * PI без використання include Math. Якщо нижча точність прийнятна, це може бути замінено буквальним.

Рішення 2 коментується в тестовій програмі

f=->r,a,s,b{          #r,s are distances, a,b are angles for points 1 and 2 respectively.                       
    [d=(b-a).abs,       #From nearer point we can take arc of length d radians perhaps crossing zero angle to the ray of the further point
    ?i.to_c.arg*4-d,    #or go the other way round which may be shorter (?i.to_c.arg*4 == 2*PI, subtract d from this.)
    2].min*             #or go through the centre if the angle exceeds 2 radians.
  [r,s].min+          #Multiply the radians by the distance of the nearer point from the origin to get the distance travelled. 
  (s-r).abs           #Now add the distance to move along the ray out to the further point.
}

#test cases per question (given as complex numbers, converted to arrays of [distance,angle]+[distance,angle] (+ concatenates.)
#the "splat" operator * converts the array to 4 separate arguments for the function.
p f[*("1+i".to_c.polar + "1-i".to_c.polar)]
p f[*("0".to_c.polar + "1+i".to_c.polar)]
p f[*("1".to_c.polar + "-0.4161+0.90929i".to_c.polar)]
p f[*("1+i".to_c.polar + "1".to_c.polar)]
p f[*("1+2i".to_c.polar + "3+4i".to_c.polar)]

Вихід

2.221441469079183
1.4142135623730951
1.9999342590038496
1.1996117257705434
3.1660966740274357

2

Математика 66 байт

Це займає прямокутні координати і може вивести точне символічне рішення

Min[If[(m=Min[{p,q}=Norm/@#])>0,m*VectorAngle@@#,0]+Abs[p-q],p+q]&

Використання:

%/@{
{{1,1},{1,-1}},
{{0,0},{1,1}},
{{1,0},{-.4161,.90929}},
{{1,1},{1,0}},
{{1,2},{3,4}}
}

врожайність: символічний результат

N @% врожайності:

{2.221441469, 1.414213562, 1.999934259, 1.199611726, 3.166096674}


1
Вишуканий! якщо ви їдете символічним шляхом, ви можете замінити тестовий випадок {1,0} {-. 4161, .90929} на {1,0} {cos (2), sin (2)}
Андо Бандо

1

Python 2, 164 126 125 132 байт:

def A(a,b,c,d,p=3.1415926535):z=abs(a-c);M=lambda f:2*p*f*abs(b-d)/360.0;print min((a==c)*min(a+c,M(a))+(b==d)*z or'',M(a)+z,M(c)+z)

На даний момент я ще більше розглядаю гольф. Приймає полярні координати. Слід викликати у форматі A(r1,θ1,r2,θ2). Виводить значення з плаваючою комою точно до 12значних цифр.

Спробуйте в Інтернеті! (Ідеон)

Проста, зрозуміла реалізація, яка обчислює та виводить для ВИМКНЕННЯ мінімальне значення з масиву щонайменше 3 значень, що містять:

  1. мінімальне значення або суми двох довжин ( r1+r2), або довжини дуги, що з'єднує дві точки iff r1==r2 ;
  2. різниця між цими двома відстанями ( abs(r1-r2)) тоді і тільки тоді θ1==θ2 (тобто дві точки лежать на одній прямій);
  3. якщо жоден з попередніх 2 елементів не додано, то порожній рядок ( ''), як очевидно, в Python, рядок більший за будь-яке ціле число;
  4. і 2 кінцеві значення, наведені від відстані, пройденої по колу та променю, і навпаки між двома точками.

Чому ні math.pi?
користувач202729

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.