Norte por Norte por Norte por Sudeste


30

Dada uma sequência de N, S, E e W, produza um rolamento (ângulo no sentido horário em relação ao norte em graus), corrija até 5 casas decimais.

Na notação tradicional da bússola , uma sequência é composta por apenas 2 desses caracteres (como NNW ou ESE). Aqui você também deve aceitar cadeias que contêm todas as 4 (como WNNNSE) . O uso de apenas 2 símbolos permite que os humanos compreendam intuitivamente o significado. Permitir 4 símbolos torna a leitura horrível, mas permite maneiras mais curtas de descrever um rolamento com uma determinada precisão.

(Como apontado nos comentários do usuário2357112 , verifica-se que você pode provar que, para qualquer rolamento, a sequência de 4 símbolos terá exatamente o mesmo comprimento que a sequência de 2 símbolos, portanto, baseei esse desafio em uma suposição falsa. Espero que essa falta de um objetivo prático não prejudique o seu prazer no desafio ...)

O método exato é descrito abaixo e é equivalente à notação tradicional (ela se expande em vez de alterá-la).

Entrada

  • A entrada é uma única sequência que contém apenas os caracteres NESW.
  • A entrada pode ser uma sequência de caracteres, se você preferir, desde que isso não inclua nenhum pré-processamento. Por exemplo, [N, [E, [S, [W]]]]não é permitida uma lista aninhada para ajudar na ordem de processamento.
  • Não são permitidos caracteres diferentes. Você não pode usar uma sequência de caracteres em 1234vez de NESW.

Saída

  • A saída deve ser um número decimal ou representação de sequência de um (não uma fração / racional).
  • Zeros à direita não precisam ser exibidos. Se o rolamento for 9.00000, a saída 9também conta como correta com 5 casas decimais.
  • A saída está no intervalo [0, 360). Ou seja, incluindo 0, mas excluindo 360.
  • A correção é verificada arredondando a saída para 5 casas decimais. Se o rolamento for 0,000005, este arredondará para 0,00001. As saídas 0,00001 e 0,000005 estão corretas.
  • A saída em notação científica para algumas entradas é aceitável. Por exemplo, em 1e-5vez de 0.00001.

Conversão

  • A pontos de caracteres único bússola N, E, S, e Wcorrespondem a 0, 90, 180, e 270 graus respectivamente.
  • Anexar um desses a uma sequência resulta no rolamento que corta o rolamento do caractere único e o rolamento da sequência original.
  • O mais próximo dos dois possíveis rolamentos de bissecção é escolhido, de modo que NE representa 45 graus, não 225 graus.
  • Isso é inequívoco, exceto onde o ângulo a ser dividido é 180 graus. Portanto NS, SN, WE, e EWcorrespondem aos rolamentos indefinida, e a entrada nunca irá terminar em qualquer um destes. No entanto, eles podem aparecer em qualquer outro lugar na sequência de entrada, pois isso não causa ambiguidade.
  • Se os dois caracteres finais forem idênticos, o caractere final será redundante, pois a bissecção retornará o mesmo rumo. Como isso não adiciona nada à notação, seu código não precisa lidar com isso. Portanto NN, EE, SS, e WWcorrespondem aos rolamentos indefinida, e a entrada nunca irá terminar em qualquer um destes. No entanto, eles podem aparecer em qualquer outro lugar na sequência de entrada.

Exemplos

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

Casos de teste

Um envio é válido apenas se fornecer saída correta para todos os casos de teste. Observe que os casos de teste ultrapassam os limites do que pode ser tratado com precisão dupla. Para idiomas que usam a precisão única como padrão, você provavelmente precisará gastar os bytes para especificar a precisão dupla, a fim de obter resultados corretos.

As saídas do caso de teste são mostradas arredondadas para 5 casas decimais e também com precisão arbitrária. Ambos são saídas válidas.

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

Pontuação

Isso é . A pontuação é o comprimento do código-fonte em bytes e as vitórias mais curtas.


