¡Ayúdame, estoy perdido en el océano!


11

Introducción

Hoy fui a pescar solo con mi canoa, desafortunadamente me quedé dormido y el arroyo me llevó, perdí mis remos, ¡ahora es de noche y estoy perdido en el océano! ¡No puedo ver la costa, así que debo estar muy lejos!

Tengo mi teléfono celular pero no funciona bien porque el agua salada lo mojó, no puedo hablar ni escuchar nada porque el micrófono y el altavoz del teléfono están rotos, ¡pero puedo enviarle SMS a mi amigo que está en la playa de la costa!

Mi amigo tiene una antorcha muy poderosa y la levantó sobre los bastones de bambú para mostrarme la dirección correcta, pero no puedo remar porque no tengo remos, así que debo decirle qué tan lejos estoy para que pueda enviar a alguien a ¡Atrápame!

Mi amigo me dijo que mantiene la antorcha a 11,50 metros sobre el nivel del mar, y puedo ver la luz sobre el horizonte. Ahora solo recuerdo de la escuela que el radio de la Tierra debería ser de 6371 km al nivel del mar, y estoy sentado en mi canoa para que puedan asumir que mis ojos también están al nivel del mar.

Tarea

Dado que las corrientes me están moviendo momento a momento, mi amigo está levantando la antorcha de vez en cuando (ahora está a 12.30 metros), ¡por favor escriba un programa completo o una función que me ayude a calcular la distancia desde la posición de mi amigo!

Aquí hay un diagrama (no a escala):

ingrese la descripción de la imagen aquí

El punto naranja etiquetado Msoy yo, el punto rojo etiquetado Tes la antorcha. La línea verde es la distancia lineal entre MyT

Entrada

Tome de entrada estándar la altura de la antorcha hen metros al nivel del mar, que veo justo encima del horizonte, en forma de un número de coma flotante con dos decimales de precisión (con la precisión de 1 centímetro o 0.01 metros), en el rango de 0 a 100 incluidos.

Salida

Debe devolver la longitud euclidiana de la línea verde con una precisión de 1 cm. Por ejemplo, si la salida en metros, debe ser con dos decimales (al menos). La salida puede ser metros o kilómetros, pero respetando la precisión.

Casos de prueba:

Todos los valores en metros.

11.5 > 12105.08
13.8 > 13260.45

Reglas

El código más corto gana.


¿El resultado tiene que ser matemáticamente correcto o está bien si los primeros 2 decimales están bien? Quiero decir que hxh es pequeño en comparación con 2xRxh y puede descuidarse para distancias pequeñas. (R es el radio de la Tierra yh es la altura de la antorcha).
Osable

@Osable los primeros 2 decimales están bien si imprime en metros
Mario

¿Cuál es el rango de entrada?
Osable

@Osable puede considerar que la entrada es de 0 a 100 (incluso demasiado de lo necesario / posible en este caso).
Mario

1
Deberías haber intentado el intercambio de la Guardia Costera: ¡el código golfista no puede ayudarte a salir del océano, hombre!
corsiKa

Respuestas:


4

05AB1E ,13 12 10 bytes

Guardado 2 bytes gracias a Emigna.

Dado que no hay funciones trigonométricas que se invoquen utilizando el supuesto de OP de que la Tierra es localmente un plano, es posible hacer una solución 05AB1E.

•1#oC•+¹*t

           For understanding purposes input is referred to as 'h'
•1#oC•     Push 12742000 [ = 2*R, where R is the radius of earth]
      +    Compute 2*R+h
       ¹*  Multiply by h. Result is (2*R*+h)*h
         t Take the square root of it and implicitly display it

Pruébalo en línea!


1
12742000se puede escribir como•1#oC•
Emigna

Como referencia, habría sido de 9 bytes: •1#oC•+*ten 2sable
Emigna

