Помоги мне, я потерялся в океане!


11

Вступление

Сегодня я пошел на рыбалку наедине со своим каноэ, к сожалению, я уснул, и ручей унес меня прочь, я потерял весла, теперь ночь, и я потерялся в океане! Я не вижу побережья, поэтому я должен быть далеко!

У меня есть мобильный телефон, но он неисправен, потому что он намок от соленой воды, я не могу ничего говорить или слышать, потому что микрофон и динамик телефона сломаны, но я могу отправить SMS своему другу, который находится на берегу моря!

У моего друга очень мощный факел, и он поднял его на бамбуковые трости, чтобы показать мне правильное направление, но я не могу грести, потому что у меня нет весла, поэтому я должен сказать ему, как далеко я нахожусь, чтобы он мог кого-то отправить Поймай меня!

Мой друг сказал мне, что он держит факел на уровне 11,50 метров над уровнем моря, и я вижу свет прямо за горизонтом. Теперь я помню только из школы, что радиус Земли должен быть 6371 км на уровне моря, и я сижу в своем каноэ, поэтому вы можете предположить, что мои глаза тоже на уровне моря.

задача

Поскольку токи меняют момент за мгновением, мой друг время от времени поднимает факел (теперь он на 12.30 метра), пожалуйста, напишите полную программу или функцию, которая поможет мне рассчитать расстояние от позиции моего друга!

Вот диаграмма (не в масштабе):

введите описание изображения здесь

Оранжевая точка с надписью M- это я, красная точка с надписью T- это факел. Зеленая линия линейное расстояние между MиT

вход

Возьмите из стандартного ввода высоту факела hв метрах на уровне моря, которую я вижу прямо на вершине горизонта, в виде числа с плавающей запятой с точностью до двух десятичных знаков (с точностью до 1 сантиметра или 0,01 метра) в диапазон от 0 до 100 включен.

Выход

Вы должны вернуть евклидову длину зеленой линии с точностью до 1 см. Например, если вы выводите в метрах, должно быть с двумя десятичными знаками (как минимум). Выход может быть либо в метрах, либо в километрах, но с учетом точности.

Тестовые случаи:

Все значения в метрах.

11.5 > 12105.08
13.8 > 13260.45

правила

Самый короткий код выигрывает.


Должен ли результат быть математически корректным или это нормально, если первые 2 десятичных числа в порядке? Я имею в виду, что hxh мало по сравнению с 2xRxh и им можно пренебречь на небольших расстояниях. (R - радиус Земли, а h - высота факела).
Osable

@ Возможны первые 2 десятичных знака, если вы выводите в метрах
Mario

Каков диапазон ввода?
Osable

@Osable, вы можете считать, что ввод от 0 до 100 (даже больше, чем необходимо / возможно в этом случае).
Марио

1
Тебе следовало попробовать обмен стеками береговой охраны - игрок в гольф не может помочь тебе выбраться из океана, чувак!
CorsiKa

Ответы:


4

05AB1E ,13 12 10 байт

Сохранено 2 байта благодаря Emigna.

Поскольку не существует тригонометрических функций, которые можно вызывать с использованием предположения OP о том, что Земля локально является плоскостью, становится возможным решение 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

Попробуйте онлайн!


1
12742000можно записать как•1#oC•
Emigna

Для справки, это было бы 9 байтов: •1#oC•+*tв 2sable
Emigna

Показывает ли строка, обозначенная знаком ..., основание 214? 05AB1E иногда испытывает недостаток документации по таким специальным функциям. Хороший ответ 2sable также. Я узнал об этом несколько дней назад, но я не думал об использовании этого для этого вопроса.
Osable

Верный. Это базовый номер 10, закодированный в базе 214.
Emigna

Результат может быть достигнут также с помощью тригонометрии, но, вероятно, дольше.
Марио

4

Python, 34 26 байт:

( -8 байт благодаря Osable! )

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

