Північ на північ Північ Південний Схід


30

Враховуючи рядок N, S, E і W, виведіть підшипник (кут за годинниковою стрілкою від півночі в градусах), виправте 5 знаків після коми.

У традиційних позначеннях компаса рядок складається лише з двох цих символів (наприклад, NNW або ESE). Тут ви також повинні прийняти рядки, які містять усі 4 (наприклад, WNNNSE) . Використання лише двох символів дозволяє людині інтуїтивно зрозуміти значення. Якщо дозволити 4 символи, це стає жахливим для читання, але дозволяє коротші способи опису підшипника до заданої точності.

(Як зазначено в коментарі по user2357112 , виявляється, можна довести , що для будь-якого даного підшипника, рядок 4 символу буде точно такої ж довжини , як рядок 2 символи, тому я на основі цього завдання на помилковій передумові. Сподіваємось, ця відсутність практичної мети не погіршує вашу насолоду від виклику ...)

Точний метод описаний нижче і еквівалентний традиційним позначенням (він розширюється на ньому, а не змінюється).

Вхідні дані

  • Вхід - це один рядок, що містить лише символи NESW.
  • Якщо ви хочете, вхід може представляти собою послідовність символів, якщо це не включає попередню обробку. Наприклад, [N, [E, [S, [W]]]]забороняється брати вкладений список, який допоможе впорядкувати обробку.
  • Використання різних символів заборонено. Ви не можете взяти рядок 1234замість NESW.

Вихідні дані

  • Вихід повинен бути десятковим числом або рядковим поданням одного (а не раціонального / дробу).
  • Задні нулі не потрібно відображати. Якщо підшипник є 9.00000, то вихід 9також вважається правильним до 5 знаків після коми.
  • Вихід знаходиться в діапазоні [0, 360). Тобто, включаючи 0, але виключаючи 360.
  • Правильність перевіряється округленням результату до 5 знаків після коми. Якщо підшипник 0,000005, це закруглюється до 0,00001. Результати 0,00001 та 0,000005 є правильними.
  • Вихід у наукових позначеннях для деяких матеріалів є прийнятним. Наприклад, 1e-5замість 0.00001.

Перетворення

  • Одиничний символ компас точки N, E, Sі Wвідповідають 0, 90, 180 і 270 градусів відповідно.
  • Попередження одного з них до рядка призводить до підшипника, яке розбиває підшипник одиничного символу та опору вихідної струни.
  • Вибирається найближчий з двох можливих підрізних підшипників, так що NE представляє 45 градусів, а не 225 градусів.
  • Це однозначно, за винятком випадків, коли кут, який слід розрізати, становить 180 градусів. Тому NS, SN, WEі EWвідповідають невизначеним підшипників, а вхід ніколи не закінчаться ні в одному з них. Однак вони можуть з’являтися деінде у вхідному рядку, оскільки це не викликає двозначності.
  • Якщо два останніх символи однакові, остаточний символ буде надлишковим, оскільки бісекція поверне той самий підшипник. Оскільки це нічого не додає до позначень, ваш код не потребує цього. Тому NN, EE, SSі WWвідповідають невизначеним підшипників, а вхід ніколи не закінчаться ні в одному з них. Однак вони можуть з’являтися деінде у вхідному рядку.

Приклади

N: 0
E: 90
S: 180
SE: halfway between S and E: 135
NSE: halfway between N and SE: 67.5
NNSE: halfway between N and NSE: 33.75
NNNSE: halfway between N and NNSE: 16.875
NNNNSE: halfway between N and NNNSE: 8.4375

Тестові справи

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

Результати тестових випадків показані округлими до 5 знаків після коми, а також з довільною точністю. Обидва є дійсними результатами.