¿Una cadena rodeada con representa un ... número 214 base? 05AB1E sufre una falta de documentación sobre tales funciones especiales a veces. Buena respuesta 2sable también. Lo descubrí hace unos días, pero no pensé en usarlo para esta pregunta.
Osable

Correcto. Es un número de base 10 codificado en base 214.
Emigna

El resultado también se puede lograr mediante trigonometría, pero probablemente sea más largo.
Mario

4

Python, 34 26 bytes:

( -8 bytes gracias a Osable! )

lambda i:(i*(i+12742))**.5

Una función lambda anónima. Toma entrada en kilómetros y salidas en kilómetros. Invocar como print(<Function Name>(<Input>)).


lambda i:(i*(i+12742))**.5Sería aún más corto.
Osable

@Osable Nice! Estaba a punto de hacer eso. :)
R. Kap

Si hay tolerancia matemática, dada la discrepancia entre iy 12742, la expresión se puede acortar así:(i*12742)**.5
Osable el

Los resultados están mal. 11.5m -> ~ 380km en lugar de ~ 12km
GB

@GB El programa lee su entrada como kilómetros.
Osable el

4

PHP, 34 bytes

<?=sqrt((12742e3+$h=$argv[1])*$h);

Descompostura

   r^2+x^2=(r+h)^2      # Pythagoras base
   r^2+x^2=r^2+2rh+h^2  # right term distributed
       x^2=    2rh+h^2  # -r^2
       x =sqrt(2rh+h^2) # sqrt

Hasta ahora, esto es idéntico a la vieja respuesta de Mathematica

sqrt(2*6371e3*$h+$h*$h) # to PHP
sqrt(14742e3*$h+$h+$h)  # constants combined
sqrt((14742e3+$h)*$h)   # conjugation to save a byte
((14742e3+$h)*$h)**.5   # same size

ahora todo lo que queda por hacer es agregar entrada =$argv[1]y salida <?=- hecho


4

dc, 16 11 bytes:

?d12742+*vp

Solicita la entrada a través de la línea de comando en kilómetros y luego la distancia de salida en kilómetros.

Explicación

?           # Prompt for input
 d          # Duplicate the top-of-stack value
  12742     # Push 12,742 onto the stack
       +    # Pop the top 2 values of the stack and push their sum
        *   # Pop top 2 values of the stack and push their product
         v  # Pop the remaining value and push the square root
          p # Output the result to STDOUT

Esto aprovecha lo siguiente:

((6371+h)**2-6371**2)**.5 
=> ((6371**2+12742h+h**2)-6371**2)**0.5 
=> (h**2+12742h)**0.5 
=> (h*(h+12742))**0.5

4

jq, 18 caracteres

(12742e3+.)*.|sqrt

Otra copia más de la misma fórmula.

Ejecución de muestra:

bash-4.3$ jq '(12742e3+.)*.|sqrt' <<< 11.5
12105.087040166212

Prueba en línea


4

Haskell, 22 bytes

d h=sqrt$h*(h+12742e3)

Uso:

Prelude> d 11.5
12105.087040166212

Punto libre: (23 bytes)

sqrt.((*)=<<(+12742e3))

3

R, 29 bytes

h=scan();sqrt(h^2+2*h*6371e3)

Toma entrada de stdin


Un par de bytes más corto es (h=scan())*(1+12742e3/h)^.5.
Flounderer

2

Mathematica, 16 bytes

Cualquiera de estos funciona tanto para la entrada como para la salida en kilómetros:

