Ajude-me, estou perdido no oceano!

11

Introdução

Hoje fui pescar sozinho com minha canoa, infelizmente adormeci e o riacho me levou embora, perdi meus remos, agora é noite e estou perdido no oceano! Não posso ver a costa, então devo estar longe!

Eu tenho meu telefone celular, mas está com defeito porque ficou molhado pela água salgada, não consigo falar ou ouvir nada porque o alto-falante do microfone e do telefone está quebrado, mas posso enviar SMS para meu amigo que está na praia!

Meu amigo tem uma lanterna muito poderosa e a ergueu em cima dos bastões de bambu para me mostrar a direção certa, mas não consigo remar porque não tenho remos, então devo dizer a ele a que distância estou para que ele possa enviar alguém para pegue-me!

Meu amigo me disse que ele mantinha a tocha a 11,50 metros no nível do mar, e eu posso ver a luz bem no horizonte. Agora só lembro da escola que o raio da Terra deveria estar a 6371 km ao nível do mar e estou sentado na minha canoa para que você possa assumir que meus olhos também estão no nível do mar.

Tarefa

Como as correntes estão me movendo momento a momento, meu amigo está levantando a tocha de tempos em tempos (agora a 12,30 metros), por favor, escreva um programa completo ou função que me ajudará a calcular a distância da posição do meu amigo!

Aqui está um diagrama (sem escala):

insira a descrição da imagem aqui

O ponto laranja rotulado Msou eu, o ponto vermelho rotulado Té a tocha. A linha verde é a distância linear entre MeT

Entrada

Pegue na entrada padrão a altura da tocha hem metros ao nível do mar, que vejo no topo do horizonte, na forma de um número de ponto flutuante com precisão de duas casas decimais (com a precisão de 1 centímetro ou 0,01 metros), no variam de 0 a 100 incluídos.

Resultado

Você deve retornar o comprimento euclidiano da linha verde com a precisão de 1 cm. Por exemplo, se você produzir em metros, deve ter duas casas decimais (pelo menos). A saída pode ser metros ou quilômetros, mas respeitando a precisão.

Casos de teste:

Todos os valores em metros.

11.5 > 12105.08
13.8 > 13260.45

Regras

O menor código vence.

Mario
fonte
O resultado precisa ser matematicamente correto ou está correto se as duas primeiras casas decimais estiverem corretas? Quero dizer que hxh é pequeno em comparação com 2xRxh e pode ser negligenciado por pequenas distâncias. (R é o raio da Terra e h é a altura da tocha).
Osable
@Osable primeiros 2 casas decimais são ok se você saída em metros
Mario
Qual é o alcance da entrada?
Osable
@Osable, você pode considerar a entrada de 0 a 100 (neste caso, até demais do que o necessário / possível).
Mario
1
Você deveria ter experimentado o Coast Guard Stack Exchange - o código golferse não pode ajudá-lo a sair do oceano, cara!
corsiKa

Respostas:

4

05AB1E ,13 12 10 bytes

Economizou 2 bytes graças a Emigna.

Como não há funções trigonométricas a serem chamadas usando a suposição de OP de que a Terra é localmente um plano, torna-se possível fazer uma solução 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

Experimente online!

Osable
fonte
1
12742000pode ser escrito como•1#oC•
Emigna 24/11
Para referência, teria sido 9 bytes: •1#oC•+*tem 2sable
Emigna
Uma cadeia de caracteres ao redor representa um ... número 214 base? 05AB1E às vezes sofre de falta de documentação sobre essas funções especiais. Resposta 2sable agradável também. Eu descobri isso há alguns dias atrás, mas não pensei em usá-lo para esta pergunta.
Osable
Corrigir. É um número base 10 codificado na base 214.
Emigna 24/11
O resultado também pode ser alcançado por trigonometria, mas provavelmente é mais longo.
Mario
4

Python, 34 26 bytes:

( -8 bytes graças a Osable! )

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

Uma função lambda anônima. Toma entradas em quilômetros e saídas em quilômetros. Invocar como print(<Function Name>(<Input>)).