WNE 337.5 337.5
WEN 337.5 337.5
WEWEWEWEWEWEWEWEWEWEWEN 330.00001 330.000007152557373046875
NESWNESWNESWNESWNESWNESWNESW 90 89.99999932944774627685546875
NNNNNNNNNNNNNNNNNNNNNNNE 0.00001 0.0000107288360595703125
NNNNNNNNNNNNNNNNNNNNNNNW 359.99999 359.9999892711639404296875
SNNNNNNNNNNNNNNNNNNNNNNNE 90.00001 90.00000536441802978515625
SNNNNNNNNNNNNNNNNNNNNNNNW 269.99999 269.99999463558197021484375

Оцінка балів

Це . Оцінка - це довжина вихідного коду в байтах, і найкоротший виграш.


Педантність

Я допустив помилку, думаючи, що "Північ на північний захід" - дійсний компас. Щаслива помилка, оскільки вона призвела до виклику ідеї, але я потім виявив на сторінці Вікіпедії :

"Назва фільму Альфреда Хічкока 1959 року на північ від Північного Заходу насправді не напрямна точка 32-вітрового компаса, а фільм містить посилання на Northwest Airlines ".

Також виявляється, що метод, який використовується для цього завдання, узгоджується лише з традиційними точками компаса до 16-ти точкового компаса. 32-вітровий компас, описаний на цій сторінці, є дещо іншим, і я зручно не помітив його існування для цього завдання.

Нарешті, для тих, хто думає, що я повинен використовувати "Південно-Східний" замість "Південний Схід",.


WNNNSE<= що буде результатом для цього прикладного запису на початку вашої публікації? це звучить для мене недійсно, але важко сказати.
Тенсібай

@Tensibai Для введення WNNNSEбуде вихід 323.4375. Дивіться приклад розділу щодо покрокової інструкції, яка б аналогічно стосувалася і цього випадку.
трихоплакс

Чи f(N,N,N,S,E)добре введення даних ?
Карл Напф

@KarlNapf Я розширив розділ введення для уточнення. Якщо я правильно розумію, ваш приклад введення з декількома аргументами здається еквівалентним послідовності символів, тому було б прийнятним.
трихоплакс

2
"Якщо дозволити 4 символи, це стає жахливим для читання, але дозволяє коротші способи опису підшипника до заданої точності." - ви впевнені в цьому? Схоже, що всі входи, що описують один і той же підшипник, мають однакову довжину, оскільки якщо призначити кожному несучому діадічний раціональний від 0 до 1, рядок довжиною N з N> 1 завжди відповідає діадичному раціональному з знаменником 2 ^ (N +1) найнижчими показниками. Крім того, дозволення більше ніж двох чітких літер в підшипнику не додає виразної сили; будь-який підшипник, виражений 3 або 4 літерами, може бути виражений
символом

Відповіді:


13

JavaScript (ES6), 84 80 78 74 72 байт

Збережено байт завдяки @Titus, 1 завдяки @Neil

f=([c,...s],b="NESW".search(c))=>b*90-(s[0]?(b-=f(s)/90)-4*(b*b>4):0)*45

Минув час, але я думаю, що я остаточно вдосконалив формулу ...

Фрагмент тесту

Пояснення

Почнемо з найпростішого випадку: однорядного рядка. Результатом є просто його (0-індексоване) положення в рядку NESW, помножене на 90.

Для двочарових рядків результат лежить на півдорозі між результатом першого знака та результатом другого. Однак є улов: якщо абсолютна різниця між цими двома більша, ніж 180 (наприклад, NWабо WN), ми повинні 180 на кут, щоб він не вказував протилежну сторону.

Для будь-якого більш тривалого рядка результат лежить на півдорозі між результатом першого символу та результатом решти рядка. Це можна узагальнити наступним чином:

  • Якщо вхід є одним знаком, поверніть його індекс у рядку NESWразів 90.
  • В іншому випадку поверніть індекс першого символу в рядку NESWраз 45 плюс половину результату решти рядка; додайте додаткових 180, якщо абсолютна різниця між ними більше 90.

