Aiutami, mi sono perso nell'oceano!


11

introduzione

Oggi sono andato a pescare da solo con la mia canoa, purtroppo mi sono addormentato e il torrente mi ha portato via, ho perso i remi, ora è notte e mi sono perso nell'oceano! Non riesco a vedere la costa, quindi devo essere lontano!

Ho il mio cellulare ma non funziona perché è bagnato dall'acqua salata, non riesco a parlare o ascoltare nulla perché l'altoparlante del microfono e del telefono è rotto, ma posso inviare SMS al mio amico che si trova sulla spiaggia della costa!

Il mio amico ha una torcia molto potente e l'ha sollevata sopra le canne di bambù per mostrarmi la giusta direzione, ma non posso remare perché non ho remi, quindi devo dirgli quanto sono lontano, così da poter mandare qualcuno a Prendimi!

Il mio amico mi ha detto che sta mantenendo la torcia a 11,50 metri sul livello del mare e posso vedere la luce proprio all'orizzonte. Ora ricordo solo dalla scuola che il raggio terrestre dovrebbe essere di 6371 Km a livello del mare, e sono seduto nella mia canoa, quindi puoi presumere che anche i miei occhi siano a livello del mare.

Compito

Dato che le correnti mi muovono momento per momento, il mio amico alza di tanto in tanto la torcia (ora è a 12.30 metri), per favore scrivi un programma completo o una funzione che mi aiuterà a calcolare la distanza dalla posizione del mio amico!

Ecco un diagramma (non in scala):

inserisci qui la descrizione dell'immagine

Il punto arancione etichettato Msono io, il punto rosso etichettato Tè la torcia. La linea verde è la distanza lineare tra MeT

Ingresso

Prendi dallo standard input l'altezza della torcia hin metri al livello del mare, che vedo proprio in cima all'orizzonte, sotto forma di un numero in virgola mobile con precisione di due decimali (con la precisione di 1 centimetro o 0,01 metri), nel intervallo compreso tra 0 e 100 inclusi.

Produzione

Dovresti restituire la lunghezza euclidea della linea verde con la precisione di 1 cm. Ad esempio, se si emette in metri, dovrebbe essere con due decimali (almeno). L'output può essere metri o chilometri, ma rispettando la precisione.

Casi test:

Tutti i valori in metri.

11.5 > 12105.08
13.8 > 13260.45

Regole

Il codice più corto vince.


Il risultato deve essere matematicamente corretto o va bene se i primi 2 decimali sono ok? Voglio dire che hxh è piccolo rispetto a 2xRxh e può essere trascurato per piccole distanze. (R è il raggio della Terra e h è l'altezza della torcia).
Osable,

@ I primi 2 decimali sono accettabili se si emette in metri
Mario

Qual è la gamma di input?
Osable,

@Sable è possibile considerare l'input compreso tra 0 e 100 (anche troppo del necessario / possibile in questo caso).
Mario,

1
Avresti dovuto provare lo scambio di stack della guardia costiera - il codice golferse non può aiutarti a uscire dall'oceano, amico!
corsiKa

Risposte:


4

05AB1E ,13 12 10 byte

Salvato 2 byte grazie a Emigna.

Poiché non vi sono funzioni trigonometriche da chiamare usando l'assunto di OP secondo cui la terra è localmente un piano, diventa possibile realizzare una soluzione 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

Provalo online!


1
12742000può essere scritto come•1#oC•
Emigna il

Per riferimento, sarebbero stati 9 byte: •1#oC•+*tin 2sable
Emigna il

Una stringa circondata con rappresenta un numero ... base 214? 05AB1E soffre talvolta di una mancanza di documentazione su tali funzioni speciali. Bella risposta anche a 2 cifre. L'ho scoperto qualche giorno fa ma non ho pensato di usarlo per questa domanda.
Osable,

Corretta. È un numero di base 10 codificato nella base 214.
Emigna,

Il risultato può essere raggiunto anche dalla trigonometria, ma è probabilmente più lungo.
Mario,

4

Python, 34 26 byte:

( -8 byte grazie a Osable! )

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

Una funzione lambda anonima. Accetta input in chilometri e output in chilometri. Invoke as print(<Function Name>(<Input>)).


lambda i:(i*(i+12742))**.5sarebbe ancora più breve.
Osable,

@Osable Nice! Stavo per farlo. :)
R. Kap,

