Distancia entre dos puntos en la luna

11

Dada la latitud / longitud de dos puntos en la Luna (lat1, lon1)y (lat2, lon2), calcule la distancia entre los dos puntos en kilómetros, usando cualquier fórmula que dé el mismo resultado que la fórmula de Haversine.

Entrada

  • Cuatro valores enteros lat1, lon1, lat2, lon2en grados (ángulo) o
  • cuatro valores decimales ϕ1, λ1, ϕ2, λ2en radianes.

Salida

Distancia en kilómetros entre los dos puntos (decimal con cualquier precisión o número entero redondeado).

Fórmula de 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)

dónde

  • r es el radio de la esfera (suponga que el radio de la Luna es de 1737 km),
  • ϕ1 latitud del punto 1 en radianes
  • ϕ2 latitud del punto 2 en radianes
  • λ1 longitud del punto 1 en radianes
  • λ2 longitud del punto 2 en radianes
  • d es la distancia circular entre los dos puntos

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

Otras posibles fórmulas

Ejemplo donde las entradas son grados y la salida como entero redondeado

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

Reglas

  • La entrada y la salida se pueden dar en cualquier formato conveniente .
  • Especifique en la respuesta si las entradas están en grados o radianes .
  • No es necesario manejar valores de latitud / longitud no válidos
  • Un programa completo o una función son aceptables. Si es una función, puede devolver el resultado en lugar de imprimirlo.
  • Si es posible, incluya un enlace a un entorno de prueba en línea para que otras personas puedan probar su código.
  • Las lagunas estándar están prohibidas.
  • Este es el por lo que se aplican todas las reglas habituales de golf, y gana el código más corto (en bytes).
mdahmoune
fuente
77
Usar esa fórmula particular es un requisito no observable. ¿No es suficiente dar el mismo resultado que daría esa fórmula ?
Adám
1
¿Podemos tomar la entrada en radianes?
Adám
1
@mdahmoune OK, por lo que indicó en grados para facilitar la escritura, pero puede que requieran la intervención de estar en radianes? De lo contrario, este desafío se convierte en un combo (que es malo) de conversión de ángulo y del desafío principal.
Adám
55
He rechazado esta pregunta porque parece más bien "¿Quién es el idioma que puede jugar más esta fórmula?", Lo que, en mi opinión, no es particularmente interesante.
caird coinheringaahing
2
Una fórmula más corta para la mayoría de los idiomas sería d = r * acos( sin ϕ1 sin ϕ2 + cos ϕ1 cos ϕ2 cos(λ2 - λ1) )donder = 1737
millas

Respuestas:

6

R + geosfera , 54 47 bytes

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

Pruébalo en línea!

Toma la entrada como vectores de 2 elementos longitude,latitudeen grados. TIO no tiene el geospherepaquete, pero puede estar seguro de que devuelve resultados idénticos a la función a continuación.

Gracias a Jonathan Allan por reducir 7 bytes.

R , 64 bytes

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

Pruébalo en línea!

Toma 4 entradas como en los casos de prueba, pero en radianes en lugar de grados.

Giuseppe
fuente
¿Son los e3y /1000realmente necesarios?
Jonathan Allan
1
@JonathanAllan no, no lo son. Eso es bastante tonto de mi parte, pero el argumento predeterminado para el radio es la tierra en metros, por lo que era lógico en ese momento, jajaja
Giuseppe
Tenga en cuenta que la ley esférica de cosenos no es numéricamente estable, en particular para distancias pequeñas. Probablemente esté bien en Mathematica , pero en R y en la mayoría de los otros lenguajes es discutible si se cumple el criterio de "cualquier fórmula que dé el mismo resultado que la fórmula de Haversine".
dejó de girar en contra del reloj el
@ceasedtoturncounterclockwis La incluí principalmente para tenerla en la base R. Supongo que usar una biblioteca de punto flotante de precisión arbitraria mitigaría el efecto.
Giuseppe
Sí, o usando una fórmula estable como, por ejemplo, la fórmula de Haversine ...
dejó de girar en sentido antihorario el
5

JavaScript (Node.js) , 65 bytes

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

Pruébalo en línea!

Basado en la respuesta de Kevin Cruijssen, los comentarios de Miles y Neil, y a pedido de Arnauld.

Olivier Grégoire
fuente
5

JavaScript (ES7), 90 bytes

Nota: vea la publicación de @ OlivierGrégoire para una solución mucho más corta

Un puerto directo de la respuesta de TFeld . Toma entrada en radianes.

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

Pruébalo en línea!

Usando el infame with(), 85 bytes

Gracias a @ l4m2 por guardar 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)

Pruébalo en línea!