Відмінний спосіб вирізати першого символу зі струни! Ви можете зберегти один байт, якщо обчислити зі значеннями, поділеними на 45.
Тит

@Titus Я можу зберегти 2 байти за допомогою цієї техніки, дякую!
ETHproductions

1
searchзамість того, indexOfщоб зберегти вам байт.
Ніл

@Neil Дякую ще раз! Мені вдалося відіграти ще три, повністю переставивши рівняння.
ETHproductions

10

C # 6, 226 217 207 185 байт

using System.Linq;double N(string s){double b=f(s.Last());foreach(var c in s.Reverse()){b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0))/2;b=(b+4)%4;}return b*90;}int f(char x)=>"NESW".IndexOf(x);

Редагувати: -10 байт, запозичивши ідею з подання ETHproductions,
-22 байти завдяки @Titus

Безумовно

// Call this method
double N(string s){
    // Initialize bearing with last direction
    double b=f(s.Last());
    // Do backward. Doing last direction once more doesn't impact result
    foreach(var c in s.Reverse()){
        // Average current bearing with new bearing, adjusted with wrapping
        b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0))/2;
        // Make bearing back to range [0,4)
        b=(b+4)%4;
    }
    // Change from "full circle = 4" unit to degree
    return b*90;
}
// helper method to convert direction to bearing. This returns bearing with full circle = 4.
int f(char x)=>"NESW".IndexOf(x);

Я думаю, що ви можете зменшити діапазон регулювання до [0,360), скориставшись%
trichoplax

@trichoplax Ви не вирізали десятичні числа?
Тит


1
Збережіть 10 байт за допомогою, b=(b+360)%360;а не b+=b>360?-360:b<0?360:0;. Збережіть ще 12 байт, розділивши все на 90 і return b*90;.
Тит

1
Ось ще 10 байт: об’єднайте два завдання та видаліть дужки: b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0)+8)/2%4;потім розподіліть +8до потрійних результатівb=(b+f(c)+(b-f(c)>2?12:f(c)-b>2?4:8))/2%4;
Тит

8

PHP, 95 88 86 100 127 104 101 байт

  • -7 байт з оператором нульового злиття
  • -2 байти, не замінюючи N(і більше, тому що це дозволяє помістити переклад на голову циклу: Nє truthy, але оцінює 0в обчисленні.)
  • +41 байт для фіксації бісекції ( кашлю )
  • -7 байтів безпосередньо та -16 опосередковано натхненні кодом @ ETHproductions
  • -3 байти, замінивши strtrодним із моїх бітових жонглів

for($i=strlen($s=$argv[1]);$i--;$p=($q+$p=$p??$q)/2+2*(abs($q-$p)>2))$q=ord($s[$i])/.8+3&3;echo$p*90;

Офіційно це перший раз, коли я використовую оператор нульового згортання. Бігайте з -r.

PHP 7.1

Негативні зміщення рядків у майбутній версії PHP заощадять 12 байт:
Замініть strlen($s=$argv[1])на 0і $sна $argv[1].


Безкоштовні байти для (майже) кожного:

  • Обчислення 0,1,2,3 замість 0,90,180,270 та помноження кінцевого результату на 90 дозволить заощадити два байти і, ймовірно, дозволить подальший гольф.
  • У кодах ASCII символів є деякі візерунки. Спробуйте один із них мовою:
    • (a/2%6+2)%5
    • a<87?a/2&3^3:3 або a/2&3^3*(a<87)
    • a&1?a&2|a/4&1:0
    • a/.8-1&3

5

Python 3, 133 113 байт

Просто покращую відповідь на @ L3viathan, тому що я щойно зробив цей обліковий запис і тому поки що не можу коментувати.

d={"N":0,"E":.5,"S":1,"W":1.5}
def B(s):
 b=d[s[-1]]
 for c in s[::-1]:b=(b+d[c])/2+(abs(b-d[c])>1)
 return b*180