Se c'è tolleranza matematica, data la discrepanza tra ie 12742, l'espressione può essere abbreviata in questo modo:(i*12742)**.5
Osable

I risultati sono sbagliati 11,5 m -> ~ 380 km invece di ~ 12 km
GB

@IT Il programma legge il suo input come chilometri.
Osable

4

PHP, 34 byte

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

abbattersi

   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

finora, questo è identico alla vecchia risposta di 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

ora tutti i thats resta da fare è aggiungere in ingresso =$argv[1]e in uscita <?=- fatto


4

dc, 16 11 byte:

?d12742+*vp

Richiede l'inserimento tramite la riga di comando in chilometri e quindi la distanza in uscita.

Spiegazione

?           # 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

Questo sfrutta quanto segue:

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

(12742e3+.)*.|sqrt

Ancora un'altra copia della stessa formula.

Esecuzione di esempio:

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

Test online


4

Haskell, 22 byte

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

Uso:

Prelude> d 11.5
12105.087040166212

Pointfree: (23 byte)

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

3

R, 29 byte

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

Riceve input dallo stdin


Un paio di byte è più corto (h=scan())*(1+12742e3/h)^.5.
Flounderer,

2

Mathematica, 16 byte

Ognuna di queste funziona sia per input che per output in chilometri:

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

Questa è una semplice applicazione di Pitagora 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 byte nella codepage di Jelly

Ho deciso di provare a scrivere il programma in una lingua da golf. In realtà ho trovato un algoritmo più efficiente di quello che stanno usando le altre persone (almeno su brevi distanze come quello nella domanda), ma richiede numeri letterali in virgola mobile che Jelly non sembra essere in grado di comprimere, quindi Pitagora è.

+“Ȯịż’×µ½

Spiegazione:

 “Ȯịż’     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 necessità del µseparatore mi irrita, ma penso che sia inevitabile; Jelly ha già salvato un byte su 05AB1E grazie alla possibilità di indovinare quali argomenti richiedono molti comandi, ma in questo caso non può indovinare correttamente fino alla fine, quindi ho dovuto dargli un suggerimento.

Jelly, 7 byte nella codepage di Jelly

דȮịż’½

Come ho spiegato nella mia altra risposta , l'approssimazione di serie all'approssimazione di Pitagora produce effettivamente risultati migliori sulle lunghezze incluse nella domanda (almeno, sono più vicine agli output di esempio) e ha anche una formula più breve. Mentre lo stavo scrivendo, mi sono reso conto che invece di calcolare in anticipo la radice quadrata di 12742000, ho potuto moltiplicare prima il numero per 12742000 e poi la radice quadrata entrambi contemporaneamente. Questo è sostanzialmente equivalente all'altra formula senza aggiunta e, come tale, può essere prodotto dal programma precedente rimuovendo l'aggiunta da esso. Ciò consente di risparmiare due byte, poiché ora analizza in modo inequivocabile e quindi non abbiamo più bisogno di uno µ.


Ho deciso di non utilizzare questa ottimizzazione perché non produce gli stessi valori se si guardano i centimetri (vedi output richiesto) dato l'intervallo di h. Inoltre salverebbe 2 byte in 05AB1E.
Osable,

Con l'ottimizzazione, ottengo output di 12105.081577585506 e 13260.452480967608; quelli sono molto vicini all'output del test case e arrotondati a loro. Senza, ottengo 12105.087040166212 e 13260.459661716106, che sono più lontani (e quest'ultimo non è corretto nei centimetri, arrotondando a 13260.46). Come menzionato nell'altra risposta, l'ottimizzazione sembra essere più vicina al valore corretto rispetto al codice ottimizzato perché contiene due errori che si annullano a vicenda, piuttosto che uno che non ha nulla per annullarlo.

Dato che hai appena votato "Lascia aperto" nella coda delle recensioni, presumo che tu creda di conoscere le risposte alle domande per le quali ho richiesto chiarimenti nei commenti. Si prega quindi di modificare la domanda in modo che sia inequivocabile.
Peter Taylor,

1
La domanda non è ambigua: l'autore deve conoscere la distanza dal suo amico per aiutare a navigare. Può determinare la posizione della torcia con un'accuratezza di 0,1 metri (possiamo determinarlo dalla storia che è stata raccontata). Ciò produrrà inevitabilmente circa 1 metro di incertezza dall'output alla distanza corrente (nota: l'autore sta andando alla deriva, quindi è improbabile che si muova molto molto molto rapidamente ...), e quindi è probabile che tutto ciò che è approssimativamente così accurato sia accettabile. Parte del problema è determinare quanto preciso dovresti essere in questa situazione!

