Допоможи мені, що я загубився в океані!


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 - висота факела).
Доступний

@ Доступні перші 2 десяткові дроби - це нормально, якщо ви виходите в метрах
Маріо

Який діапазон введення?
Доступний

@ Придатним ви можете вважати, що вхід становить від 0 до 100 (навіть занадто багато, ніж це потрібно / можливо в цьому випадку).
Маріо

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

Відповіді:


4

05AB1E ,13 12 10 байт

Збережено 2 байти завдяки Еміньї.

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

Чи відображає рядок із заточеним номером ... номер 214? 05AB1E іноді відчуває брак документації щодо таких спеціальних функцій. Приємна відповідь також. Я дізнався про це кілька днів тому, але не думав використовувати його для цього питання.
Доступний

Правильно. Це номер 10, закодований у базі 214.
Емінья

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

4

Python, 34 26 байт:

( -8 байт завдяки Ovable! )

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

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


lambda i:(i*(i+12742))**.5було б ще коротше.
Доступний

@ Придатний Ніцца! Я збирався це зробити. :)
Р. Кап

Якщо є математична толерантність, враховуючи розбіжність між iі 12742, вираз можна скоротити так:(i*12742)**.5
Доступно

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

@GB Програма читає свої дані як кілометри.
Доступний

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

Хаскелл, 22 байти

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

Використання:

Prelude> d 11.5
12105.087040166212

Pointfree: (23 байти)

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


2

Математика, 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 байт на кодовій сторінці Jelly

Я вирішив зайнятися написанням програми гольф-мовою. Я фактично знайшов більш ефективний алгоритм, ніж той, який використовують інші люди (принаймні на невеликі відстані, як той, що йдеться у запитанні), але для цього потрібні буквальні числа з плаваючою комою, які Jelly, здається, не здатні стиснути, тому Піфагор Це є.

+“Ȯịż’×µ½

Пояснення:

 “Ȯịż’     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 байт на кодовій сторінці Jelly

דȮịż’½

Як я пояснив у своїй іншій відповіді , наближення ряду до наближення Піфагора насправді дає кращі результати за довжини, що входять у питання (принаймні, вони ближче до прикладних результатів), а також має більш коротку формулу. Поки я писав це, я зрозумів, що замість того, щоб заздалегідь обчислити квадратний корінь 12742000, я міг би помножити спочатку число на 12742000, а потім одночасно квадратний корінь. Це в основному еквівалентно іншій формулі без додавання, і як таку вона може бути вироблена з попередньої програми шляхом видалення додавання з неї. Це економить два байти, оскільки тепер це однозначно аналізує, і тому нам більше не потрібно µ.


Я вирішив не використовувати цю оптимізацію, оскільки вона не дає однакових значень, якщо подивитися на сантиметри (див. Запитуваний вихід), враховуючи діапазон h. Це також заощадить 2 байти в 05AB1E.
Доступний

За допомогою оптимізації я отримую виходи 12105.081577585506 та 13260.452480967608; вони дуже близькі до результатів тестового прикладу і круглі до них. Без цього я отримую 12105.087040166212 і 13260.459661716106, які знаходяться далі (а останнє неправильне в сантиметрах, округлюючи до 13260,46). Як було сказано в іншій відповіді, оптимізація виявляється ближчою до правильного значення, ніж оптимізований код, оскільки містить дві помилки, які значною мірою скасовують одна одну, а не лише одну, яка нічого не може її скасувати.

Оскільки ви просто проголосували за "Залишити відкритим" у черзі на огляд, я вважаю, що ви вважаєте, що знаєте відповіді на запитання, до яких я просив роз'яснити коментарі. Тому відредагуйте це питання так, щоб воно було однозначним.
Пітер Тейлор

1
Питання однозначне: автору потрібно знати відстань до свого друга, щоб допомогти орієнтуватися. Він може визначити положення факела з точністю до 0,1 метра (це можна визначити з розповіді, що розповідається). Це неминуче дасть приблизно 1 метр невизначеності від виходу на поточну відстань (зауважте: автор дрейфує навколо, таким чином, навряд чи рухатиметься дуже далеко дуже швидко ...), і тому все, що є приблизно таким точним, ймовірно, буде прийнятний. Частина проблеми полягає у визначенні того, наскільки точними ви повинні бути в цій ситуації!

1
Запитаний вихід показує 2 десяткових метри в метрах. Тож очікується, що точність складе 1 сантиметр. У коментарях до питання ОП заявив, що h може піднятися до 100. З h = 100 є невідповідність 14 сантиметрів від вихідного алгоритму.
Доступна

2

Рубі, 23

23 байти, в км

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

25 байт, м

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

1

Tcl, 49 байт:

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

Ну, я абсолютно новачок у Tcl, тому будь-які поради щодо гри в гольф це дуже цінується. Як і інші мої відповіді, підказки для введення командного рядка в кілометрах та виходів у кілометрах. По суті є адаптацією Tcl моїх існуючих dcта pythonвідповідей.


є відсутність s на get s
sergiol

1

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

Байти програми знаходяться ліворуч (у шістнадцятковій формі), справа знаходиться в розборці, щоб зробити її легше читати. Це функція, яка відповідає нормальній умові x86_64 для функцій, що приймають та повертають одноточне число з плаваючою точкою (він бере аргумент у% xmm0 і повертає свою відповідь у тому ж реєстрі, і використовує% xmm1 та% eax як тимчасові; ці це ті самі умови викликів, які використовуватиме програма 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може містити чотири одноточні числа з плаваючою комою кожен, і я працюю на всіх чотирьох. Міркування тут дуже просте: їх кодування на один байт коротше, ніж у відповідних скалярних інструкціях. Тож я можу змусити ФПУ зробити купу додаткової роботи з квадратним укоріненням і множенням нулів, щоб врятувати собі два байти, методом, який дуже нагадує типовий алгоритм мови гольфу. (Я зателефонував асемблеру x86 гольф на мову гольфу в чаті, і я досі не передумав.)

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


1

Minkolang 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

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.