Ласкаво просимо до програмування головоломок та коду для гольфу та приємного вдосконалення ...
trichoplax

Я не бачив вашої відповіді, але у Тита була подібна ідея, плюс у мене була інша, я зараз до 98 :)
L3viathan

5

05AB1E ,48 42 37 32 байти

Збережено 6 байт завдяки Еміньї. Збережено 5 байт завдяки ідеї Тіта працювати в діапазоні [0,4] та помножувати на 90 наприкінці. Збережено 5 байт завдяки майстерності Аднана в античній метаморфозі XOR / модуля.

Таким чином, кожен кут зменшується від діапазону [0,360 [до діапазону [0,4] протягом усього виконання. Потім результат множать на 90 і відображають.

Ç30^5%R¬U¦vXy+;DX-Ä0›2*+4%U}X90*

It can be divided into two sequentially called subprograms.
First program: convert input string into an array of the corresponding angles in range [0,4[
Ç      Take the ascii value of all input characters
 30^5% Dark ascii manipulation that yields [0,1,2,3] for [N,E,S,W]

Now we have an array of integers in range [0,4[.

Second program: actually compute the final angle
R                          Reverse the array
 ¬                         Take the first value (the last of the non-reversed array)
  U                        Pop it from the stack and set X to the same value
   ¦                       Strip the first element
    v                      For each remaining element
     Xy+;                  Compute the average value between the leftmost value and X
         DX-Ä0›            Push 1 if angular distance cast to integer is > 0 (i.e. if it is >= 1), 0 otherwise. It's equivalent to checking >= 90 degrees
               2*+         Multiply by 2 (=2 if angular distance is >= 1 and 0 otherwise) and add it to the formerly computed average value. It's equivalent to multiplying by 180
                  4%       Perform mod 4. It's equivalent to performing mod 360
                    U      Store the result back to X
                     }     End for, mandatory if input has only one character
                      X90* Push X*90 and implicitly display it

Спробуйте в Інтернеті!

Потенційні осі гольфу:

  • Не впевнений, чи потрібен цей мод 4 (він би заощадив 2 байти). Усі тестові справи працюють без цього, але, можливо, існує хитра справа. Математичний доказ або підтвердити його, або скасувати це було б найкращим.
  • Немає неявного матеріалу, окрім відображення результату (закриття лапок, закриття дужок).

1
Чи не схоже , щоб дати необхідний результат на NNNNNNNNNNNNNNNNNNNNNNNEі SNNNNNNNNNNNNNNNNNNNNNNNEтестах.
Емінья

2
Дивно. Зараз я також. Я, мабуть, неправильно вставив щось, вибачте. Ви можете скоротити код до v"NESW"yk90*})R¬U¦vXy+;DX-Ä89›180*+360%U}X.
Емінья

1
Чудове пояснення! Можливо, варто включити зауваження, що 89›фактично означає, що ціла частина більша за 89, що еквівалентно твердженню, що повне число більше або дорівнює 90 (що все одно працює нормально, бо точно 90 ніколи не повинно виникати). Наразі коментар у поясненому коді звучить так, ніби він перевіряє понад 89, тоді як ваш код проходить тестові випадки, тому явно правильно перевіряється на більш ніж 90.
trichoplax

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

1
Ви можете замінити v"NESW"yk})з Ç30^5%:)
Аднана

5

Python 3, 146 145 117 107 97 94 93 92 байт

f(s):u='NESW'.find(s[0])*90;return(u+f(s[1:]))/2+180*(abs(u-‌​f(s[1:]))>180)if s[1:]else u

Дзвінок fза допомогою рядка.


У вас не може бути двох, які ...0elseвони кидають SyntaxErrors.
Джонатан Аллан

@JonathanAllan Яку версію Python ви використовуєте? Я на 3.5.2, і це працює.
L3viathan