Pedantry

Cometi o erro de pensar que "North by North West" era uma direção válida da bússola. Um erro feliz, pois levou a uma idéia desafiadora, mas descobri na página da Wikipedia :

"O título do filme de Alfred Hitchcock 1959, North by Northwest, na verdade não é um ponto de direção na bússola de 32 ventos, mas o filme contém uma referência à Northwest Airlines ".

Acontece também que o método usado para esse desafio é consistente apenas com os pontos tradicionais da bússola, incluindo a bússola de 16 pontos. A bússola de 32 ventos descrita nessa página é sutilmente diferente e eu negligenciei convenientemente sua existência para esse desafio.

Finalmente, para quem pensa que eu deveria usar "Sudeste" em vez de "Sudeste",.


WNNNSE<= qual seria a saída desse exemplo de entrada no início da sua postagem? parece inválido para mim, mas é difícil dizer.
Tensibai

@Tensibai Para entrada, WNNNSEa saída seria 323.4375. Consulte a seção de exemplo para obter uma explicação passo a passo que se aplicaria da mesma maneira a este caso.
Trichoplax

A entrada é f(N,N,N,S,E)boa?
Karl Napf

@KarlNapf Expandi a seção de entrada para esclarecer. Se bem entendi, seu exemplo de entrada com vários argumentos parece equivalente a uma sequência de caracteres, portanto seria aceitável.
Trichoplax

2
"Permitir 4 símbolos torna a leitura horrível, mas permite maneiras mais curtas de descrever um rumo com uma determinada precisão". - você tem certeza sobre isso? Parece que todas as entradas que descrevem o mesmo rolamento têm o mesmo comprimento, pois se você atribuir a cada rolamento um racional diádico de 0 a 1, uma cadeia N de comprimento com N> 1 sempre corresponderá a um racional diádico com denominador 2 ^ (N +1) nos termos mais baixos. Além disso, permitir mais de 2 letras distintas em um rolamento não adiciona poder expressivo; qualquer rolamento expresso com 3 ou 4 letras pode ser expresso com 2. #
user2357112 suporta Monica 15/11

Respostas:


13

JavaScript (ES6), 84 80 78 74 72 bytes

Guardou um byte graças a @Titus, 1 graças a @Neil

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

Demorou um pouco, mas acho que finalmente aperfeiçoei a fórmula ...

Snippet de teste

Explicação

Vamos começar com o caso mais simples: uma string de caractere único. O resultado é simplesmente sua posição (indexada 0) na cadeia de caracteres NESW, multiplicada por 90.

Para uma sequência de dois caracteres, o resultado fica na metade do caminho entre o resultado do primeiro caractere e o resultado do segundo. No entanto, há um problema: se a diferença absoluta entre os dois for maior que 180 (por exemplo, NWou WN), devemos 180 no ângulo para que não aponte na direção oposta.

Para qualquer sequência mais longa, o resultado fica na metade do caminho entre o resultado do primeiro caractere e o resultado do restante da sequência. Isso pode ser generalizado da seguinte maneira:

  • Se a entrada for um único caractere, retorne seu índice na string NESWvezes 90.
  • Caso contrário, retorne o índice do primeiro caractere na cadeia NESWvezes 45, mais a metade do resultado do restante da cadeia; adicione 180 extras se a diferença absoluta entre os dois for maior que 90.

Excelente maneira de cortar o primeiro caractere da corda! Você pode salvar um byte se calcular com valores divididos por 45.
Titus

@ Titus Eu posso salvar 2 bytes com essa técnica, obrigado!
ETHproductions

1
searchem vez de indexOfeconomizar um byte.
214 Neil

@ Neil Obrigado novamente! Consegui jogar mais três, reorganizando completamente a equação.
ETHproductions

10

C # 6, 226 217 207 185 bytes

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);

Edit: -10 bytes por "emprestar" a ideia da submissão da ETHproductions
-22 bytes graças a @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);

