Север за Севером Север за Югом Восток


30

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

В традиционных обозначениях компаса строка состоит только из 2 из этих символов (например, NNW или ESE). Здесь вы также должны принять строки, которые содержат все 4 (например, WNNNSE) . Использование только 2 символов позволяет людям интуитивно понять смысл. Разрешение 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<= что будет выходом для этого примера записи в начале вашего сообщения? это звучит недействительно для меня, но трудно сказать.
Тенсибай

@ Тенсибай Для ввода WNNNSEбудет вывод 323.4375. Посмотрите пример раздела для пошагового руководства, которое применимо таким же образом к этому случаю.
трихоплакс

Ввод как f(N,N,N,S,E)хорошо?
Карл Напф

@KarlNapf Я расширил раздел ввода, чтобы уточнить. Если я правильно понимаю, ваш пример ввода с несколькими аргументами кажется эквивалентным последовательности символов, поэтому он будет приемлемым.
Трихоплакс

2
«Разрешение 4 символов делает чтение ужасным, но позволяет использовать более короткие способы описания направления с заданной точностью». - Вы уверены, что? Кажется, что все входные данные, которые описывают один и тот же подшипник, имеют одинаковую длину, поскольку, если вы назначите каждому подшипнику двоичный рациональный от 0 до 1, строка длины N с N> 1 всегда будет соответствовать двоичному рациональному знаменателю 2 ^ (N +1) в самые низкие сроки. Кроме того, добавление более двух разных букв в букву не добавляет выразительной силы; любой подшипник, выраженный 3 или 4 буквами, может быть выражен 2.
user2357112 поддерживает Monica

Ответы:


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

Ungolfed

// 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заголовок цикла: верно, но оценивается 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

Добро пожаловать в Программирование Пазлов и Code Golf и приятных улучшений ...
trichoplax

Я не видел вашего ответа, но у Тита была похожая идея, плюс у меня была другая, у меня сейчас 98 до сих пор :)
L3viathan

5

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

Сохранено 6 байтов благодаря Emigna. Сохранено 5 байт благодаря идее Тита работать на диапазоне [0,4 [и умножить на 90 в конце. Сохранено 5 байт благодаря мастерству Аднана в древней метаморфозе xor / modulo.

Таким образом, каждый угол уменьшается от диапазона [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тестовых случаях.
Emigna

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

1
Отличное объяснение! Возможно, стоит включить примечание, которое на 89›самом деле означает, что целочисленная часть больше 89, что эквивалентно тому, чтобы сказать, что полное число больше или равно 90 (что по-прежнему работает нормально, потому что точно 90 никогда не должно возникать). В настоящее время комментарий в объясненном коде звучит так, как будто он проверяет более 89, тогда как ваш код проходит тестовые случаи, поэтому он явно правильно проверяет более 90.
trichoplax

1
Я отредактировал объяснение так, однако я написал «приведение к целому числу», так как я не уверен, как оператор должен вести себя к отрицательным значениям с плавающей запятой. Здесь нет проблем, так как он работает с абсолютным значением, но я предпочитаю не делать слишком строгих предположений в отношении оператора.
Osable

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
@ Титус 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;}

Ungolfed

// 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 не дает необходимой точности.
Эяль Лев

4
Добро пожаловать в PPCG! : D
mbomb007

Не будут ли имена функций конфликтовать друг с другом (так как имена оба d)?
clismique

@qwerp, другая подпись (один берет символ *, другой принимает только символ)
Эяль Лев

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)

Ungolfed

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. Чтение ввода из стандартного ввода
    • Сопоставить ввод по индексу с c("N","E","S","W")
    • Из сопоставленных индексов: совпадение с вектором градусов 0:3*90(вместо c(0,90,180,270))
    • Обратный и хранить как z
  2. Инициализировать pдо степени, эквивалентной последнему символу на входе
  3. Сохранить длину ввода как l
  4. Итеративно вычислите ближайший из двух возможных биссектрис.
  5. Если только один вход задан, устанавливается pвz
  6. Формат и печать

Попробуйте тестовые случаи на R-fiddle (обратите внимание, что это функция из-за того, что она scanне работает на R-fiddle)


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

@ trichoplax Я понимаю. Может ли ввод также быть вектором строковых символов, таких как. c("N","N","E")вместо "NNE"? Это эквивалентно не вложенному списку Python ["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

Dyalog 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○преобразовать в комплексные числа на единичном круге; е я · θ

(... )/уменьшить список с помощью ... (т.е. вставить функцию между элементами ...)

+÷(|+)... нормализованная сумма; x n - 1 + x n| х н - 1 + х н |

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

Common Lisp, 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 байтов?
Титус

@ Я думаю, что это так. Я понял , некоторые другие улучшения я добавлю это , когда я нахожусь на моем компьютере
artificialnull

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-to-int.

 ~ : 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.