Я запустив це на 3.3.3 - ви можете видалити пробіл між elseі -занадто? (може в 3.3.3)
Джонатан Аллан

@JonathanAllan Так, я можу! Дякую, що врятує мені ще один байт.
L3viathan

2
@Titus d.findможе, я мав точну ідею хвилину тому; див. оновлену відповідь.
L3viathan

5

C, 184 байти

double h(char c){return ((c=='E')+(c=='S')*2+(c=='W')*3);}double d(char*s){double f=h(*s);if(s[1]){double t=f;f=(f+d(s+1)/90)/2;if(((t-f)>1)||((f-t)>1))f+=2;if(f>=4)f-=4;}return f*90;}

Безумовно

// a helper function
double direction_(char ch)
{
    if (ch=='N')
        return 0.;
    else if (ch=='E')
        return 90.;
    else if (ch=='S')
        return 180.;
    else
        return 270.;
}

// this is the main function to call
double direction(char* str)
{
    double fAngle = direction_(str[0]);
    if (str[1])
    {
        double tmp = fAngle + direction(str+1);
        if (tmp>=360.)
            tmp-=360.;
        tmp/=2;

        if (((tmp-fAngle)>90.) || ((tmp-fAngle)<-90.))
        { //  check if we need to take the "other side"; if the resulting angle is more than 90 degrees away, we took the wrong on
            if (tmp>=180.)
                tmp-=180.;
            else
                tmp+=180.;
        }
        fAngle = tmp;
    }
    return fAngle;
}

Здається, що використання float не дає точності, необхідної.
Eyal Lev

4
Ласкаво просимо до PPCG! : D
mbomb007

Чи не будуть імена функцій суперечити один одному (оскільки імена обидва d)?
клісмік

@qwerp, інший підпис (один бере char *, інший бере лише char)
Eyal Lev

2
Імена функцій не називаються іменами в C, як вони є в C ++, тому вам потрібно перейменувати одне з них, якщо ви хочете, щоб це було C.
Klas Lindbäck,

3

R, 172 146 байт

z=rev((0:3*90)[match(scan(,""),c("N","E","S","W"))]);p=z[1];l=length(z);for(i in 2:l)p=(p+z[i])/2+(abs(p-z[i])>180)*180;if(l<2)p=z;sprintf("%f",p)

Безумовно

z=rev((0:3*90)[match(scan,""),c("N","E","S","W"))]); #1
p=z[1];                                              #2
l=length(z)                                          #3
for(i in 2:l)p=(p+z[i])/2+(abs(p-z[i])>180)*180;     #4
if(l<2)p=z                                           #5
sprintf("%f",p)                                      #6

Пояснив

  1. Прочитайте введення з stdin
    • Збіг введення за індексом до c("N","E","S","W")
    • Із відповідних індексів: відповідність вектору градусів 0:3*90(замість c(0,90,180,270))
    • Зворотний і зберігати як z
  2. Ініціалізуйте pдо ступеня, еквівалентної останньому знаку введення
  3. Зберегти довжину введення як l
  4. Ітеративно обчисліть найближчий з двох можливих розрізних підшипників.
  5. Якщо вказано лише один вхід, встановіть pзначенняz
  6. Форматування та друк

Спробуйте тестові випадки на R-скрипці (зауважте, що це функція через те, що scanне працює над R-скрипкою)


За умови правильності виводу на 5 знаків після коми, вам не потрібно проводити округлення. З виклику: Outputs 0.00001 and 0.000005 are both correct.Отже, ви повинні бути в змозі зберегти кілька байт, не округлюючи
trichoplax

@trichoplax я розумію. Чи може вхід також бути вектором рядкових символів, як. c("N","N","E")замість "NNE"? Це еквівалент невкладеному списку пітонів ["N","N","E"].
Billywob

Так. Я задумав "послідовність" бути загальним терміном, щоб включати такі речі, як масиви, вектори, списки, кортежі.
трихоплакс

