Abstand zwischen zwei Punkten auf dem Mond


11

Geben Sie bei gegebener Breite / Länge von zwei Punkten auf dem Mond (lat1, lon1)und (lat2, lon2)der Entfernung zwischen den beiden Punkten in Kilometern eine beliebige Formel an , die das gleiche Ergebnis wie die Haversine-Formel liefert.

Eingang

  • Vier ganzzahlige Werte lat1, lon1, lat2, lon2in Grad (Winkel) oder
  • vier Dezimalwerte ϕ1, λ1, ϕ2, λ2im Bogenmaß.

Ausgabe

Abstand in Kilometern zwischen den beiden Punkten (Dezimalzahl mit beliebiger Genauigkeit oder gerundeter Ganzzahl).

Haversine Formel

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

wo

  • r ist der Radius der Kugel (angenommen, der Radius des Mondes beträgt 1737 km),
  • ϕ1 Breitengrad von Punkt 1 im Bogenmaß
  • ϕ2 Breitengrad von Punkt 2 im Bogenmaß
  • λ1 Länge von Punkt 1 im Bogenmaß
  • λ2 Länge von Punkt 2 im Bogenmaß
  • d ist der kreisförmige Abstand zwischen den beiden Punkten

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

Andere mögliche Formeln

  • d = r * acos(sin ϕ1 sin ϕ2 + cos ϕ1 cos ϕ2 cos(λ2 - λ1)) @ Meilen 'Formel .
  • d = r * acos(cos(ϕ1 - ϕ2) + cos ϕ1 cos ϕ2 (cos(λ2 - λ1) - 1)) @Neils Formel .

Beispiel, bei dem Eingaben Grad sind und Ausgaben als gerundete Ganzzahl ausgegeben werden

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

Regeln

  • Die Eingabe und Ausgabe kann in jedem geeigneten Format erfolgen .
  • Geben Sie in der Antwort an, ob die Eingaben in Grad oder Bogenmaß erfolgen .
  • Keine Notwendigkeit, ungültige Breiten- / Längengrade zu verarbeiten
  • Entweder ein vollständiges Programm oder eine Funktion sind akzeptabel. Wenn es sich um eine Funktion handelt, können Sie die Ausgabe zurückgeben, anstatt sie zu drucken.
  • Wenn möglich, fügen Sie bitte einen Link zu einer Online-Testumgebung hinzu, damit andere Personen Ihren Code ausprobieren können!
  • Standardlücken sind verboten.
  • Dies ist daher gelten alle üblichen Golfregeln, und der kürzeste Code (in Bytes) gewinnt.

7
Die Verwendung dieser bestimmten Formel ist eine nicht beobachtbare Anforderung. Ist es nicht genug, das gleiche Ergebnis zu erzielen, das diese Formel liefern würde ?
Adám

1
Dürfen wir die Eingabe im Bogenmaß nehmen?
Adám

1
@mdahmoune OK, so aufgeführt Sie in Grad zur Erleichterung des Schreibens, aber können wir Eingabe erfordern in Radiant zu sein? Andernfalls wird diese Herausforderung zu einer Kombination (was schlecht ist) der Winkelumwandlung und der Hauptherausforderung.
Adám

5
Ich habe diese Frage abgelehnt, weil es eher so aussieht: "Wer kann diese Formel am meisten spielen?", Was meiner Meinung nach nicht besonders interessant ist.
Caird Coinheringaahing

2
Eine kürzere Formel für die meisten Sprachen wäre d = r * acos( sin ϕ1 sin ϕ2 + cos ϕ1 cos ϕ2 cos(λ2 - λ1) )wor = 1737
Meilen

Antworten:



6

R + Geosphäre , 54 47 Bytes

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

Probieren Sie es online aus!

Nimmt die Eingabe als 2-Element-Vektoren longitude,latitudein Grad auf. TIO hat das geospherePaket nicht, aber Sie können sicher sein, dass es identische Ergebnisse für die folgende Funktion zurückgibt.

Vielen Dank an Jonathan Allan für das Rasieren von 7 Bytes.

R , 64 Bytes

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

Probieren Sie es online aus!

Nimmt 4 Eingaben wie in den Testfällen vor, jedoch eher im Bogenmaß als in Grad.


Sind die e3und /1000wirklich notwendig?
Jonathan Allan

1
@ JonathanAllan nein sie sind nicht. Das ist ziemlich dumm von mir, aber das Standardargument für den Radius ist die der Erde in Metern, also war es zu der Zeit logisch, lol
Giuseppe