Eu acho que você pode fazer a sua volta ajuste da gama para [0360) mais curto usando%
Trichoplax

@trichoplax Não cortou os decimais?
Titus


1
Salve 10 bytes com em b=(b+360)%360;vez de b+=b>360?-360:b<0?360:0;. Salve outros 12 bytes dividindo tudo por 90 e return b*90;.
Titus

1
Aqui estão mais 10 bytes: fundir as duas atribuições e suspensórios Remover: b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0)+8)/2%4;depois distribuir +8aos resultados ternáriosb=(b+f(c)+(b-f(c)>2?12:f(c)-b>2?4:8))/2%4;
Titus

8

PHP, 95 88 86 100 127 104 101 bytes

  • -7 bytes com o operador coalescente nulo
  • -2 bytes por não substituir N(e mais, porque isso permite colocar a conversão na cabeça do loop: Né verdade, mas é avaliada 0no cálculo.)
  • +41 bytes para corrigir a bissecção ( tosse )
  • -7 bytes diretamente e -16 indiretamente inspirados no código @ ETHproductions
  • -3 bytes substituindo strtrpor um dos meus malabarismos de bits

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;

Esta é oficialmente a primeira vez que eu uso o operador coalescente nulo. Corra com -r.

PHP 7.1

Os deslocamentos negativos de string na próxima versão do PHP economizarão 12 bytes:
Substitua strlen($s=$argv[1])por 0e $scom $argv[1].


Bytes livres para (quase) todos:

  • Calcular com 0,1,2,3 em vez de 0,90,180,270 e multiplicar o resultado final por 90 economizará dois bytes e provavelmente permitirá mais golfe.
  • Existem alguns padrões nos códigos ASCII dos caracteres. Experimente um destes no seu idioma:
    • (a/2%6+2)%5
    • a<87?a/2&3^3:3 ou a/2&3^3*(a<87)
    • a&1?a&2|a/4&1:0
    • a/.8-1&3

5

Python 3, 133 113 bytes

Estou melhorando a resposta do @ L3viathan porque acabei de fazer essa conta e, portanto, ainda não posso fazer comentários.

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

Bem-vindo à Programação Puzzles & Code Golf, e melhoria bom ...
Trichoplax

Eu não vi a sua resposta, mas Tito tinha uma ideia semelhante, mais eu tinha outro, eu vou até 98 agora :)
L3viathan

5

05AB1E ,48. 42. 37. 32 bytes

Economizou 6 bytes graças a Emigna. Economizou 5 bytes graças à idéia de Titus de trabalhar no intervalo [0,4 [e multiplicar por 90 no final. Economizou 5 bytes graças ao domínio de Adnan da antiga metamorfose xor / modulo.

Portanto, todos os ângulos são reduzidos do intervalo [0,360 [para o intervalo [0,4]] durante toda a execução. O resultado é então multiplicado por 90 e exibido.

Ç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

Experimente online!

Eixos potenciais do golfe:

  • Não tenho certeza se esse mod 4 é necessário (ele salvaria 2 bytes). Todos os casos de teste funcionam sem ele, mas talvez exista um caso complicado. Uma prova matemática para validá-lo ou anulá-lo seria de primeira qualidade.
  • Não há itens implícitos além da exibição do resultado (aspas de fechamento, colchetes de fechamento).

1
Parece não fornecer o resultado solicitado nos casos NNNNNNNNNNNNNNNNNNNNNNNEe SNNNNNNNNNNNNNNNNNNNNNNNEteste.
Emigna

2
Esquisito. Agora eu também faço. Eu devo ter colado errado ou algo assim, desculpe. Você pode reduzir o código para v"NESW"yk90*})R¬U¦vXy+;DX-Ä89›180*+360%U}X.
Emigna