Arnauld
fuente
2
Puede hacerlowith(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 usando el algoritmo más corto 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 bytes usando el algoritmo más corto 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 bytes optimizando la respuesta de todos:(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 Muy bien. Probablemente deberías publicarlo como una nueva respuesta.
Arnauld
5

APL (Dyalog Unicode) , 40 35 bytes SBCS

Función tácita anónima. Toma {ϕ₁, λ₁} como argumento izquierdo y {ϕ₂, λ₂} como argumento derecho.

Utiliza la fórmula 2 r √ (sin² ( (ϕ₁-ϕ₂)2 ) + cos ϕ₁ cos ϕ₂ sin² ( (λ₁ - λ₂)2 ))

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

Pruébalo en línea! (la rfunción convierte grados a radianes)


 concatenar elementos correspondientes; {{ϕ₁, ϕ₂}, {λ₁, λ₂}}

 escoge el primero; {ϕ₁, ϕ₂}

 entonces

2×.○ producto de sus cosenos; cos ϕ₁ cos ϕ₂
encendido. punto "producto" pero con selector de función trigonométrica (2 es coseno) en lugar de multiplicación y tiempos en lugar de más

1, anteponer 1 a eso; {1, cos ϕ₁ cos ϕ₂}

( Multiplique eso por el resultado de aplicar la siguiente función a {ϕ₁, λ₁} y {ϕ₂, λ₂}:

- sus diferencias {ϕ₁ - ϕ₂, λ₁ - λ₂}

2÷⍨ dividir eso por 2; { (ϕ₁ - ϕ₂)2 , (λ₁ - λ₂)2 }

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

×⍨ cuadrado que (lit. auto-multiplicar); {sin² ( (ϕ₁ - ϕ₂)2 ), sin² ( (λ₁-λ₂)2 )}

Ahora tenemos {sin² ( (ϕ₁ - ϕ₂)2 ), cos ϕ₁ cos ϕ₂ sin² ( (λ₁ - λ₂)2 )}

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

.5*⍨ raíz cuadrada de eso (literalmente, eleva eso a la potencia de la mitad)

¯1○ arcoseno de eso

3474× multiplica eso por esto


La función para permitir la entrada en grados es:

○÷∘180

÷180 argumento dividido por 180

 multiplicar por π

Adán
fuente
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*

Pruébalo en línea!

Toma entrada en radianes.


Versión anterior, antes de que la E / S se aflojara: toma la entrada como grados enteros y devuelve dist redondeado

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

Pruébalo en línea!

TFeld
fuente
puede soltar inty rounddado que los decimales están permitidos como salida, también puede evitar la conversión a radianes porque las entradas como radianes también están permitidas
mdahmoune
@mdahmoune, gracias, actualizado
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))

Las entradas a,b,c,destán ϕ1,λ1,ϕ2,λ2en radianes.

-21 bytes usando la fórmula más corta de @miles .
-4 bytes gracias a @ OlivierGrégore porque todavía lo usaba {Math m=null;return ...;}con cada Math.as m., en lugar de soltarlo returny usarlo Mathdirectamente.
-6 bytes usando la fórmula más corta de @Neil .

Pruébalo en línea.

Explicación:

(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
fuente
1
"La optimización temprana es la raíz de todo mal"! 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
" La optimización prematura es la raíz de todo mal " Supongo que tienes razón ... ¡Gracias!
Kevin Cruijssen
1
He encontrado una formulación más corta:(a,b,c,d)->1737*Math.acos(Math.cos(a-c)+Math.cos(a)*Math.cos(c)*(Math.cos(d-b)-1))
Neil
(Sin embargo, esa formulación no es más corta en el Wolfram Language original).
Neil
3

Japt , 55 50 bytes

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

No necesariamente tan precisa como las otras respuestas, pero vaya si me divertí con esta. Permíteme elaborar.
Si bien en la mayoría de los idiomas, este desafío es bastante sencillo, Japt tiene la desafortunada propiedad de que no hay arcoseno ni arcosina incorporados. Claro, puedes incrustar Javascript en Japt, pero eso sería lo opuesto a Feng Shui.

¡Todo lo que tenemos que hacer para superar esta pequeña molestia es el arcocoseno aproximado y estamos listos para comenzar!

La primera parte es todo lo que se introduce en el arcocoseno.

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.

El resultado se almacena implícitamente Upara su uso posterior.

Después de eso, necesitamos encontrar una buena aproximación para el arcocoseno. Como soy flojo y no soy tan bueno con las matemáticas, obviamente solo lo vamos a forzar.

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.

Podríamos haber usado cualquier número grande para la resolución del generador, las pruebas manuales mostraron que 7!es lo suficientemente grande y razonablemente rápido.

Toma la entrada como radianes, emite números sin redondear.

Afeitado cinco bytes gracias a Oliver .

Pruébalo en línea!

Liendre
fuente
Se puede quitar el (en Mc(X-V. Dado que el código char para 1737no es ISO-8859-1, cambia a UTF-8, que cuesta más. En su lugar, puede usar el código char para 173+ 7. ethproductions.github.io/japt/?v=1.4.5&code=I603&input=
Oliver
También puede eliminar el ,después ToMP:-)
Oliver
@Oliver Muchas gracias, los paréntesis eran necesarios en mi versión original, pero se volvieron obsoletos al jugar un poco al golf, aunque me lo perdí por completo. Además, no sabía sobre la codificación, muchas gracias por eso también.
Nit
1
Si desea seguir la ruta de JavaScript, tenga en cuenta que puede ejecutar todo a través de shoco.
Oliver
2

Jalea ,  23 22  18 bytes

-4 bytes gracias a millas (uso de {y }mientras se usa su fórmula .

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

Una función diádica que acepta [ϕ1, ϕ2,]a la izquierda y [λ1, λ2]a la derecha en radianes que devuelve el resultado (como punto flotante).

Pruébalo en línea!


Mine ... (también guardé un byte aquí usando a {)

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

Pruébalo en línea

Jonathan Allan
fuente
Es interesante, actualicé la página nuevamente y mostró su edición, solo haciendo clic en nueva respuesta para mostrar que el cambio no se actualiza para mostrar sus ediciones. la alternativa de 18 bytes era;I}ÆẠP+ÆSP${ÆA×⁽£ġ
millas del
Nunca entendí cómo usar {y }nunca hacen lo que yo esperaba. ¿No significa eso que puedo hacer lo contrario en 17?
Jonathan Allan
Tal vez. {y }solo crea una diada a partir de una mónada. Una opinión similar podría ser P{ -> ḷP¥. Podría ser bueno agregar una composición (de J) rápidamente para hacer algo como lo x (P+$) y -> (P x) + (P y)que puede guardar un byte o dos en situaciones similares.
millas
2

MATLAB con Mapping Toolbox, 26 bytes

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

Función anónima que toma las cuatro entradas como una matriz de celdas, en el mismo orden que se describe en el desafío.

Tenga en cuenta que esto da resultados exactos (suponiendo que el radio de la Luna es de 1737 km), porque 1737/180es igual 9.65.

Ejemplo ejecutado en Matlab R2017b:

ingrese la descripción de la imagen aquí

Luis Mendo
fuente
1

Python 3, 79 bytes

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

TIO no tiene geopy.py

RootTwo
fuente
2
@Nit, entiendo que es un juego justo usar una biblioteca pública que sea anterior a la pregunta. Creo que es como usar las herramientas de mapeo de MATLAB u otros idiomas usando una biblioteca matemática.
RootTwo
1

APL (Dyalog Unicode) , SBCS de 29 bytes

Programa completo Solicita stdin para {ϕ₁, ϕ₂} y luego para {λ₁, λ₂}. Imprime en stdout.

Utiliza la fórmula r acos (sin ϕ₁ sin ϕ₂ + cos (λ₂ - λ₁) cos ϕ₁ cos ϕ₂)

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

Pruébalo en línea! (la rfunción convierte grados a radianes)


 solicitud de {ϕ₁, ϕ₂}

1 2∘.○ Aplicación de función trigonométrica cartesiana; {{sin ϕ₁, sin ϕ₂}, {cos ϕ₁, cos ϕ₂}}

×/ productos en hileras; {sin ϕ₁ sin ϕ₂, cos ϕ₁ cos ϕ₂}

(... )×@2 en el segundo elemento, multiplique lo siguiente por eso:

 solicitud de {λ₁, λ₂}

-/ diferencia entre esos; λ₁ - λ₂

2○ coseno de eso; cos (λ₁ - λ₂)

Ahora tenemos {sin ϕ₁ sin ϕ₂, cos (λ₁ - λ₂) cos ϕ₁ cos ϕ₂}

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

¯2○ coseno de eso; cos (sin ϕ₁ sin ϕ₂ + cos (λ₁ - λ₂) cos ϕ₁ cos ϕ₂)

1737× multiplicar r por eso; 1737 cos (sin ϕ₁ sin ϕ₂ + cos (λ₁ - λ₂) cos ϕ₁ cos ϕ₂)


La función para permitir la entrada en grados es:

○÷∘180

÷180 argumento dividido por 180

 multiplicar por π

Adán
fuente
1

C (gcc) , 100 88 65 64 bytes

88 → 65 usando la fórmula de @miles '65
→ 64 usando la fórmula de @ Neil

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

Pruébalo en línea!

jxh
fuente
Creo que necesita agregar dos bytes para el -lmindicador del compilador.
OOBalance
@OOBalance: la presencia de la bandera no siempre es necesaria. Depende de cómo se instaló el compilador en el sistema.
jxh
Bien. Supongo que esto significa que puedo restar dos bytes en esta respuesta mía: codegolf.stackexchange.com/a/161452/79343 Gracias.
OOBalance
@OOBalance: Votó la respuesta. También presenté mi propia solución.
jxh
Agradable. Votaron el suyo también.
OOBalance
1

Excel, 53 bytes

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

Usando la fórmula de @ Neil. Entrada en radianes.

Wernisch
fuente
1

Langosta , 66 bytes

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

Utiliza la fórmula de millas, pero la entrada está en grados. Esto agrega un paso adicional de conversión a radianes antes de multiplicar por radio.

Panda0nEarth
fuente
1

PHP , 88 bytes

Puerto de Oliver respuesta

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

Pruébalo en línea!

Luis felipe De jesus Munoz
fuente
1

SmileBASIC, 60 bytes

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