1
Я думаю, ви можете зберегти 4 байти, якщо розділити все на 90 і printf (p * 90).
Тит

3

Haskell, 109 105 103 байт

h=180
a#b|abs(a-b)<h=n|n>h=n-h|1>0=n+h where n=(a+b)/2 -- calculates the new "mean" on the cirlce
f 'N'=0                                          -- translates characters to angles
f 'E'=90
f 'S'=h
f _=270
foldr1(#).map f                                  -- traverses the whole string

Дякую за -2 байт @xnor!


Вичерпний список fвиглядає довгим, але я маю проблеми знайти щось коротше. Найближчим мені було f c=90*until(\i->"NESW"!!i==c)(+1)0(35). Я думаю , ви можете замінити 'W'з _.
xnor

Так, я також очікував, що там буде щось коротше, але нічого не знайшов. Дякую за _!
flawr

3

Діалог APL , 55 45 38 байт

Рішення

Вимагає ⎕IO←0, що для багатьох систем за замовчуванням. Запитує напрямок.

360|÷○÷180×12○(+÷(|+))/¯12○○2÷⍨'NES'⍳⍞

Пояснення

Вирішує проблему, перетворюючи кожну букву на комплексну цифру 1∠ θa + b · i , після чого виконуючи зменшення суми справа наліво (форте APL) при нормалізації на кожному кроці. Кінцевий θ перетворюється на градуси і нормалізується в межах [0, 360):

'NES'⍳⍞індекси кожної літери введення у "NES"; N → 0, E → 1, S → 2, все інше → 3

○2÷⍨перетворити на кути в радіанах; θ = π · x2

¯12○перетворити на складні числа на одиничному колі; e i · θ

(... )/зменшити список за допомогою ... (тобто вставити функцію між елементами ...)

+÷(|+)... нормована сума; x n - 1 + x n| x n - 1 + x n |

12○перетворити на кут; θ

÷○÷180×конвертувати в градуси; 1π · 1180 · x

360| залишок ділення при поділі на 360

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

Анекдот

Якби вхід і вихід були ортогональними складними одиницями, все рішення було б просто:

(+÷(|+))/

Решта коду - це аналіз синтаксису введення та форматування.


Зауважую, тестові результати не відповідають результатам виклику до 5 знаків після коми, що робить це недійсним. Чи має Dyalog APL можливість використовувати подвійну точність?
трихоплакс

@trichoplax Так, ⎕FR←1287використовується 128-бітний поплавок, але TryAPL це не дозволяє.
Адам

Я думаю, що все, що перевищує або дорівнює 64-бітовим плавцям, має працювати (хоча я протестував лише в Python). Чи означає це, що ви можете зробити код дійсним, але він буде працювати лише для людей, які встановили мову? Можливо, ви могли б показати повний дійсний код для оцінки та включити онлайн-версію, яка не має достатньої точності, щоб люди могли бачити, що алгоритм правильний.
трихоплакс

@trichoplax Насправді TryAPL використовує подвійну точність, але у ваших тестових випадках накопичуються помилки понад 53 біт.
Адам

Якщо може бути показано, що різниця пов'язана з різницею в інтерпретації стандарту IEEE 754, які все ще відповідають стандарту, я відкоригую тестові випадки, щоб переконатися, що обидві інтерпретації дають однаковий результат до 5 знаків після коми. Я вибрав тестові випадки таким чином, що вони давали однаковий результат до 5 знаків після коми в Python як для плаваючої (подвійної точності), так і для довільних десяткових знаків. Я розберуся.
трихоплакс

2

Лист звичайний, 347 327 байт

Дякуємо @Titus за те, що зняв декілька

Напевно, це може бути більше гольфу, але принаймні це працює (я думаю):

(defun d(c)(if(eql c #\N)0(if(eql c #\E)1(if(eql c #\S)2(if(eql c #\W)3)))))(defun m(a b)(if(> a b)(rotatef a b))(if(<(+(- 4 b)a)(- b a))(+(/(+(- 4 b)a)2)b)(+(/(- b a)2)a)))(defun f(s)(let((c))(setf c(d(char s(1-(length s)))))(do((a)(p(-(length s)2)(1- p)))((< p 0))(setf a(char s p))(setf c(m(d a)c)))(format t"~5$"(* c 90))))

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

* (f "WNE")
337.50000
NIL

Функція dприймає символ N, E, Wабо Sі повертає відповідний ступінь. Функція mотримує відповідну комбіновану ступінь двох заданих напрямків. Функція fповторюється через наданий рядок, обчислює відповідний ступінь і друкує його як плаваючу точку.


Мій LISP іржавий, але чи можна ділити все на 90, щоб заощадити 6 байт?
Тит

@Titus Я думаю, що це було б. Я зрозумів деякі інші вдосконалення, тому додам це, коли буду за своїм комп'ютером
штучний

2

Befunge, 183 181 175 байт

>~#+:#25#%6*#/`#2_$>5%4*:00p"Z}"4*:***20g#v_+2/00g10g-:8`\0\-8`+!v
v5:+*:*:"d"/+55+5$_^#!:\p01/**:*4"}Z":p020<%**:*"(2Z"+**5*:*"0}"!<
>5>+#<%#56#58#:*#/+\#5:#5_$$$,,,".">:#,_@

Спробуйте в Інтернеті!

Пояснення

Це дотримується аналогічного алгоритму для багатьох інших відповідей, тільки він використовує обчислення з фіксованою точкою, емільовані цілими числами, оскільки Befunge не підтримує плаваючу крапку.

Дякуємо @Titus за звичайну процедуру ASCII.

 ~ : 5 6* ` _$        while ((c = getchar()) > 30)  // ends with any ctrl char or EOF
> + 2 %6 / 2            push(c / 2 % 6 + 2)         // partial conversion to int

                      do {
  5%                    dir = pop() % 5             // completes the conversion to int   
  4*:00p                dir *= 4; lowres_dir = dir  // used by the 180-flip calculation
  "Z}"4*:***            dir *= 22500000             // this is 90000000 / 4 
  20g_                  if (!first_pass) {
    +2/                   dir = (dir+last_dir)/2    // last_dir is second item on stack
    00g10g-               diff = lowres_dir - last_lowres_dir
    :8`\0\-8`+!!          flip = diff>8 || -diff>8
    "}0"*:*5**+           dir += flip * 180000000   // add 180 degrees if we need to flip
    "Z2("*:**%            dir %= 360000000          // keep within the 360 degree range
                        }
  020p                  first_pass = false
  :"Z}"4*:**/10p        last_lowres_dir = dir / 22500000
  \                     last_dir = dir              // saved as second item on stack
  :!_                 } while (!stack.empty())

$                     pop()                         // this leaves the final dir on top
5+55+/                dir = (dir + 5)/10            // round down to 5 decimal places
"d":*:*+              dir += 100000000              // add a terminating digit
                      while (true) {                // convert into chars on stack
:55 + % 6 8 * +\ : _    push(dir%10+'0'); if (!dir) break
   > < 5 5 : /+ 5 5     dir /= 10
                      }

$$$                   pop() x 3                     // drop the chars we don't need
,,,                   putchar(pop()) x 3            // output first three chars
"."                   push('.')                     // add a decimal point
>:#,_@                while(c=pop()) putchar(c)     // output the remaining chars

Це означає лише, що вам потрібно емулювати більший тип фіксованої точки (більше знаків після коми)? Тестові приклади розроблені так, щоб вимагати подвійної точності, що становить не більше 17 значущих цифр (максимум 16 десяткових знаків), а 14 десяткових знаків, можливо, буде достатньо.
трихоплакс

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