Distance entre deux points se déplaçant sur une carte graphique polaire


23

Brève explication du problème

Écrivez un programme pour trouver la distance minimale entre deux points se déplaçant uniquement sur des rayons émanant de l'origine et des cercles centrés sur l'origine.

Explication de la prémisse

Imaginons maintenant que nous soyons dans un avion, et sur cet avion, nous ne sommes autorisés à voyager que de manière spéciale. Nous sommes autorisés à voyager sur n'importe quel rayon émanant de l'origine.

Rayons sur lesquels nous pouvons voyager

Nous pouvons également voyager sur n'importe quel cercle centré sur un cercle

Cercles sur lesquels nous pouvons voyager

Maintenant, notre objectif est de voyager d'un point sur cet avion à un autre. Cependant, nous ne pouvons pas simplement voyager dans un simple chemin euclidien, nous ne pouvons le faire que si les points tombent sur un rayon émanant du centre.

entrez la description de l'image ici

Nous pouvons voyager sur celui-ci car il tombe sur l'un de nos rayons.

entrez la description de l'image ici

On peut aussi voyager sur des cercles centrés à l'origine.

entrez la description de l'image ici

Exemples

Voici maintenant le défi:

Nous devons aller d'un point à un autre sur le chemin le plus court; c'est souvent une combinaison de voyages sur des cercles et des rayons.

entrez la description de l'image ici

Cependant, il pourrait également se déplacer sur deux rayons.

entrez la description de l'image ici

Parfois, il existe deux chemins qui parcourent la distance minimale.

entrez la description de l'image ici

Problème

Votre défi est d'écrire un programme qui, lorsque deux points vous seront donnés, nous donnera la distance minimale entre eux si nous suivons ces règles. Les entrées peuvent être données sous forme rectangulaire ou polaire et la sortie doit être un nombre, la distance entre les deux.

Cas de test

(avec entrée rectangulaire)

(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

Les exemples de cas de test sont-ils sous forme rectangulaire ou polaire? Aussi:
bewteen

Ils sont sous forme rectangulaire, je dois préciser que
Ando Bando

Le dernier exemple est-il correct? Je reçois ~ 3.166
Angs

6
@Peter Taylor Parce qu'ils ne sont pas vraiment sur le même chemin. De la même manière, un chemin de 0,0 à 1,1 sur le plan xy via de petits pas alternant dans les directions x et y apparaît identique à un chemin diagonal direct car la longueur du pas tend vers zéro. Mais le chemin diagonal a une longueur sqrt (2) tandis que le chemin de l'étape aura toujours une longueur 2.
Penguino

1
Je pense que le défi serait meilleur si les images n'étaient pas si grandes. Actuellement, il est difficile de suivre le texte
Luis Mendo

Réponses:


5

Haskell, 49 48 octets

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

Usage:

> 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

Merci à @Zgarb d'avoir enregistré un octet


Vous pouvez enregistrer un octet en définissant (a!q)c rau lieu de d a q c r.
Zgarb

4

JavaScript (ES6), 65 octets

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

Prend des coordonnées polaires. Utilise l'astuce @Angs pour réduire un angle entre 0 et π. Pour les coordonnées rectangulaires, quelque chose comme ceci fonctionne:

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 octets

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

L'entrée est un tableau de deux nombres complexes.

Essayez-le en ligne! Ou vérifiez tous les cas de test .

Explication

|       % 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

Ruby, 64 octets

Tout d'abord, ma soumission. Fonction lambda avec arguments 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}

Voici maintenant deux solutions différentes de 66 octets (hors affectation f=) suivies de ma soumission réelle à nouveau à 64 octets.

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}

La soumission est basée sur la solution 2, mais utilise l'identité (s-r).abs= s+r-[s,r].min*2pour raccourcir le code de 2 octets, d'où l' -2intérieur des crochets.

L'autre caractéristique notable est l'expression ?i.to_c.arg*4= 2 * PI sans utiliser include Math. Si une précision inférieure est acceptable, elle peut être remplacée par un littéral.

Solution 2 commentée dans le programme de test

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

Sortie

2.221441469079183
1.4142135623730951
1.9999342590038496
1.1996117257705434
3.1660966740274357

2

Mathematica 66 octets

Cela prend des coordonnées rectangulaires et peut produire une solution symbolique exacte

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

Usage:

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

rendements: résultat symbolique

N @% rendements:

{2.221441469, 1.414213562, 1.999934259, 1.199611726, 3.166096674}


1
Nifty! si vous suivez la route symbolique, vous pouvez remplacer le cas de test {1,0} {-. 4161, .90929} par {1,0} {cos (2), sin (2)}
Ando Bando

1

Python 2, 164 126 125 125 132 octets:

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)

Je cherche actuellement à jouer au golf plus, cependant. Accepte les coordonnées polaires. Doit être appelé dans le format A(r1,θ1,r2,θ2). Produit une valeur en virgule flottante précise jusqu'à 12des chiffres significatifs.

Essayez-le en ligne! (Ideone)

Une implémentation simple et directe qui calcule et renvoie à STDOUT la valeur minimale à partir d'un tableau d'au plus 3 valeurs contenant:

  1. la valeur minimale de la somme des deux longueurs ( r1+r2) ou de la longueur de l'arc reliant les deux points ssi r1==r2 ;
  2. la différence entre les deux distances ( abs(r1-r2)) ssi θ1==θ2 (c'est-à-dire que les deux points sont colinéaires);
  3. si aucun des 2 éléments précédents n'est ajouté, alors une chaîne vide ( '') comme apparemment en Python une chaîne est supérieure à n'importe quel entier;
  4. et 2 valeurs finales données à partir des distances parcourues le long d'un cercle et d'un rayon et vice-versa entre les deux points.

Pourquoi ne pas math.pi?
user202729

En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.