Beachten Sie, dass das sphärische Gesetz von Cosinus numerisch nicht stabil ist, insbesondere für kleine Entfernungen. In Mathematica ist das wahrscheinlich in Ordnung , aber in R und den meisten anderen Sprachen ist fraglich, ob das Kriterium "Jede Formel, die das gleiche Ergebnis wie die Haversinformel liefert" erfüllt ist.
hörte auf, gegen den Uhrzeigersinn zu drehen

@ceasedtoturncounterclockwis Ich habe es meistens eingefügt, um es in Basis R zu haben. Ich nehme an, die Verwendung einer Gleitkommabibliothek mit beliebiger Genauigkeit würde den Effekt abschwächen.
Giuseppe

Ja, oder mit einer stabilen Formel wie zum Beispiel der Haversine-Formel ...
hörte auf, sich gegen den Uhrzeigersinn zu drehen, als der


5

JavaScript (ES7), 90 Byte

Hinweis: Eine viel kürzere Lösung finden Sie im Beitrag von @ OlivierGrégoire

Ein direkter Hafen von TFelds Antwort . Nimmt Eingaben im Bogenmaß vor.

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

Probieren Sie es online aus!

Mit dem berüchtigten with()85 Bytes

Vielen Dank an @ l4m2 für die Einsparung von 6 Bytes

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

Probieren Sie es online aus!


