Distanza tra due punti sulla Luna


11

Data la latitudine / longitudine di due punti sulla Luna (lat1, lon1)e (lat2, lon2), calcola la distanza tra i due punti in chilometri, usando qualsiasi formula che dia lo stesso risultato della formula haversine.

Ingresso

  • Quattro valori interi lat1, lon1, lat2, lon2in gradi (angolo) o
  • quattro valori decimali ϕ1, λ1, ϕ2, λ2in radianti.

Produzione

Distanza in chilometri tra i due punti (decimale con precisione o numero intero arrotondato).

Formula di 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 \ left (\ frac {\ lambda_2 - \ lambda_1} {2} \ right)} \ right)

dove

  • r è il raggio della sfera (supponiamo che il raggio della Luna sia di 1737 km),
  • ϕ1 latitudine del punto 1 in radianti
  • ϕ2 latitudine del punto 2 in radianti
  • λ1 longitudine del punto 1 in radianti
  • λ2 longitudine del punto 2 in radianti
  • d è la distanza circolare tra i due punti

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

Altre possibili formule

  • d = r * acos(sin ϕ1 sin ϕ2 + cos ϕ1 cos ϕ2 cos(λ2 - λ1)) formula di @miles .
  • d = r * acos(cos(ϕ1 - ϕ2) + cos ϕ1 cos ϕ2 (cos(λ2 - λ1) - 1)) Formula di @Neil .

Esempio in cui gli input sono gradi e output come numero intero arrotondato

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

Regole

  • L'input e l'output possono essere forniti in qualsiasi formato conveniente .
  • Specificare nella risposta se gli ingressi sono in gradi o radianti .
  • Non è necessario gestire valori di latitudine / longitudine non validi
  • È accettabile un programma completo o una funzione. Se una funzione, è possibile restituire l'output anziché stamparlo.
  • Se possibile, includi un collegamento a un ambiente di test online in modo che altre persone possano provare il tuo codice!
  • Sono vietate le scappatoie standard .
  • Si tratta di quindi si applicano tutte le normali regole del golf e vince il codice più breve (in byte).

7
L'uso di quella particolare formula è un requisito inosservabile. Non è sufficiente dare lo stesso risultato che darebbe quella formula ?
Adám,

1
Possiamo prendere l'input in radianti?
Adám,

1
@mdahmoune OK, quindi hai elencato in gradi per facilità di scrittura, ma potremmo aver bisogno di input in radianti? Altrimenti questa sfida diventa una combinazione (che è cattiva) di conversione dell'angolo e della sfida principale.
Adám,

5
Ho sottovalutato questa domanda perché sembra più che altro "Chi è la lingua può golf questa formula di più", che, secondo me, non è particolarmente interessante.
caird coinheringaahing

2
Una formula più breve per la maggior parte delle lingue sarebbe d = r * acos( sin ϕ1 sin ϕ2 + cos ϕ1 cos ϕ2 cos(λ2 - λ1) )dover = 1737
miglia

Risposte:



6

Geosfera R + , 54 47 byte

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

Provalo online!

Accetta input come vettori a 2 elementi longitude,latitudein gradi. TIO non ha il geospherepacchetto ma si assicura che restituisce risultati identici alla funzione seguente.

Grazie a Jonathan Allan per la rasatura di 7 byte.

R , 64 byte

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

Provalo online!

Accetta 4 input come nei casi di test, ma in radianti anziché in gradi.


Sono il e3e /1000davvero necessario?
Jonathan Allan,

1
@JonathanAllan no, non lo sono. È piuttosto stupido da parte mia, ma l'argomento predefinito per il raggio è la terra in metri, quindi era logico al momento, lol
Giuseppe

Si noti che la legge sferica dei coseni non è numericamente stabile, in particolare per le piccole distanze. Probabilmente va bene in Mathematica , ma in R e nella maggior parte delle altre lingue è discutibile se il criterio "qualsiasi formula che dia lo stesso risultato della formula di haversine" sia soddisfatto.
cessò di girare in senso antiorario il