Анонимная лямбда-функция. Принимает ввод в километрах и выводит в километрах. Вызывать как print(<Function Name>(<Input>)).


lambda i:(i*(i+12742))**.5будет еще короче.
Osable

@Osable Nice! Я как раз собирался это сделать. :)
Р. Кап

Если есть математическая терпимость, учитывая несоответствие между i12742, выражение может быть сокращено так:(i*12742)**.5
Osable

Результаты неверны. 11,5 м -> ~ 380 км вместо ~ 12 км
ГБ,

@GB Программа считывает свои данные в километрах.
Osable

4

PHP, 34 байта

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

сломать

   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

до сих пор это идентично старому ответу 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

теперь все, что осталось сделать, это добавить ввод =$argv[1]и вывод <?=- готово


4

dc, 16 11 байтов:

?d12742+*vp

Запрашивает ввод через командную строку в километрах, а затем выводит расстояние в километрах.

объяснение

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

Это использует следующие преимущества:

((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 символов

(12742e3+.)*.|sqrt

Еще одна копия той же формулы.

Образец прогона:

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

Он-лайн тест


4

Haskell, 22 байта

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

Использование:

Prelude> d 11.5
12105.087040166212

Pointfree: (23 байта)

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

3

R, 29 байт

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

Принимает ввод от стандартного ввода


Пара байтов короче есть (h=scan())*(1+12742e3/h)^.5.
Камбала

2

Mathematica, 16 байт

Любая из этих работ работает как для ввода и вывода в километрах:

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

Это простое приложение Пифагора к проблеме:

   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

Желе, 9 байт в кодовой странице желе

Я решил попробовать написать программу на языке игры в гольф. Я на самом деле нашел более эффективный алгоритм, чем тот, который используют другие люди (по крайней мере, на коротких расстояниях, подобных тому, который указан в вопросе), но он требует буквальных чисел с плавающей точкой, которые, по-видимому, Джелли не может сжать, поэтому Пифагор это.

+“Ȯịż’×µ½

Объяснение:

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

Необходимость в µсепараторе раздражает меня, но я думаю, что это неизбежно; Jelly уже сохранил байт над 05AB1E, поскольку он может угадать, какие аргументы нужны многим командам, но в этом случае он не может правильно угадать до конца, поэтому мне нужно было дать ему подсказку.

Желе, 7 байт в кодовой странице желе

דȮịż’½

Как я объяснил в моем другом ответе , приближение рядов к приближению Пифагора фактически дает лучшие результаты по длинам, включенным в вопрос (по крайней мере, они ближе к выходным данным примера), а также имеет более короткую формулу. Когда я писал его, я понял, что вместо того, чтобы заранее вычислять квадратный корень из 12742000, я мог бы сначала умножить число на 12742000, а затем и квадратный корень одновременно. Это в основном эквивалентно другой формуле без добавления, и, как таковое, ее можно получить из предыдущей программы, удалив дополнение из нее. Это экономит два байта, так как теперь он анализирует однозначно, и поэтому нам больше не нужен µ.


Я решил не использовать эту оптимизацию, потому что она не дает одинаковых значений, если вы посмотрите на сантиметры (см. Запрошенный вывод) с учетом диапазона h. Это также сэкономит 2 байта в 05AB1E.
Osable

С оптимизацией я получаю выходные данные 12105.081577585506 и 13260.452480967608; они очень близки к выводу тестового примера и округлены до них. Без, я получаю 12105.087040166212 и 13260.459661716106, которые находятся дальше (а последний неверен в сантиметрах, округляя до 13260.46). Как упоминалось в другом ответе, оптимизация оказывается ближе к правильному значению, чем оптимизированный код, потому что она содержит две ошибки, которые в значительной степени взаимно компенсируют друг друга, а не только одна, которая не имеет ничего для ее отмены.

Поскольку вы только что проголосовали за «Оставить открытым» в очереди на проверку, я предполагаю, что вы считаете, что знаете ответы на вопросы, по которым я просил разъяснения в комментариях. Поэтому, пожалуйста, отредактируйте вопрос так, чтобы он был однозначным.
Питер Тейлор

1
Вопрос однозначен: автору нужно знать расстояние до своего друга, чтобы помочь сориентироваться. Он может определить положение факела с точностью до 0,1 метра (мы можем определить это по рассказанной истории). Это неизбежно приведет к приблизительно 1 метру неопределенности от выходных данных на текущем расстоянии (примечание: автор дрейфует вокруг, поэтому вряд ли очень быстро продвинется очень далеко…), и, следовательно, все, что приблизительно настолько точно, вероятно, будет приемлемо. Частично проблема заключается в определении того, насколько точно вы должны быть в этой ситуации!

1
Запрошенный вывод показывает 2 десятичных знака в метрах. Так что точность ожидается на уровне 1 сантиметра. В комментариях к вопросу OP сказал, что h может доходить до 100. При h = 100 наблюдается несоответствие 14 сантиметров от исходного алгоритма.
Osable


1

Tcl, 49 байт:

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

Ну, я новичок в Tcl, так что любые советы по игре в гольф это высоко ценится. Как и другие мои ответы, запрашивает ввод командной строки в километрах и вывод в километрах. По сути Tcl адаптация моего существующего dcи pythonответы.


на s s не хватает s
sergiol

1

x86_64 + машинный код SSE, 16 байт

Байты программы находятся слева (в шестнадцатеричном формате), справа есть разборка, чтобы ее было легче читать. Это функция, которая следует обычному соглашению x86_64 для функций, принимающих и возвращающих число с плавающей запятой одинарной точности (она принимает аргумент в% xmm0 и возвращает свой ответ в том же регистре, и использует% xmm1 и% eax в качестве временных значений; являются теми же соглашениями о вызовах, которые будут использовать программы на C, и, как таковые, вы можете вызывать функцию непосредственно из программы на C, как я ее тестировал).

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

Даже с разборкой, однако, это все еще нуждается в объяснении. Во-первых, стоит обсудить формулу. Большинство людей игнорируют кривизну земли и используют формулу Пифагора для измерения расстояния. Я тоже это делаю, но я использую приближение расширения серии; Я использую только термин, относящийся к первой степени входного сигнала, и игнорирую третью, пятую, седьмую и т. Д., Которые все имеют очень небольшое влияние на этом коротком расстоянии. (Кроме того, приближение Пифагора дает низкое значение, в то время как более поздние члены в разложении рядов служат для уменьшения значения; поэтому, игнорируя незначительный фактор, который послужит толчком к приближению в неправильном направлении, я на самом деле получаю более точный результат с использованием менее точной формулы.) Формула оказывается √12742000 × √h;0x455f1980,

Следующее, что может смутить людей, - это то, почему я использую векторные инструкции для квадратного корня и умножения; %xmm0и %xmm1может содержать четыре числа с плавающей запятой одинарной точности каждое, и я оперирую всеми четырьмя. Рассуждения здесь очень просты: их кодировка на один байт короче, чем у соответствующих скалярных инструкций. Таким образом, я могу заставить FPU выполнять кучу дополнительных операций с квадратным корнем и умножением нулей, чтобы сэкономить себе два байта, в методе, который очень напоминает типичный алгоритм языка игры в гольф. (Я называл x86 ассемблер языком игры ассемблеров в чате некоторое время назад, и я до сих пор не передумал.)

Отсюда алгоритм очень прост: загрузка %xmm1с помощью √12742000 через %eax(что короче в байтах, чем будет загрузка его из памяти), квадратный корень аргумента (и три нуля), умножение соответствующих элементов на %xmm1и %xmm0(нас интересует только о первом элементе), затем вернитесь.


1

Минколанг v0.15, 22 байта

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

Попробуйте онлайн!

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 байт

Отображает значение в метрах

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


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

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.