2
Sie können tunwith(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 Bytes mit dem kürzeren Algorithmus von @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 Bytes mit @Neils kürzerem Algorithmus :(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 Bytes, die jedermanns Antwort optimieren:(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 Sehr schön. Sie sollten es wahrscheinlich als neue Antwort posten.
Arnauld

5

APL (Dyalog Unicode) , 40 35 Byte SBCS

Anonyme stillschweigende Funktion. Nimmt {ϕ₁, λ₁} als linkes Argument und {ϕ₂, λ₂} als rechtes Argument.

Verwendet die Formel 2 r √ (sin² ( (ϕ₁-ϕ₂)2 ) + cos ϕ₁ cos ϕ₂ sin² ( (λ₁ - λ₂)2 ))

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

Probieren Sie es online aus! (Die rFunktion konvertiert Grad in Bogenmaß)


 entsprechende Elemente verketten; {{ϕ₁, ϕ₂}, {λ₁, λ₂}}

 wähle den ersten aus; {ϕ₁, ϕ₂}

 dann

2×.○ Produkt ihrer Kosinusse; cos ϕ₁ cos ϕ₂
lit. Punkt "Produkt", aber mit Triggerfunktionswähler (2 ist Cosinus) anstelle von Multiplikation und Zeiten anstelle von Plus

1, 1 voranstellen; {1, cos ϕ₁ cos ϕ₂}

( Multiplizieren Sie dies mit dem Ergebnis der Anwendung der folgenden Funktion auf {ϕ₁, λ₁} und {ϕ₂, λ₂}:

- ihre Unterschiede; {ϕ₁ - ϕ₂, λ₁ - λ₂}

2÷⍨ dividiere das durch 2; { (ϕ₁ - ϕ₂)2 , (λ₁ - λ₂)2 }

1○ Sinus davon; {sin ( (ϕ₁ - ϕ₂)2 ), sin ( (λ₁ - λ₂)2 )}

×⍨ Quadrat das (lit. selbst multiplizieren); {sin² ( (ϕ₁ - ϕ₂)2 ), sin² ( (λ₁-λ₂)2 )}

Jetzt haben wir {sin² ( (ϕ₁ - ϕ₂)2 ), cos ϕ₁ cos ϕ₂ sin² ( (λ₁ - λ₂)2 )}

1⊥ Summe, die (lit. in Basis-1 auswerten); sin² ( (ϕ₁-ϕ₂)2 ) + cos ϕ₁ cos ϕ₂ sin² ( (λ₁ - λ₂)2 )

.5*⍨ Quadratwurzel davon (wörtlich: Erhöhen Sie das auf die Potenz einer halben)

¯1○ Arkussinus davon

3474× multiplizieren Sie das damit


Die Funktion zum Zulassen der Eingabe in Grad ist:

○÷∘180

÷180 Argument geteilt durch 180

 mit π multiplizieren


4

Python 2 , 95 Bytes

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*

Probieren Sie es online aus!

Nimmt Eingaben im Bogenmaß vor.


Alte Version, bevor die E / A nachgelassen hat: Nimmt die Eingabe als ganzzahlige Grade und gibt gerundete Dist zurück

Python 2 , 135 Bytes

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

Probieren Sie es online aus!


Sie können fallen lassen intund roundweil Dezimalstellen als Ausgabe zulässig sind, können Sie auch die Konvertierung in Bogenmaß vermeiden, da Eingaben als Bogenmaß ebenfalls zulässig sind
mdahmoune

@ Mdahmoune, danke, aktualisiert
TFeld

3

Java 8, 113 92 88 82 Bytes

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

Die Eingänge a,b,c,dsind ϕ1,λ1,ϕ2,λ2in Radiant.

-21 Bytes mit der kürzeren Formel von @miles .
-4 Bytes danke an @ OlivierGrégore, weil ich immer noch {Math m=null;return ...;}mit jedem Math.as verwendet habe m., anstatt das zu löschenreturn und Mathdirekt zu verwenden.
-6 Bytes mit der kürzeren Formel von @Neil .

Probieren Sie es online aus.

Erläuterung:

(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

1
"Vorzeitige Optimierung ist die Wurzel allen Übels"! 88 Bytes:(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

" Vorzeitige Optimierung ist die Wurzel allen Übels " Ich denke, Sie haben tatsächlich Recht. Danke!
Kevin Cruijssen

1
Ich habe eine kürzere Formulierung gefunden:(a,b,c,d)->1737*Math.acos(Math.cos(a-c)+Math.cos(a)*Math.cos(c)*(Math.cos(d-b)-1))
Neil

(Diese Formulierung ist in der ursprünglichen Wolfram-Sprache jedoch nicht kürzer.)
Neil

3

Japt , 55 50 Bytes

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

Nicht unbedingt ganz so präzise wie die anderen Antworten, aber Junge, hatte ich Spaß mit dieser. Lassen Sie mich näher darauf eingehen.
Während diese Herausforderung in den meisten Sprachen recht einfach ist, hat Japt die unglückliche Eigenschaft, dass weder für Arkussinus noch für Arccosin ein integrierter Bestandteil vorhanden ist. Sicher, Sie können Javascript in Japt einbetten, aber das ist das Gegenteil von Feng Shui.

Alles, was wir tun müssen, um dieses kleine Ärgernis zu überwinden, ist ungefähres Arccosin und wir können loslegen!

Der erste Teil ist alles, was in das Arccosin eingespeist wird.

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.

Das Ergebnis wird implizit gespeichert U, um später verwendet zu werden.

Danach müssen wir eine gute Annäherung für Arccosin finden. Da ich faul bin und nicht so gut mit Mathe umgehen kann, werden wir es offensichtlich nur brutal erzwingen.

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.

Wir hätten jede große Zahl für die Generatorauflösung verwenden können. Manuelle Tests haben gezeigt, dass sie 7!ausreichend groß und relativ schnell sind.

Nimmt die Eingabe als Bogenmaß und gibt ungerundete Zahlen aus.

Dank Oliver fünf Bytes rasiert .

Probieren Sie es online aus!


Sie können das (in entfernen Mc(X-V. Da der Zeichencode für 1737nicht ISO-8859-1 ist, wechselt er zu UTF-8, was mehr kostet. Sie können stattdessen den Zeichencode für 173+ verwenden 7. ethproductions.github.io/japt/?v=1.4.5&code=I603&input=
Oliver

Sie können auch die ,nach entfernen ToMP:-)
Oliver

@Oliver Vielen Dank, die Klammern waren in meiner Originalversion notwendig, wurden aber beim Golfen veraltet, ich habe sie jedoch komplett verpasst. Ich wusste auch nichts über die Codierung, vielen Dank auch dafür.
Nit

1
Wenn Sie den JavaScript-Weg gehen möchten, denken Sie daran, dass Sie alles über shoco ausführen können.
Oliver



2

Gelee ,  23 22  18 Bytes

-4 Bytes dank Meilen (Verwendung {und }Verwendung ihrer Formel .

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

Eine dyadische Funktion, [ϕ1, ϕ2,]die links und [λ1, λ2]rechts im Bogenmaß akzeptiert und das Ergebnis zurückgibt (als Gleitkomma).

Probieren Sie es online aus!


Meins ... (hat hier auch ein Byte mit a gespeichert {)

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

Probieren Sie es online aus


Oh interessant, ich habe die Seite erneut aktualisiert und sie hat Ihre Bearbeitung angezeigt. Klicken Sie einfach auf Neue Antwort, um anzuzeigen, dass die Änderung nicht aktualisiert wird, um Ihre Änderungen anzuzeigen. Die 18-Byte-Alternative war;I}ÆẠP+ÆSP${ÆA×⁽£ġ
Meilen

Ich habe nie verstanden, wie man es benutzt {und }sie machen nie das, was ich erwarten würde. Bedeutet das nicht, dass ich in 17 den anderen Weg gehen kann?!
Jonathan Allan

Könnte sein. {und }erstelle einfach eine Dyade aus einer Monade. Eine ähnliche Ansicht könnte sein P{ -> ḷP¥. Könnte gut sein, schnell eine Komposition (aus J) hinzuzufügen , um so etwas zu tun, x (P+$) y -> (P x) + (P y)das in ähnlichen Situationen ein oder zwei Bytes sparen kann.
Meilen

2

MATLAB mit Mapping Toolbox, 26 Bytes

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

Anonyme Funktion, die die vier Eingaben als Zellenarray in derselben Reihenfolge wie in der Herausforderung beschrieben verwendet.

Beachten Sie, dass dies genaue Ergebnisse liefert (vorausgesetzt, der Mondradius beträgt 1737 km), da 1737/180gleich ist 9.65.

Beispiellauf in Matlab R2017b:

Geben Sie hier die Bildbeschreibung ein


1

Python 3, 79 Bytes

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

TIO hat keine geopy.py


2
@Nit, ich verstehe, dass es ein faires Spiel ist, eine öffentlich verfügbare Bibliothek zu verwenden, die vor der Frage liegt. Ich denke, es ist wie mit den Mapping-Tools von MATLAB oder anderen Sprachen mit einer Mathematikbibliothek.
RootTwo

1

APL (Dyalog Unicode) , 29 Byte SBCS

Komplettes Programm. Fordert stdin zu {ϕ₁, ϕ₂} und dann zu {λ₁, λ₂} auf. Druckt nach Standard.

Verwendet die Formel r acos (sin ϕ₁ sin ϕ₂ + cos (λ₂ - λ₁) cos ϕ₁ cos ϕ₂)

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

Probieren Sie es online aus! (Die rFunktion konvertiert Grad in Bogenmaß)


 Eingabeaufforderung für {ϕ₁, ϕ₂}

1 2∘.○ Kartesische Triggerfunktionsanwendung; {{sin ϕ₁, sin ϕ₂}, {cos ϕ₁, cos ϕ₂}}

×/ zeilenweise Produkte; {sin ϕ₁ sin ϕ₂, cos ϕ₁ cos ϕ₂}

()×@2 Multiplizieren Sie im zweiten Element Folgendes damit:

 Eingabeaufforderung für {λ₁, λ₂}

-/ Unterschied zwischen diesen; λ₁ - λ₂

2○ Kosinus davon; cos (λ₁ - λ₂)

Jetzt haben wir {sin ϕ₁ sin ϕ₂, cos (λ₁ - λ₂) cos ϕ₁ cos ϕ₂}

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

¯2○ Kosinus davon; cos (sin ϕ₁ sin ϕ₂ + cos (λ₁ - λ₂) cos ϕ₁ cos ϕ₂)

1737× multipliziere r damit; 1737 cos (sin ϕ₁ sin ϕ₂ + cos (λ₁ - λ₂) cos ϕ₁ cos ϕ₂)


Die Funktion zum Zulassen der Eingabe in Grad ist:

○÷∘180

÷180 Argument geteilt durch 180

 mit π multiplizieren


1

C (gcc) , 100 88 65 64 Bytes

88 → 65 mit der Formel von @miles
65 → 64 mit der Formel von @ Neil

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

Probieren Sie es online aus!


Ich glaube, Sie müssen zwei Bytes für das -lmCompiler-Flag hinzufügen .
OOBalance

@OOBalance: Das Vorhandensein des Flags ist nicht immer erforderlich. Dies hängt davon ab, wie der Compiler auf dem System installiert wurde.
jxh

In Ordung. Vermutlich bedeutet dies, dass ich bei meiner Antwort zwei Bytes subtrahieren kann: codegolf.stackexchange.com/a/161452/79343 Danke.
OOBalance

@OOBalance: Die Antwort wurde positiv bewertet. Ich habe auch meine eigene Lösung eingereicht.
jxh

Nett. Auch deine positiv bewertet.
OOBalance

1

Excel, 53 Bytes

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

Verwenden Sie die Formel von @ Neil. Eingabe im Bogenmaß.


1

Hummer , 66 Bytes

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

Verwendet die Meilenformel, aber die Eingabe erfolgt in Grad. Dies fügt einen zusätzlichen Schritt der Umrechnung in Bogenmaß hinzu, bevor mit dem Radius multipliziert wird.




1

SmileBASIC, 60 Bytes

INPUT X,Y,S,T?1737*ACOS(COS(X-S)+COS(X)*COS(S)*(COS(T-Y)-1))
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.