@ceasedtoturncounterclockwis L'ho incluso principalmente per il gusto di averlo nella base R. Suppongo che l'uso di una libreria a virgola mobile di precisione arbitraria mitigherebbe l'effetto.
Giuseppe,

Sì, o usando una formula stabile come, diciamo, la formula haversine ...
cessò di girare in senso antiorario il


5

JavaScript (ES7), 90 byte

Nota: vedi il post di @ OlivierGrégoire per una soluzione molto più breve

Una porta diretta della risposta di TFeld . Accetta input in radianti.

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

Provalo online!

Utilizzando il famigerato with(), 85 byte

Grazie a @ l4m2 per il risparmio di 6 byte

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

Provalo online!


2
Puoi farewith(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 byte usando l'algoritmo più corto di @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 l'

1
74 byte utilizzando @Neil 's più breve algoritmo :(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 byte ottimizzando la risposta di tutti:(a,b,c,d,C=Math.cos)=>1737*Math.acos(C(a-c)+C(a)*C(c)*(C(d-b)-1))
Olivier Grégoire l'

@ OlivierGrégoire Molto bello. Probabilmente dovresti pubblicarlo come una nuova risposta.
Arnauld,

5

APL (Dyalog Unicode) , 40 35 byte SBCS

Funzione tacita anonima. Prende {ϕ₁, λ₁} come argomento di sinistra e {ϕ₂, λ₂} come argomento di destra.

Usa la formula 2 r √ (sin² ( (ϕ₁-ϕ₂)2 ) + cos ϕ₁ cos ϕ₂ sin² ( (λ₁ - λ₂)2 ))

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

Provalo online! (la rfunzione converte i gradi in radianti)


 concatenare gli elementi corrispondenti; {{ϕ₁, ϕ₂}, {λ₁, λ₂}}

 scegli il primo; {ϕ₁, ϕ₂}

 poi

2×.○ prodotto dei loro coseni; cos ϕ₁ cos ϕ₂
lit. punto "prodotto" ma con selettore della funzione di attivazione (2 è coseno) invece di moltiplicazione e tempi anziché più

1, anteporre 1 a quello; {1, cos ϕ₁ cos ϕ₂}

(...  moltiplicalo per il risultato dell'applicazione della seguente funzione a {ϕ₁, λ₁} e {ϕ₂, λ₂}:

- le loro differenze; {ϕ₁ - ϕ₂, λ₁ - λ₂}

2÷⍨ dividerlo per 2; { (ϕ₁ - ϕ₂)2 , (λ₁ - λ₂)2 }

1○ seno di quello; {sin ( (ϕ₁ - ϕ₂)2 ), sin ( (λ₁ - λ₂)2 )}

×⍨ quadrato che (lit. auto-moltiplica); {sin² ( (ϕ₁ - ϕ₂)2 ), sin² ( (λ₁-λ₂)2 )}

Ora abbiamo {sin² ( (ϕ₁ - ϕ₂)2 ), cos ϕ₁ cos ϕ₂ sin² ( (λ₁ - λ₂)2 )}

1⊥ somma che (lett. valuta in base-1); sin² ( (ϕ₁-ϕ₂)2 ) + cos ϕ₁ cos ϕ₂ sin² ( (λ₁ - λ₂)2 )

.5*⍨ radice quadrata di quello (lett. elevalo alla potenza della metà)

¯1○ arcsine di quello

3474× moltiplicalo per questo


La funzione per consentire l'inserimento in gradi è:

○÷∘180

÷180 argomento diviso per 180

 moltiplicare per π


4

Python 2 , 95 byte

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*

Provalo online!

Accetta input in radianti.


Versione precedente, prima che gli I / o venissero allentati: accetta input come gradi interi e restituisce una distanza arrotondata

Python 2 , 135 byte

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

Provalo online!


puoi rilasciare inte roundpoiché i decimali sono consentiti come output, puoi anche evitare la conversione in radianti perché sono consentiti anche input come radianti
mdahmoune

@mdahmoune, grazie, aggiornato
TFeld

3

Java 8, 113 92 88 82 byte

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

Gli ingressi a,b,c,dsono ϕ1,λ1,ϕ2,λ2in radianti.

-21 byte usando la formula più breve di @miles .
-4 byte grazie a @ OlivierGrégore perché l'ho ancora usato {Math m=null;return ...;}con ogni Math.as m., invece di far cadere returne usare Mathdirettamente.
-6 byte usando la formula più breve di @Neil .

Provalo online.

Spiegazione:

(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
"L'ottimizzazione precoce è la radice di tutti i mali"! 88 byte:(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'ottimizzazione prematura è la radice di tutti i mali " Immagino tu abbia davvero ragione .. Grazie!
Kevin Cruijssen l'

1
Ho trovato una formulazione più breve:(a,b,c,d)->1737*Math.acos(Math.cos(a-c)+Math.cos(a)*Math.cos(c)*(Math.cos(d-b)-1))
Neil,

(Questa formulazione non è più breve nella lingua originale di Wolfram.)
Neil,

3

Japt , 55 50 byte

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

Non necessariamente preciso come le altre risposte, ma ragazzo mi sono divertito con questo. Mi permetta di elaborare.
Mentre nella maggior parte delle lingue, questa sfida è piuttosto semplice, Japt ha la sfortunata proprietà che non esiste un built-in né per arcsine né per arccosine. Certo, puoi incorporare Javascript in Japt, ma sarebbe quello che è sempre il contrario di Feng Shui.

Tutto ciò che dobbiamo fare per superare questo piccolo fastidio è l'arccosina approssimativa e siamo pronti per partire!

La prima parte è tutto ciò che viene alimentato nell'arccosina.

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.

Il risultato viene implicitamente archiviato Uper essere utilizzato in seguito.

Successivamente, dobbiamo trovare una buona approssimazione per l'arccosina. Dato che sono pigro e non molto bravo con la matematica, ovviamente lo faremo solo per forzare.

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.

Avremmo potuto usare qualsiasi numero elevato per la risoluzione del generatore, i test manuali hanno mostrato che 7!è sufficientemente grande pur essendo ragionevolmente veloce.

Accetta input come radianti, genera numeri non arrotondati.

Rasato cinque byte grazie a Oliver .

Provalo online!


È possibile rimuovere (in Mc(X-V. Poiché il codice char 1737non è ISO-8859-1, passa a UTF-8, che costa di più. Puoi invece usare il codice char per 173+ 7. ethproductions.github.io/japt/?v=1.4.5&code=I603&input=
Oliver

Puoi anche rimuovere il ,dopo ToMP:-)
Oliver l'

@Oliver Grazie mille, la parentesi era necessaria nella mia versione originale, ma è diventata obsoleta quando la giocavo un po 'in giro, però mi mancava completamente. Inoltre, non sapevo nulla della codifica, grazie anche per quello.
Nit

1
Se vuoi seguire il percorso JavaScript, tieni presente che puoi eseguire tutto tramite shoco.
Oliver,



2

Gelatina ,  23 22  18 byte

-4 byte grazie alle miglia (uso di {e }durante l'utilizzo della loro formula .

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

Una funzione diadica che accetta [ϕ1, ϕ2,]a sinistra ea [λ1, λ2]destra in radianti che restituisce il risultato (come virgola mobile).

Provalo online!


Il mio ... (anche salvato un byte qui usando a {)

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

Provalo online


Oh interessante, ho aggiornato di nuovo la pagina e ha mostrato la tua modifica, basta fare clic su una nuova risposta per mostrare che la modifica non si aggiorna per mostrare le tue modifiche. l'alternativa a 18 byte era;I}ÆẠP+ÆSP${ÆA×⁽£ġ
miglia

Non ho mai capito come usare {e }non fanno mai quello che mi aspetto. Questo non significa che posso fare il contrario in 17 ?!
Jonathan Allan,

Può essere. {e }basta creare una diade da una monade. Una vista simile potrebbe essere P{ -> ḷP¥. Potrebbe essere utile aggiungere una composizione (da J) veloce per fare qualcosa del genere x (P+$) y -> (P x) + (P y)che può salvare un byte o due in situazioni simili.
miglia

2

MATLAB con Mapping Toolbox, 26 byte

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

Funzione anonima che accetta i quattro input come un array di celle, nello stesso ordine descritto nella sfida.

Si noti che ciò fornisce risultati esatti (supponendo che il raggio lunare sia di 1737 km), perché è 1737/180uguale 9.65.

Esempio eseguito in Matlab R2017b:

inserisci qui la descrizione dell'immagine


1

Python 3, 79 byte

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

TIO non ha geopy.py


2
@Nit, la mia comprensione è che è giusto usare una libreria disponibile al pubblico che precede la domanda. Penso che sia come usare gli strumenti di mappatura di MATLAB o altre lingue usando una libreria matematica.
Radice Due

1

APL (Dyalog Unicode) , SBCS da 29 byte

Programma completo. Richiede stdin per {ϕ₁, ϕ₂} e quindi per {λ₁, λ₂}. Stampa su stdout.

Usa la formula r acos (sin ϕ₁ sin ϕ₂ + cos (λ₂ - λ₁) cos ϕ₁ cos ϕ₂)

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

Provalo online! (la rfunzione converte i gradi in radianti)


 richiesta {ϕ₁, ϕ₂}

1 2∘.○ Applicazione cartesiana con funzione di innesco; {{sin ϕ₁, sin ϕ₂}, {cos ϕ₁, cos ϕ₂}}

×/ prodotti a righe; {sin ϕ₁ sin ϕ₂, cos ϕ₁ cos ϕ₂}

(...)×@2  al secondo elemento, moltiplicare quanto segue per quello:

 richiesta {λ₁, λ₂}

-/ differenza tra quelli; λ₁ - λ₂

2○ coseno di quello; cos (λ₁ - λ₂)

Ora abbiamo {sin ϕ₁ sin ϕ₂, cos (λ₁ - λ₂) cos ϕ₁ cos ϕ₂}

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

¯2○ coseno di quello; cos (sin ϕ₁ sin ϕ₂ + cos (λ₁ - λ₂) cos ϕ₁ cos ϕ₂)

1737× moltiplicare r per quello; 1737 cos (sin ϕ₁ sin ϕ₂ + cos (λ₁ - λ₂) cos ϕ₁ cos ϕ₂)


La funzione per consentire l'inserimento in gradi è:

○÷∘180

÷180 argomento diviso per 180

 moltiplicare per π


1

C (cc) , 100 88 65 64 byte

88 → 65 usando la formula di @miles
65 → 64 usando la formula di @ Neil

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

Provalo online!


Credo che sia necessario aggiungere due byte per la -lmbandiera del compilatore.
OOBalance,

@OOBalance: la presenza della bandiera non è sempre richiesta. Dipende da come è stato installato il compilatore sul sistema.
jxh

Tutto a posto. Immagino che questo significhi che posso sottrarre due byte a questa mia risposta: codegolf.stackexchange.com/a/161452/79343 Grazie.
OOBalance,

@OOBalance: ha annullato la risposta. Ho anche presentato la mia soluzione.
jxh

Bello. Anche tu hai votato.
OOBalance,

1

Excel, 53 byte

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

Usando la formula di @ Neil. Input in Radianti.


1

Aragosta , 66 byte

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

Utilizza la formula delle miglia, ma l'input è espresso in gradi. Ciò aggiunge un ulteriore passaggio alla conversione in radianti prima di moltiplicare per raggio.




1

SmileBASIC, 60 byte

INPUT X,Y,S,T?1737*ACOS(COS(X-S)+COS(X)*COS(S)*(COS(T-Y)-1))
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.