1
Ótima explicação! Pode valer a pena incluir uma observação que 89›realmente significa que a parte inteira é maior que 89, o que equivale a dizer que o número completo é maior que ou igual a 90 (o que ainda funciona bem porque exatamente 90 nunca deve ocorrer). Atualmente o comentário no explicou código faz parecer que ele está verificando maior do que 89, enquanto que o seu código passa os casos de teste assim é claramente corretamente verificando maior do que 90.
Trichoplax

1
Eu editei a explicação, mas escrevi "converter para inteiro", pois não tenho certeza de como o operador deve se comportar em relação a valores negativos de ponto flutuante. Não há nenhum problema aqui, pois funciona com o valor absoluto, mas prefiro não fazer suposições muito fortes sobre o operador.
Osable

1
Você pode substituir v"NESW"yk})por Ç30^5%:)
Adnan

5

Python 3, 146 145 117 107 97 94 93 92 bytes

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

Ligue fcom a corda.


Você não pode ter os dois ...0elseque lançam SyntaxErrors.
Jonathan Allan

@ JonathanAllan Qual versão do Python você está usando? Estou no 3.5.2 e funciona.
L3viathan

Eu executei no 3.3.3 - você pode remover o espaço entre elsee -também? (cân em 3.3.3)
Jonathan Allan

@JonathanAllan Sim, eu posso! Obrigado, isso me salva outro byte.
L3viathan

2
@ Titus d.findpode, eu tive a idéia exata um minuto atrás; veja resposta atualizada.
L3viathan

5

C, 184 bytes

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;
}

Parece que usar float não fornece a precisão necessária.
Eyal Lev

4
Bem-vindo ao PPCG! : D
mbomb007

Os nomes das funções não conflitam (já que os nomes são ambos d)?
Clismique

@qwerp, assinatura diferente (uma tira de char *, outro leva apenas carvão animal)
Eyal Lev

2
Nomes de funções não são nome desconfigurado em C, como eles estão em C ++, então você precisa para renomear um deles se você quer que ele seja C.
Klas Lindbäck

3

R, 172 146 bytes

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

Explicado

  1. Ler entrada de stdin
    • Corresponde a entrada por índice a c("N","E","S","W")
    • Dos índices correspondentes: corresponda ao vetor de graus 0:3*90(em vez de c(0,90,180,270))
    • Inverta e armazene como z
  2. Inicialize pcom o grau equivalente ao último caractere na entrada
  3. Armazene o comprimento da entrada como l
  4. Iterativamente, calcule o mais próximo dos dois possíveis rolamentos de bissecção.
  5. Se apenas uma entrada for fornecida, configure pcomoz
  6. Formatar e imprimir

Experimente os casos de teste no R-fiddle (observe que esta é uma função devido ao scannão trabalho no R-fiddle)


Desde que a saída esteja correta com 5 casas decimais, não é necessário executar o arredondamento. Do desafio: Outputs 0.00001 and 0.000005 are both correct.Então você deve ser capaz de salvar alguns bytes por não arredondamento
Trichoplax

@trichoplax eu entendo. A entrada também pode ser um vetor de caracteres de seqüência de caracteres como. c("N","N","E")em vez de "NNE"? Isso equivale a uma lista python não aninhada ["N","N","E"].
Billywob

Sim. Eu pretendia que "sequência" fosse um termo geral para incluir coisas como matrizes, vetores, listas, tuplas.
Trichoplax

1
Eu acho que você pode salvar 4 bytes se você dividir tudo por 90 e printf (p * 90).
Titus

3

Haskell, 109 105 103 bytes

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

Obrigado por -2 byte @xnor!


A lista exaustiva fparece longa, mas estou tendo problemas para encontrar algo mais curto. O mais perto que fiquei foi f c=90*until(\i->"NESW"!!i==c)(+1)0(35). Eu acho que você pode substituir 'W'por _.
Xnor

Sim, eu também esperava que houvesse algo mais curto, mas não encontrei nada. Obrigado pelo _!
flawr

3

Dyalog APL , 55 45 38 bytes

Solução