R. Kap
fonte
lambda i:(i*(i+12742))**.5seria ainda mais curto.
Osable
@Osable Nice! Eu estava prestes a fazer isso. :)
R. Kap
Se houver tolerância matemática, dada a discrepância entre ie 12742, a expressão pode ser abreviada para:(i*12742)**.5
Osable
Os resultados estão errados. 11,5m -> ~ 380km em vez de ~ 12km
GB
O programa lê sua entrada como quilômetros.
Osable
4

PHP, 34 bytes

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

demolir

   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

até agora, isso é idêntico à antiga resposta do 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

agora tudo o que precisamos fazer é adicionar entrada =$argv[1]e saída <?=- pronto

Titus
fonte
4

dc, 16 11 bytes:

?d12742+*vp

Solicita a entrada pela linha de comando em quilômetros e, em seguida, gera a distância em quilômetros.

Explicação

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

Isso tira proveito do seguinte:

((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
R. Kap
fonte
4

jq, 18 caracteres

(12742e3+.)*.|sqrt

Mais uma cópia da mesma fórmula.

Exemplo de execução:

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

Teste on-line

homem a trabalhar
fonte
4

Haskell, 22 bytes

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

Uso:

Prelude> d 11.5
12105.087040166212

Sem ponto: (23 bytes)

sqrt.((*)=<<(+12742e3))
Laikoni
fonte
3

R, 29 bytes

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

Recebe entrada de stdin

Billywob
fonte
Um par de bytes mais curto é (h=scan())*(1+12742e3/h)^.5.
Flounderer
2

Mathematica, 16 bytes

Qualquer um destes trabalhos para entrada e saída em quilômetros:

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

Esta é uma aplicação simples de Pitágoras ao 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)
Martin Ender
fonte
2

Jelly, 9 bytes na página de código de Jelly

Eu decidi escrever o programa em um idioma de golfe. Na verdade, encontrei um algoritmo mais eficiente do que o usado por outras pessoas (pelo menos em distâncias curtas como a da questão), mas requer números literais de ponto flutuante que Jelly não parece capaz de comprimir, então Pitágoras isto é.

+“Ȯịż’×µ½

Explicação:

 “Ȯịż’     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

A necessidade do µseparador me incomoda, mas acho inevitável; O Jelly já salvou um byte acima de 05AB1E, pois consegue adivinhar quais argumentos muitos dos comandos precisam, mas, neste caso, não consegue adivinhar corretamente até o final, então eu precisava dar uma dica.

Jelly, 7 bytes na página de código de Jelly

דȮịż’½

Como expliquei em minha outra resposta , a aproximação em série à aproximação de Pitágoras realmente produz melhores resultados ao longo dos comprimentos incluídos na pergunta (pelo menos, eles estão mais próximos das saídas de exemplo) e também possui uma fórmula mais curta. Enquanto escrevia, percebi que, em vez de calcular a raiz quadrada de 12742000 com antecedência, eu podia multiplicar o número por 12742000 primeiro e depois raiz quadrada, ao mesmo tempo. Isso é basicamente equivalente à outra fórmula sem a adição e, como tal, pode ser produzido a partir do programa anterior através da remoção da adição. Isso economiza dois bytes, pois agora analisa sem ambiguidade e, portanto, não precisamos µmais disso.

Comunidade
fonte
Decidi não usar essa otimização porque ela não produz os mesmos valores se você olhar para os centímetros (consulte a saída solicitada), considerando o intervalo de h. Também salvaria 2 bytes em 05AB1E.
Osable
Com a otimização, recebo saídas de 12105.081577585506 e 13260.452480967608; esses estão muito próximos da saída do caso de teste e arredondados para eles. Sem, recebo 12105.087040166212 e 13260.459661716106, que estão mais distantes (e o último está incorreto nos centímetros, arredondando para 13260.46). Conforme mencionado na outra resposta, a otimização está mais próxima do valor correto do que o código otimizado, pois contém dois erros que se cancelam amplamente, em vez de apenas um que não tem nada para cancelá-lo.
Como você acabou de votar em "Deixar em aberto" na fila de revisão, presumo que você acredite conhecer as respostas para as perguntas para as quais solicitei esclarecimentos nos comentários. Por favor, edite a pergunta para que não seja ambígua.
Peter Taylor
1
A pergunta é inequívoca: o autor precisa saber a distância do amigo para ajudar a navegar. Ele pode determinar a posição da tocha com uma precisão de 0,1 metros (podemos determinar isso a partir da história contada). Isso inevitavelmente resultará em aproximadamente 1 metro de incerteza a partir da saída na distância atual (nota: o autor está à deriva, portanto é improvável que se mova muito longe muito rapidamente ...) e, portanto, qualquer coisa que seja aproximadamente tão precisa provavelmente será aceitável. Parte do problema é determinar a precisão que você precisa ter nessa situação!
1
A saída solicitada mostra 2 casas decimais em metros. Portanto, a precisão deve ser de 1 centímetro. Nos comentários à pergunta, o OP disse que h poderia ir até 100. Com h = 100, há uma discrepância de 14 centímetros em relação ao algoritmo original.
Osable
2

Ruby, 23

23 bytes, em Km

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

25 bytes, em m

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

Tcl, 49 bytes:

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

Bem, eu sou novo no Tcl, então qualquer dica para jogar golfe é muito apreciada. Como minhas outras respostas, solicita a entrada da linha de comando em quilômetros e a saída em quilômetros. Essencialmente, uma adaptação Tcl dos meus existentes dce pythonrespostas.

R. Kap
fonte
existe um s faltando em get s
sergiol 13/12
1

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

Os bytes do programa estão à esquerda (em hexadecimal); há uma desmontagem à direita para facilitar a leitura. Essa é uma função que segue a convenção x86_64 normal para funções que recebem e retornam um número de ponto flutuante de precisão única (pega o argumento em% xmm0 e retorna sua resposta no mesmo registro e usa% xmm1 e% eax como temporários; esses são as mesmas convenções de chamada que um programa C usará e, como tal, você pode chamar a função diretamente de um programa C, que foi como eu a testei.

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

Mesmo com uma desmontagem, no entanto, isso ainda precisa de uma explicação. Primeiro, vale a pena discutir a fórmula. A maioria das pessoas ignora a curvatura da terra e usa a fórmula de Pitágoras para medir a distância. Também estou fazendo isso, mas estou usando uma aproximação de expansão em série; Estou apenas adotando o termo relativo à primeira potência da entrada e ignorando as terceira, quinta, sétima etc. potências, que todas têm apenas uma influência muito pequena a essa curta distância. (Além disso, a aproximação de Pitágoras fornece um valor baixo, enquanto os termos posteriores na expansão em série servem para reduzir o valor; como tal, ignorando um fator menor que serviria para empurrar a aproximação na direção errada, na verdade um resultado mais preciso usando uma fórmula menos precisa.) A fórmula acaba sendo √12742000 × √h;0x455f1980.

A próxima coisa que pode confundir as pessoas é por que estou usando instruções vetoriais para a raiz quadrada e a multiplicação; %xmm0e %xmm1pode conter quatro números de ponto flutuante de precisão única cada, e eu estou operando nos quatro. O raciocínio aqui é realmente simples: sua codificação é um byte menor que a das instruções escalares correspondentes. Para que eu possa fazer com que a FPU faça um trabalho extra de raiz quadrada e multiplicação de zeros para economizar dois bytes, em um método que lembra muito o algoritmo típico da linguagem do golfe. (Chamei x86 assembler a linguagem de golfe dos assemblers no chat há um tempo, e ainda não mudei de idéia sobre isso.)

A partir daí, o algoritmo é muito simples: carregar %xmm1com √12742000 via %eax(que é mais curto em termos de bytes do que carregá-lo da memória), raiz quadrada do argumento (e três zeros), multiplicar os elementos correspondentes de %xmm1e %xmm0(apenas nos importamos sobre o primeiro elemento) e, em seguida, retorne.


fonte
1

Minkolang v0.15, 22 bytes

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

Experimente 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
user41805
fonte
1

JavaScript (ES6), 31 25 bytes

Exibe o valor em metros

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


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

user41805
fonte