Distance entre deux points sur la Lune

11

Étant donné la latitude / longitude de deux points sur la Lune (lat1, lon1)et (lat2, lon2), calculez la distance entre les deux points en kilomètres, en utilisant n'importe quelle formule qui donne le même résultat que la formule haversine.

Contribution

  • Quatre valeurs entières lat1, lon1, lat2, lon2en degrés (angle) ou
  • quatre valeurs décimales ϕ1, λ1, ϕ2, λ2en radians.

Production

Distance en kilomètres entre les deux points (décimale avec n'importe quelle précision ou entier arrondi).

Formule Haversine

d = 2 r \ arcsin \ left (\ sqrt {\ sin ^ 2 \ left (\ frac {\ phi_2 - \ phi_1} {2} \ right) + \ cos (\ phi_1) \ cos (\ phi_2) \ sin ^ 2 \ gauche (\ frac {\ lambda_2 - \ lambda_1} {2} \ droite)} \ droite)

  • r est le rayon de la sphère (supposons que le rayon de la Lune est de 1737 km),
  • ϕ1 latitude du point 1 en radians
  • ϕ2 latitude du point 2 en radians
  • λ1 longitude du point 1 en radians
  • λ2 longitude du point 2 en radians
  • d est la distance circulaire entre les deux points

(source: https://en.wikipedia.org/wiki/Haversine_formula )

Autres formules possibles

Exemple où les entrées sont des degrés et la sortie sous forme d'entier arrondi

42, 9, 50, 2  --> 284
50, 2, 42, 9  --> 284
4, -2, -2, 1  --> 203
77, 8, 77, 8  --> 0
10, 2, 88, 9  --> 2365

Règles

  • L'entrée et la sortie peuvent être données dans n'importe quel format pratique .
  • Spécifiez dans la réponse si les entrées sont en degrés ou en radians .
  • Pas besoin de gérer des valeurs de latitude / longitude invalides
  • Un programme complet ou une fonction sont acceptables. S'il s'agit d'une fonction, vous pouvez renvoyer la sortie plutôt que de l'imprimer.
  • Si possible, veuillez inclure un lien vers un environnement de test en ligne afin que d'autres personnes puissent essayer votre code!
  • Les failles standard sont interdites.
  • Il s'agit de donc toutes les règles de golf habituelles s'appliquent et le code le plus court (en octets) l'emporte.
mdahmoune
la source
7
L'utilisation de cette formule particulière est une exigence non observable. Est - il pas suffisant pour donner le même résultat que cette formule serait donner?
2018
1
Pouvons-nous prendre l'entrée en radians?
Adám
1
@mdahmoune OK, vous avez donc énuméré en degrés pour faciliter l'écriture, mais pouvons - nous exiger que les données soient en radians? Sinon, ce défi devient un combo (ce qui est mauvais) de conversion d'angle et du défi principal.
Adám
5
J'ai dévalorisé cette question car elle semble plutôt être «Qui est la langue qui peut jouer le plus à cette formule», ce qui, à mon avis, n'est pas particulièrement intéressant.
caird coinheringaahing
2
Une formule plus courte pour la plupart des langues serait d = r * acos( sin ϕ1 sin ϕ2 + cos ϕ1 cos ϕ2 cos(λ2 - λ1) )r = 1737
miles

Réponses:

6

Géosphère R + , 54 47 octets

function(p,q)geosphere::distHaversine(p,q,1737)

Essayez-le en ligne!

Prend l'entrée en tant que vecteurs à 2 éléments longitude,latitudeen degrés. TIO n'a pas le geospherepackage mais soyez assuré qu'il renvoie des résultats identiques à la fonction ci-dessous.

Merci à Jonathan Allan d'avoir rasé 7 octets.

R , 64 octets

function(p,l,q,k)1737*acos(sin(p)*sin(q)+cos(p)*cos(q)*cos(k-l))

Essayez-le en ligne!

Prend 4 entrées comme dans les cas de test, mais en radians plutôt qu'en degrés.

Giuseppe
la source
Est -ce le e3et /1000vraiment nécessaire?
Jonathan Allan
1
@JonathanAllan non, ils ne le sont pas. C'est assez stupide de ma part, mais l'argument par défaut pour le rayon est la terre en mètres, donc c'était logique à l'époque, lol
Giuseppe
Notez que la loi sphérique des cosinus n'est pas numériquement stable, en particulier pour les petites distances. C'est probablement correct dans Mathematica , mais dans R et dans la plupart des autres langues, on peut se demander si le critère "toute formule qui donne le même résultat que la formule haversine" est rempli.
cessé de tourner dans le sens antihoraire le
@ceasedtoturncounterclockwis Je l'ai principalement inclus dans le but de l'avoir dans la base R. Je suppose que l'utilisation d'une bibliothèque à virgule flottante de précision arbitraire atténuerait l'effet.
Giuseppe
Oui, ou en utilisant une formule stable comme, disons, la formule haversine ...
cessé de tourner dans le sens inverse des aiguilles d'une montre le
5

JavaScript (Node.js) , 65 octets

(a,b,c,d,C=Math.cos)=>1737*Math.acos(C(a-c)+C(a)*C(c)*(C(d-b)-1))

Essayez-le en ligne!

D'après la réponse de Kevin Cruijssen, les commentaires de Miles et Neil et à la demande d'Arnauld.

Olivier Grégoire
la source
5

JavaScript (ES7), 90 octets

Remarque: voir l'article de @ OlivierGrégoire pour une solution beaucoup plus courte

Un port direct de la réponse de TFeld . Prend l'entrée en radians.

(a,b,c,d,M=Math)=>3474*M.asin((M.sin((c-a)/2)**2+M.cos(c)*M.cos(a)*M.sin((d-b)/2)**2)**.5)

Essayez-le en ligne!

Utilisation de l'infâme with(), 85 octets

Merci à @ l4m2 pour avoir économisé 6 octets

with(Math)f=(a,b,c,d)=>3474*asin((sin((c-a)/2)**2+cos(c)*cos(a)*sin((d-b)/2)**2)**.5)

Essayez-le en ligne!

Arnauld
la source
2
Vous pouvez le fairewith(Math)f=(a,b,c,d)=>3474*asin((sin((c-a)/2)**2+cos(c)*cos(a)*sin((d-b)/2)**2)**.5)
l4m2
77 octets en utilisant l'algorithme plus court de @miles :(a,b,c,d,M=Math)=>1737*M.acos(M.sin(a)*M.sin(c)+M.cos(a)*M.cos(c)*M.cos(d-b))
Kevin Cruijssen
1
74 octets utilisant l' algorithme plus court de @Neil :(a,b,c,d,M=Math)=>1737*M.acos(M.cos(a-c)+M.cos(a)*M.cos(c)*(M.cos(d-b)-1))
Kevin Cruijssen
3
65 octets optimisant la réponse de tout le monde:(a,b,c,d,C=Math.cos)=>1737*Math.acos(C(a-c)+C(a)*C(c)*(C(d-b)-1))
Olivier Grégoire
@ OlivierGrégoire Très sympa. Vous devriez probablement l'afficher en tant que nouvelle réponse.
Arnauld
5

APL (Dyalog Unicode) , 40 35 octets SBCS

Fonction tacite anonyme. Prend {ϕ₁, λ₁} comme argument de gauche et {ϕ₂, λ₂} comme argument de droite.

Utilise la formule 2 r √ (sin² ( (ϕ₁-ϕ₂)2 ) + cos ϕ₁ cos ϕ₂ sin² ( (λ₁ - λ₂)2 ))

3474ׯ1○.5*⍨1⊥(×⍨12÷⍨-)×1,2×.○∘⊃,¨

Essayez-le en ligne! (la rfonction convertit les degrés en radians)


 concaténer les éléments correspondants; {{ϕ₁, ϕ₂}, {λ₁, λ₂}}

 choisissez le premier; {ϕ₁, ϕ₂}

 puis

2×.○ produit de leurs cosinus; cos ϕ₁ cos ϕ₂
lit. point "produit" mais avec sélecteur de fonction trig (2 est cosinus) au lieu de multiplication et fois au lieu de plus

1, ajouter 1 à cela; {1, cos ϕ₁ cos ϕ₂}

( Multipliez cela par le résultat de l'application de la fonction suivante à {ϕ₁, λ₁} et {ϕ₂, λ₂}:

- leurs différences; {ϕ₁ - ϕ₂, λ₁ - λ₂}

2÷⍨ divisez cela par 2; { (ϕ₁ - ϕ₂)2 , (λ₁ - λ₂)2 }

1○ sinus de cela; {sin ( (ϕ₁ - ϕ₂)2 ), sin ( (λ₁ - λ₂)2 )}

×⍨ carré qui (lit. auto-multiplié); {sin² ( (ϕ₁ - ϕ₂)2 ), sin² ( (λ₁-λ₂)2 )}

Nous avons maintenant {sin² ( (ϕ₁ - ϕ₂)2 ), cos ϕ₁ cos ϕ₂ sin² ( (λ₁ - λ₂)2 )}

1⊥ somme que (lit. évaluer en base-1); sin² ( (ϕ₁-ϕ₂)2 ) + cos ϕ₁ cos ϕ₂ sin² ( (λ₁ - λ₂)2 )

.5*⍨ racine carrée de cela (lit. élever cela à la puissance d'un demi)

¯1○ arcsinus de cela

3474× multiplier cela par ce


La fonction permettant d'autoriser la saisie en degrés est:

○÷∘180

÷180 argument divisé par 180

 multiplier par π

Adam
la source
4

Python 2 , 95 octets

lambda a,b,c,d:3474*asin((sin((c-a)/2)**2+cos(c)*cos(a)*sin((d-b)/2)**2)**.5)
from math import*

Essayez-le en ligne!

Prend l'entrée en radians.


Ancienne version, avant que les E / S ne soient relâchées: prend l'entrée en degrés entiers et renvoie une dist arrondie

Python 2 , 135 octets

lambda a,b,c,d:int(round(3474*asin((sin((r(c)-r(a))/2)**2+cos(r(c))*cos(r(a))*sin((r(d)-r(b))/2)**2)**.5)))
from math import*
r=radians

Essayez-le en ligne!

TFeld
la source
vous pouvez supprimer intet roundcomme les décimales sont autorisées en sortie, vous pouvez également éviter la conversion en radians car les entrées en radians sont également autorisées
mdahmoune
@mdahmoune, Merci, mis à jour
TFeld
3

Java 8, 113 92 88 82 octets

(a,b,c,d)->1737*Math.acos(Math.cos(a-c)+Math.cos(a)*Math.cos(c)*(Math.cos(d-b)-1))

Les entrées a,b,c,dsont ϕ1,λ1,ϕ2,λ2en radians.

-21 octets en utilisant la formule plus courte de @miles .
-4 octets grâce à @ OlivierGrégore car je l'ai toujours utilisé {Math m=null;return ...;}avec tous les Math.as m., au lieu de laisser tomber le returnet d'utiliser Mathdirectement.
-6 octets en utilisant la formule plus courte de @Neil .

Essayez-le en ligne.

Explication:

(a,b,c,d)->                  // Method with four double parameters and double return-type
  1737*Math.acos(            //  Return 1737 multiplied with the acos of:
   Math.cos(a-c)             //   the cos of `a` minus `c`,
   +Math.cos(a)*Math.cos(c)  //   plus the cos of `a` multiplied with the cos of `c`
   *(Math.cos(d-b)-1))       //   multiplied with the cos of `d` minus `b` minus 1
Kevin Cruijssen
la source
1
"L'optimisation prématurée est la racine de tout Mal"! 88 octets:(a,b,c,d)->1737*Math.acos(Math.sin(a)*Math.sin(c)+Math.cos(a)*Math.cos(c)*Math.cos(d-b))
Olivier Grégoire
" L'optimisation prématurée est la racine de tout mal " Je suppose que vous avez bien raison .. Merci!
Kevin Cruijssen
1
J'ai trouvé une formulation plus courte:(a,b,c,d)->1737*Math.acos(Math.cos(a-c)+Math.cos(a)*Math.cos(c)*(Math.cos(d-b)-1))
Neil
(Cette formulation n'est cependant pas plus courte dans la langue originale de Wolfram.)
Neil
3

Japt , 55 50 octets

MsU *MsW +McU *McW *McX-V
ToMP1/7l¹ñ@McX aUÃv *#­7

Pas nécessairement tout à fait aussi précis que les autres réponses, mais garçon, je me suis amusé avec celle-ci. Permettez-moi de développer.
Alors que dans la plupart des langues, ce défi est assez simple, Japt a la malheureuse propriété qu'il n'y a pas intégré pour ni arcsine ni arccosine. Bien sûr, vous pouvez intégrer Javascript dans Japt, mais ce serait toujours le contraire du Feng Shui.

Tout ce que nous avons à faire pour surmonter cette nuisance mineure, c'est l'arc cosinus approximatif et nous sommes prêts à partir!

La première partie est tout ce qui est introduit dans l'arc cosinus.

MsU *MsW +McU *McW *McX-V
MsU                        // Take the sine of the first input and
    *MsW...                // multiply by the cos of the second one etc.

Le résultat est implicitement stocké Upour être utilisé ultérieurement.

Après cela, nous devons trouver une bonne approximation pour l'arccosine. Puisque je suis paresseux et pas très bon en mathématiques, nous allons évidemment simplement le forcer brutalement.

ToMP1/7l¹ñ@McX aUÃv *#­7
T                       // Take 0
 o                      // and create a range from it
  MP                    // to π
    1/7l¹               // with resolution 1/7!.
         ñ@             // Sort this range so that
           McX          // the cosine of a given value
               aU       // is closest to U, e.g. the whole trig lot
                        // we want to take arccosine of.
                 Ã      // When that's done,
                  v     // get the first element
                    *#­7 // and multiply it by 1737, returning implicitly.

Nous aurions pu utiliser un nombre important pour la résolution du générateur, les tests manuels ont montré qu'il 7!était suffisamment grand tout en étant raisonnablement rapide.

Prend l'entrée en radians, sort des nombres non arrondis.

Rasé cinq octets grâce à Oliver .

Essayez-le en ligne!

Lente
la source
Vous pouvez supprimer le (dans Mc(X-V. Étant donné que le code de caractère 1737n'est pas ISO-8859-1, il passe à UTF-8, ce qui coûte plus cher. Vous pouvez à la place utiliser le code char pour 173+ 7. ethproductions.github.io/japt/?v=1.4.5&code=I603&input=
Oliver
Vous pouvez également supprimer ce qui ,suit ToMP:-)
Oliver
@Oliver Merci beaucoup, les parenthèses étaient nécessaires dans ma version originale mais sont devenues obsolètes quand je l'ai joué un peu, je l'ai complètement raté. De plus, je ne savais rien de l'encodage, merci beaucoup pour cela aussi.
Nit
1
Si vous souhaitez suivre la route JavaScript, gardez à l'esprit que vous pouvez tout exécuter via shoco.
Oliver
2

Gelée ,  23 22  18 octets

-4 octets grâce aux miles (utilisation {et }utilisation de leur formule .

;I}ÆẠP+ÆSP${ÆA×⁽£ġ

Une fonction dyadique acceptant [ϕ1, ϕ2,]à gauche et [λ1, λ2]à droite en radians qui renvoie le résultat (en virgule flottante).

Essayez-le en ligne!


Le mien ... (a également enregistré un octet ici en utilisant un {)

,IÆẠCH;ÆẠ{Ḣ+PƊ½ÆṢ×⁽µṣ

Essayez-le en ligne

Jonathan Allan
la source
Oh intéressant, j'ai actualisé la page à nouveau et elle a montré votre modification, il suffit de cliquer sur une nouvelle réponse pour montrer que le changement ne se met pas à jour pour montrer vos modifications. l'alternative à 18 octets était;I}ÆẠP+ÆSP${ÆA×⁽£ġ
miles
Je n'ai jamais compris comment utiliser {et }ils ne font jamais ce à quoi je m'attendais. Cela ne veut-il pas dire que je peux faire l'inverse en 17?!
Jonathan Allan
Peut être. {et il }suffit de créer une dyade à partir d'une monade. Une vue similaire pourrait être P{ -> ḷP¥. Pourrait être bon d'ajouter un composant (à partir de J) rapide pour faire quelque chose comme x (P+$) y -> (P x) + (P y)qui peut enregistrer un octet ou deux dans des situations similaires.
miles
2

MATLAB avec Mapping Toolbox, 26 octets

@(x)distance(x{:})*9.65*pi

Fonction anonyme qui prend les quatre entrées comme un tableau de cellules, dans le même ordre que celui décrit dans le défi.

Notez que cela donne des résultats exacts (en supposant que le rayon de la Lune est de 1737 km), car 1737/180égal 9.65.

Exemple exécuté dans Matlab R2017b:

entrez la description de l'image ici

Luis Mendo
la source
1

Python 3, 79 octets

from geopy import*
lambda a,b:distance.great_circle(a,b,radius=1737).kilometers

TIO n'a pas geopy.py

RootTwo
la source
2
@Nit, je crois comprendre qu'il est juste d'utiliser une bibliothèque accessible au public antérieure à la question. Je pense que c'est comme utiliser les outils de cartographie de MATLAB, ou d'autres langages en utilisant une bibliothèque mathématique.
RootTwo
1

APL (Dyalog Unicode) , 29 octets SBCS

Programme complet. Demande stdin pour {ϕ₁, ϕ₂} puis pour {λ₁, λ₂}. Imprime à stdout.

Utilise la formule r acos (sin ϕ₁ sin ϕ₂ + cos (λ₂ - λ₁) cos ϕ₁ cos ϕ₂)

1737ׯ2○+/(2○-/⎕)×@2×/1 2∘.○⎕

Essayez-le en ligne! (la rfonction convertit les degrés en radians)


 invite pour {ϕ₁, ϕ₂}

1 2∘.○ Application de fonction trigonométrique cartésienne; {{sin ϕ₁, sin ϕ₂}, {cos ϕ₁, cos ϕ₂}}

×/ produits rangés; {sin ϕ₁ sin ϕ₂, cos ϕ₁ cos ϕ₂}

()×@2 Au deuxième élément, multipliez ce qui suit par cela:

 invite pour {λ₁, λ₂}

-/ différence entre ceux-ci; λ₁ - λ₂

2○ cosinus de cela; cos (λ₁ - λ₂)

Nous avons maintenant {sin ϕ₁ sin ϕ₂, cos (λ₁ - λ₂) cos ϕ₁ cos ϕ₂}

+/ somme; sin ϕ₁ sin ϕ₂ + cos (λ₁ - λ₂) cos ϕ₁ cos ϕ₂

¯2○ cosinus de cela; cos (sin ϕ₁ sin ϕ₂ + cos (λ₁ - λ₂) cos ϕ₁ cos ϕ₂)

1737× multipliez r par cela; 1737 cos (sin ϕ₁ sin ϕ₂ + cos (λ₁ - λ₂) cos ϕ₁ cos ϕ₂)


La fonction permettant d'autoriser la saisie en degrés est:

○÷∘180

÷180 argument divisé par 180

 multiplier par π

Adam
la source
1

C (gcc) , 100 88 65 64 octets

88 → 65 en utilisant la formule de @miles
65 → 64 en utilisant la formule de @ Neil

#define d(w,x,y,z)1737*acos(cos(w-y)+cos(w)*cos(y)*(cos(z-x)-1))

Essayez-le en ligne!

jxh
la source
Je crois que vous devez ajouter deux octets pour l' -lmindicateur du compilateur.
OOBalance
@OOBalance: La présence du drapeau n'est pas toujours requise. Cela dépend de la façon dont le compilateur a été installé sur le système.
jxh
Bien. Je suppose que cela signifie que je peux soustraire deux octets sur ma réponse: codegolf.stackexchange.com/a/161452/79343 Merci.
OOBalance
@OOBalance: a voté pour la réponse. J'ai également soumis ma propre solution.
jxh
Agréable. A également voté pour le vôtre.
OOBalance
1

Excel, 53 octets

=1737*ACOS(COS(A1-C1)+COS(A1)*COS(C1)*(COS(D1-B1)-1))

Utilisation de la formule de @ Neil. Entrée en radians.

Wernisch
la source
1

Homard , 66 octets

def h(a,c,b,d):1737*radians arccos a.sin*b.sin+a.cos*b.cos*cos d-c

Utilise la formule des miles, mais la saisie est en degrés. Cela ajoute une étape supplémentaire de conversion en radians avant de multiplier par rayon.

Panda0nEarth
la source
1

PHP , 88 octets

Port d' Oliver réponse

function f($a,$b,$c,$d,$e=cos){return 1737*acos($e($a-$c)+$e($a)*$e($c)*($e($d-$b)-1));}

Essayez-le en ligne!

Luis felipe De jesus Munoz
la source
1

SmileBASIC, 60 octets

INPUT X,Y,S,T?1737*ACOS(COS(X-S)+COS(X)*COS(S)*(COS(T-Y)-1))
12Me21
la source