Requer ⎕IO←0, que é padrão em muitos sistemas. Pede orientação.

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

Explicação

Contorna o problema convertendo cada letra em um número complexo 1∠ θa + b · i e , em seguida, reduzindo a soma da direita para a esquerda (forte da APL) enquanto normaliza a cada etapa. O θ final é então convertido em graus e normalizado para ficar entre [0, 360):

'NES'⍳⍞Os índices de cada letra de entrada em "NES"; N → 0, E → 1, S → 2, qualquer outra coisa → 3

○2÷⍨converter em ângulos em radianos; θ = π · x2

¯12○converter em números complexos no círculo unitário; e i · θ

(... )/reduza a lista com ... (ou seja, insira a função entre os elementos de ...)

+÷(|+)... a soma normalizada; x n - 1 + x n| x n - 1 + x n |

12○converter em ângulo; θ

÷○÷180×converter em graus; 1 / pi · 1 / 180 · x

360| restante da divisão quando dividido por 360

TryAPL online!

Anedota

Se a entrada e a saída fossem unidades complexas ortogonais, toda a solução seria apenas:

(+÷(|+))/

O restante do código está analisando a entrada e a formatação da saída.


Percebo que as saídas de teste não correspondem às do desafio com 5 casas decimais, tornando isso inválido. O Dyalog APL tem a opção de usar precisão dupla?
Trichoplax

@trichoplax Sim, ⎕FR←1287utiliza flutuadores de 128 bits, mas o TryAPL não permite.
Adám 15/11/16

Eu acho que qualquer coisa maior ou igual a flutuadores de 64 bits deve funcionar (só testei em Python). Isso significa que você pode validar o código, mas ele funcionará apenas para pessoas que instalaram o idioma? Talvez você possa mostrar o código válido completo para a pontuação e incluir a versão online que não possui a precisão necessária para que as pessoas possam ver que o algoritmo está correto.
Trichoplax

@trichoplax Na verdade, o TryAPL usa precisão dupla, mas seus casos de teste acumulam erros além de 53 bits.
Adám 15/11/16

Se for demonstrado que a diferença se deve a diferenças na interpretação do padrão IEEE 754, que ainda são compatíveis com o padrão, ajustarei os casos de teste para garantir que ambas as interpretações tenham o mesmo resultado com 5 casas decimais. Eu escolhi os casos de teste para que eles dessem o mesmo resultado a 5 casas decimais no Python para decimais de precisão flutuante (precisão dupla) e arbitrária. Vou dar uma olhada nisso.
Trichoplax

2

Lisp comum, 347 327 bytes

Agradecemos a @Titus por tirar alguns

Provavelmente isso pode ser jogado mais, mas pelo menos funciona (eu acho):

(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))))

Uso:

* (f "WNE")
337.50000
NIL

Função dleva um personagem N, E, W, ou Se retorna o grau adequado. Função mobtém o grau combinado apropriado de duas direções dadas. A função fpercorre a sequência fornecida, calcula o grau apropriado e a imprime como um ponto flutuante.


Meu LISP está enferrujado, mas pode dividir tudo por 90 e salvar 6 bytes?
Titus

@ Titus eu acho que sim. Eu percebi algumas outras melhorias, então adicionarei isso quando estiver no meu computador
artificialnull

2

Befunge, 183 181 175 bytes

>~#+:#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_$$$,,,".">:#,_@

Experimente online!

Explicação

Isso segue um algoritmo semelhante a muitas das outras respostas, apenas usando cálculos de ponto fixo emulados com números inteiros, já que o Befunge não suporta ponto flutuante.

Obrigado a @Titus pela rotina ASCII-para-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

Isso significa apenas que você precisa emular um tipo de ponto fixo maior (mais casas decimais)? Os casos de teste foram projetados para exigir precisão dupla, que não ultrapassa 17 algarismos significativos (máximo de 16 casas decimais) e 14 casas decimais podem ser suficientes.
Trichoplax

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.