1
L'output richiesto mostra 2 decimali in metri. Quindi la precisione dovrebbe essere di 1 centimetro. Nei commenti alla domanda, OP ha affermato che h potrebbe arrivare a 100. Con h = 100 c'è una discrepanza di 14 centimetri dall'algoritmo originale.
Osable,

2

Ruby, 23 anni

23 byte, in Km

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

25 byte, in m

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

1

Tcl, 49 byte:

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

Bene, sono nuovo di zecca per Tcl, quindi ogni consiglio per giocare a golf è molto apprezzato. Come le altre mie risposte, richiede input da riga di comando in chilometri e output in chilometri. Essenzialmente un adattamento Tcl del mio esistente dce delle pythonrisposte.


v'è una s mancanti su get s
sergiol

1

x86_64 + codice macchina SSE, 16 byte

I byte del programma sono a sinistra (in esadecimali), c'è uno smontaggio a destra per rendere un po 'più facile la lettura. Questa è una funzione che segue la normale convenzione x86_64 per le funzioni che accettano e restituiscono un numero in virgola mobile a precisione singola (prende l'argomento in% xmm0 e restituisce la sua risposta nello stesso registro, e usa% xmm1 e% eax come provvisori; questi sono le stesse convenzioni di chiamata che verrà utilizzato da un programma C, pertanto puoi chiamare la funzione direttamente da un programma C, ed è così che l'ho testato).

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

Anche con uno smontaggio, tuttavia, ciò richiede ancora una spiegazione. Innanzitutto, vale la pena discutere della formula. Molte persone ignorano la curvatura della terra e usano la formula di Pitagora per misurare la distanza. Lo sto facendo anch'io, ma sto usando un'approssimazione dell'espansione in serie; Prendo solo il termine relativo al primo potere dell'input e ignoro i poteri terzo, quinto, settimo, ecc., Che tutti hanno solo un'influenza molto piccola a questa breve distanza. (Inoltre, l'approssimazione di Pitagora dà un valore basso, mentre i termini successivi nell'espansione della serie servono a ridurre il valore; come tale, ignorando un fattore minore che servirebbe a spingere l'approssimazione nella direzione sbagliata, in realtà capita di ottenere un risultato più accurato utilizzando una formula meno accurata.) La formula risulta essere √12742000 × √h;0x455f1980.

La prossima cosa che potrebbe confondere le persone è perché sto usando le istruzioni vettoriali per la radice quadrata e il moltiplicare; %xmm0e %xmm1posso contenere quattro numeri in virgola mobile a precisione singola ciascuno e sto operando su tutti e quattro. Il ragionamento qui è davvero semplice: la loro codifica è più corta di un byte rispetto a quella delle corrispondenti istruzioni scalari. Quindi posso fare in modo che l'FPU faccia un sacco di lavoro extra di rooting quadrato e moltiplicando zero per salvarmi due byte, in un metodo che ricorda molto il tipico algoritmo del linguaggio del golf. (Ho chiamato x86 assembler il linguaggio golfistico degli assemblatori in chat qualche tempo fa, e non ho ancora cambiato idea su questo.)

Da lì, l'algoritmo è molto semplice: carica %xmm1con √12742000 via %eax(che è più breve in termini di byte che caricarlo dalla memoria sarebbe), radice quadrata dell'argomento (e tre zero), moltiplica gli elementi corrispondenti di %xmm1e %xmm0(ci interessa solo sul primo elemento), quindi torna.


1

Minkolang v0.15, 22 byte

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

Provalo online!

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 byte

Visualizza il valore in metri

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


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

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.