(12742#+#*#)^.5&
((12742+#)#)^.5&

Esta es una aplicación simple de Pitágoras al problema:

   x*x + R*R = (R+h)*(R+h)
=> x*x = (R+h)*(R+h) - R*R
       = R*R + 2*R*h + h*h - R*R
       = 2*R*h + h*h
=>   x = √(2*R*h + h*h)

2

Jelly, 9 bytes en la página de códigos de Jelly

Decidí intentar escribir el programa en un idioma de golf. De hecho, encontré un algoritmo más eficiente que el que usan otras personas (al menos en distancias cortas como el de la pregunta), pero requiere números literales de punto flotante que Jelly no parece ser capaz de comprimir, por lo que Pitágoras está.

+“Ȯịż’×µ½

Explicación:

 “Ȯịż’     12742000, compressed base-250
+          add to argument
      ×    multiply with original argument
       µ   separator to avoid what would otherwise be a parsing ambiguity
        ½  square root everything seen so far
           implicit output at EOF

La necesidad del µseparador me irrita, pero creo que es inevitable; Jelly ya ha guardado un byte sobre 05AB1E al poder adivinar qué argumentos necesitan muchos de los comandos, pero en este caso no puede adivinar correctamente hasta el final, por lo que necesitaba darle una pista.

Jelly, 7 bytes en la página de códigos de Jelly

דȮịż’½

Como expliqué en mi otra respuesta , la aproximación en serie a la aproximación de Pitágoras en realidad produce mejores resultados sobre las longitudes incluidas en la pregunta (al menos, están más cerca de los resultados del ejemplo), y también tiene una fórmula más corta. Mientras lo escribía, me di cuenta de que, en lugar de calcular la raíz cuadrada de 12742000 por adelantado, podría multiplicar primero el número por 12742000, y luego la raíz cuadrada ambas al mismo tiempo. Esto es básicamente equivalente a la otra fórmula sin la adición, y como tal, se puede producir a partir del programa anterior eliminando la adición. Esto ahorra dos bytes, ya que ahora se analiza sin ambigüedades y, por lo tanto, ya no necesitamos uno µ.


Decidí no usar esta optimización porque no produce los mismos valores si nos fijamos en los centímetros (cf. salida solicitada) dado el rango de h. También ahorraría 2 bytes en 05AB1E.
Osable el

Con la optimización, obtengo salidas de 12105.081577585506 y 13260.452480967608; estos están muy cerca de la salida del caso de prueba, y redondeados a ellos Sin, obtengo 12105.087040166212 y 13260.459661716106, que están más lejos (y este último es incorrecto en centímetros, redondeando a 13260.46). Como se mencionó en la otra respuesta, la optimización está más cerca del valor correcto que el código optimizado porque contiene dos errores que se cancelan en gran medida entre sí, en lugar de solo uno que no tiene nada para cancelarlo.

Como acaba de votar por "Dejar abierto" en la cola de revisión, supongo que cree que conoce las respuestas a las preguntas para las que solicité aclaraciones en los comentarios. Por lo tanto, edite la pregunta para que no sea ambigua.
Peter Taylor el

1
La pregunta es inequívoca: el autor necesita saber la distancia a su amigo para ayudarlo a navegar. Puede determinar la posición de la antorcha con una precisión de 0.1 metros (podemos determinar esto a partir de la historia que se cuenta). Esto inevitablemente generará aproximadamente 1 metro de incertidumbre de la salida a la distancia actual (nota: el autor se está desviando, por lo tanto, es poco probable que se mueva muy lejos muy rápidamente ...), y por lo tanto, es probable que cualquier cosa que sea tan precisa aceptable. ¡Parte del problema es determinar qué tan preciso necesitarías ser en esta situación!

1
La salida solicitada muestra 2 decimales en metros. Por lo tanto, se espera que la precisión sea de 1 centímetro. En los comentarios a la pregunta, OP dijo que h podría llegar a 100. Con h = 100 hay una discrepancia de 14 centímetros con respecto al algoritmo original.
Osable el

2

Ruby, 23

23 bytes, en km

->h{(h*h+h*12742)**0.5}

25 bytes, en m

->h{(h*h+h*12742e3)**0.5}

1

Tcl, 49 bytes:

set A [get stdin];puts [expr ($A*($A+12742))**.5]

Bueno, soy nuevo en Tcl, por lo que cualquier consejo para jugar golf es muy apreciado. Al igual que mis otras respuestas, solicita la entrada de la línea de comandos en kilómetros y las salidas en kilómetros. Esencialmente una adaptación Tcl de mi existente dcy pythonrespuestas.


falta un s en get s
sergiol

1

x86_64 + código de máquina SSE, 16 bytes

Los bytes del programa están a la izquierda (en hexadecimal), hay un desmontaje a la derecha para que sea un poco más fácil de leer. Esta es una función que sigue la convención normal x86_64 para funciones que toman y devuelven un número de coma flotante de precisión simple (toma el argumento en% xmm0 y devuelve su respuesta en el mismo registro, y usa% xmm1 y% eax como temporales; estos son las mismas convenciones de llamada que usará un programa en C y, como tal, puede llamar a la función directamente desde un programa en C, que es como lo probé).

b8 80 19 5f 45          mov    $0x455f1980,%eax
66 0f 6e c8             movd   %eax,%xmm1
0f 51 c0                sqrtps %xmm0,%xmm0
0f 59 c1                mulps  %xmm1,%xmm0
c3                      retq

Sin embargo, incluso con un desmontaje, esto todavía necesita una explicación. Primero, vale la pena discutir la fórmula. La mayoría de las personas ignoran la curvatura de la tierra y utilizan la fórmula de Pitágoras para medir la distancia. Lo estoy haciendo también, pero estoy usando una aproximación de expansión en serie; Solo estoy tomando el término relacionado con la primera potencia de la entrada, e ignorando las potencias tercera, quinta, séptima, etc., que tienen una influencia muy pequeña a esta corta distancia. (Además, la aproximación de Pitágoras da un valor bajo, mientras que los términos posteriores en la expansión de la serie sirven para reducir el valor; como tal, al ignorar un factor menor que serviría para empujar la aproximación en la dirección incorrecta, en realidad me sale un resultado más preciso mediante el uso de una fórmula menos precisa.) La fórmula resulta ser √12742000 × √h;0x455f1980.

Lo siguiente que podría confundir a las personas es por qué estoy usando instrucciones vectoriales para la raíz cuadrada y la multiplicación; %xmm0y %xmm1puede contener cuatro números de punto flotante de precisión simple cada uno, y estoy operando en los cuatro. El razonamiento aquí es realmente simple: su codificación es un byte más corta que la de las instrucciones escalares correspondientes. Entonces puedo hacer que la FPU haga un montón de trabajo extra de enraizamiento cuadrado y multiplicación de ceros para ahorrarme dos bytes, en un método que recuerda mucho al típico algoritmo de lenguaje de golf. (Llamé a x86 assembler el lenguaje de golf de los ensambladores en el chat hace un tiempo, y todavía no he cambiado de opinión al respecto).

A partir de ahí, el algoritmo es muy simple: cargar %xmm1con √12742000 vía %eax(que es más corto en términos de bytes de lo que sería cargarlo desde la memoria), raíz cuadrada del argumento (y tres ceros), multiplicar los elementos correspondientes de %xmm1y %xmm0(solo nos importa sobre el primer elemento), luego regrese.


1

Minkolang v0.15, 22 bytes

ndd*$r'12742000'*+1MN.

Pruébalo en línea!

n                               gets input in the form of a number
 dd                             duplicates it twice
   *                            multiplies 2 of the duplicates with each other
                                STACK: [h, h*h]
    $r                          swap top two stack values
                                STACK: [h*h, h]
      '12742000'*               push this number and multiply the original input by it
                                STACK: [h*h, h*12742000]
                 +1M            adds the two values and takes their square root
                                STACK: [sqrt(h*h+h*12742000)]
                    N.          output as a number and end program

1

JavaScript (ES6), 31 25 bytes

Muestra el valor en metros.

//the actual code 
f=h=>(h*h+12742e3*h)**0.5


console.log(f(11.5));
console.log(f(13.8));

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.