Norte por norte por norte por sudeste

30

Dada una cadena de N, S, E y W, genera un rumbo (ángulo en sentido horario desde el Norte en grados), correcto a 5 decimales.

En la notación de brújula tradicional , una cadena se compone de solo 2 de estos caracteres (como NNW o ESE). Aquí también debe aceptar cadenas que contengan las 4 (como WNNNSE) . El uso de solo 2 símbolos permite a los humanos comprender intuitivamente el significado. Permitir 4 símbolos hace que sea horrible de leer, pero permite formas más cortas de describir un rumbo con una precisión dada.

(Como se señaló en los comentarios de user2357112 , resulta que puede probar que para cualquier demora dada, la cadena de 4 símbolos tendrá exactamente la misma longitud que la cadena de 2 símbolos, por lo que he basado este desafío en una suposición falsa. Con suerte, esta falta de un propósito práctico no le resta valor al disfrute del desafío ...)

El método exacto se describe a continuación y es equivalente a la notación tradicional (se expande en lugar de cambiarla).

Entrada

  • La entrada es una sola cadena que contiene solo los caracteres NESW.
  • La entrada puede ser una secuencia de caracteres si lo prefiere, siempre que no incluya ningún preprocesamiento. Por ejemplo, [N, [E, [S, [W]]]]no está permitido tomar una lista anidada para ayudar con el orden de procesamiento.
  • Tomar diferentes personajes no está permitido. No puede tomar una cadena de en 1234lugar de NESW.

Salida

  • La salida debe ser un número decimal o una representación de cadena de uno (no un racional / fracción).
  • No es necesario mostrar los ceros finales. Si el rumbo es 9.00000, entonces la salida 9también cuenta como correcta a 5 decimales.
  • La salida está en el rango [0, 360). Es decir, incluye 0 pero excluye 360.
  • La corrección se verifica redondeando la salida a 5 decimales. Si el rodamiento es 0.000005, esto se redondea a 0.00001. Las salidas 0.00001 y 0.000005 son correctas.
  • La producción en notación científica para algunas entradas es aceptable. Por ejemplo, en 1e-5lugar de 0.00001.

Conversión

  • Puntos El solo carácter brújula N, E, S, y Wcorresponden a 0, 90, 180, y 270 grados, respectivamente.
  • Anteponer uno de estos a una cadena da como resultado el rumbo que divide el rumbo del carácter único y el rumbo de la cadena original.
  • Se elige el más cercano de los dos posibles cojinetes de bisección, de modo que NE represente 45 grados, no 225 grados.
  • Esto no es ambiguo, excepto donde el ángulo que se bisecará es de 180 grados. Por lo tanto NS, SN, WE, y EWcorresponden a los rodamientos no definida, y la entrada nunca terminarán en cualquiera de estos. Sin embargo, pueden aparecer en cualquier otro lugar de la cadena de entrada, ya que esto no causa ambigüedad.
  • Si los dos caracteres finales son idénticos, el carácter final será redundante ya que la bisección devolverá el mismo rumbo. Como esto no agrega nada a la notación, su código no necesita manejar esto. Por lo tanto NN, EE, SS, y WWcorresponden a los rodamientos no definida, y la entrada nunca terminarán en cualquiera de estos. Sin embargo, pueden aparecer en cualquier otro lugar de la cadena de entrada.

Ejemplos

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 prueba

Un envío solo es válido si proporciona la salida correcta para todos los casos de prueba. Tenga en cuenta que los casos de prueba llegan al límite de lo que se puede manejar con doble precisión. Para los idiomas que tienen por defecto la precisión simple, probablemente necesitará gastar los bytes para especificar la precisión doble para obtener resultados correctos.

Las salidas de casos de prueba se muestran redondeadas a 5 decimales, y también a precisión arbitraria. Ambas son salidas 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

Tanteo

Este es el . La puntuación es la longitud del código fuente en bytes, y gana el más corto.


Pedantería

Cometí el error de pensar que "Norte por Noroeste" era una dirección válida de la brújula. Un error feliz, ya que condujo a una idea desafiante, pero luego descubrí en la página de Wikipedia :

"El título de la película de Alfred Hitchcock 1959, North by Northwest, en realidad no es un punto de dirección en la brújula de 32 vientos, pero el la película contiene una referencia a Northwest Airlines ".

También resulta que el método utilizado para este desafío solo es consistente con los puntos de brújula tradicionales hasta e incluyendo la brújula de 16 puntos. La brújula de 32 vientos descrita en esa página es sutilmente diferente y convenientemente he pasado por alto su existencia para este desafío.

Finalmente, para cualquiera que piense que debería usar "Sureste" en lugar de "Sureste",.

trichoplax
fuente
WNNNSE<= ¿cuál sería la salida para esta entrada de ejemplo al comienzo de su publicación? me parece inválido, pero es difícil saberlo.
Tensibai
@Tensibai Para la entrada, WNNNSEla salida sería 323.4375. Consulte la sección de ejemplos para ver un tutorial que se aplicaría de la misma manera a este caso.
trichoplax
¿La entrada f(N,N,N,S,E)está bien?
Karl Napf
@KarlNapf He ampliado la sección de entrada para aclarar. Si entiendo correctamente, su entrada de ejemplo con múltiples argumentos parece equivalente a una secuencia de caracteres, por lo que sería aceptable.
trichoplax
2
"Permitir 4 símbolos hace que sea horrible de leer, pero permite formas más cortas de describir un rumbo con una precisión dada". - ¿Estás seguro de eso? Parece que todas las entradas que describen la misma demora tienen la misma longitud, ya que si asigna a cada demora un racional diádico de 0 a 1, una cadena de longitud N con N> 1 siempre corresponde a un racional diádico con denominador 2 ^ (N +1) en los términos más bajos. Además, permitir más de 2 letras distintas en un rodamiento no agrega poder expresivo; cualquier rodamiento expresado con 3 o 4 letras puede expresarse con 2.
user2357112 es compatible con Monica el

Respuestas:

13

JavaScript (ES6), 84 80 78 74 72 bytes

Ahorré un byte gracias a @Titus, 1 gracias a @Neil

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

Me llevó un tiempo, pero creo que finalmente he perfeccionado la fórmula ...

Fragmento de prueba

Explicación

Comencemos con el caso más simple: una cadena de un solo carácter. El resultado es simplemente su posición (indexada en 0) en la cadena NESW, multiplicada por 90.

Para una cadena de dos caracteres, el resultado se encuentra a medio camino entre el resultado del primer carácter y el resultado del segundo. Sin embargo, hay un problema: si la diferencia absoluta entre los dos es mayor que 180 (por ejemplo, NWo WN), debemos 180 al ángulo para que no apunte en la dirección opuesta.

Para cualquier cadena más larga, el resultado se encuentra a medio camino entre el resultado del primer carácter y el resultado del resto de la cadena. Esto se puede generalizar de la siguiente manera:

  • Si la entrada es un carácter único, devuelve su índice en la cadena NESWmultiplicada por 90.
  • De lo contrario, devuelva el índice del primer carácter en la cadena NESWmultiplicado por 45, más la mitad del resultado del resto de la cadena; agregue 180 adicionales si la diferencia absoluta entre los dos es mayor que 90.
ETHproducciones
fuente
¡Excelente manera de cortar el primer personaje de la cadena! Puede guardar un byte si calcula con valores divididos entre 45.
Tito
@Titus Puedo ahorrar 2 bytes con esa técnica, ¡gracias!
ETHproductions
1
searchen lugar de indexOfahorrarte un byte.
Neil
@Neil Gracias de nuevo! Me las arreglé para jugar golf tres más reorganizando completamente la ecuación.
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);

Editar: -10 bytes por la idea de "préstamo" de la presentación de ETHproductions
-22 bytes gracias a @Titus

Sin golf

// 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);
Enlace Ng
fuente
Creo que puede hacer que su ajuste de rango vuelva a [0,360) más corto usando%
trichoplax
@trichoplax ¿Eso no corta los decimales?
Titus
1
Ahorre 10 bytes con en b=(b+360)%360;lugar de b+=b>360?-360:b<0?360:0;. Ahorre otros 12 bytes dividiendo todo por 90 y return b*90;.
Titus
1
Aquí hay 10 bytes más: combine las dos asignaciones y elimine las llaves: b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0)+8)/2%4;luego distribúyalo +8a los resultados ternariosb=(b+f(c)+(b-f(c)>2?12:f(c)-b>2?4:8))/2%4;
Tito
8

PHP, 95 88 86 100 127 104 101 bytes

  • -7 bytes con el operador de fusión nulo
  • -2 bytes al no reemplazar N(y más, porque eso permite poner la traducción al encabezado del bucle: Nes cierto, pero se evalúa 0en el cálculo).
  • +41 bytes para arreglar la bisección ( tos )
  • -7 bytes directamente y -16 indirectamente inspirados por el código de @ ETHproductions
  • -3 bytes reemplazando strtrcon uno de mis 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 es oficialmente la primera vez que uso el operador de fusión nula. Corre con -r.

PHP 7.1

Las compensaciones de cadena negativas en la próxima versión de PHP ahorrarán 12 bytes:
Reemplace strlen($s=$argv[1])con 0y $scon $argv[1].


Bytes gratuitos para (casi) todos:

  • Calcular con 0,1,2,3 en lugar de 0,90,180,270 y multiplicar el resultado final con 90 ahorrará dos bytes y probablemente permitirá más golf.
  • Hay algunos patrones en los códigos ASCII de los personajes. Pruebe uno de estos en su idioma:
    • (a/2%6+2)%5
    • a<87?a/2&3^3:3 o a/2&3^3*(a<87)
    • a&1?a&2|a/4&1:0
    • a/.8-1&3
Tito
fuente
5

Python 3, 133 113 bytes

Solo estoy mejorando la respuesta de @ L3viathan porque acabo de crear esta cuenta y, por lo tanto, aún no puedo hacer comentarios.

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
Moonocababa
fuente
Bienvenido a Programming Puzzles & Code Golf, y una buena mejora ...
trichoplax
No vi su respuesta, pero Titus tuvo una idea similar, además tuve otra, ahora tengo 98 años :)
L3viathan
5

05AB1E ,48 42 37 32 bytes

Guardado 6 bytes gracias a Emigna. Ahorró 5 bytes gracias a la idea de Titus de trabajar en el rango [0,4 [y multiplicar por 90 al final. Ahorró 5 bytes gracias al dominio de Adnan de la antigua metamorfosis xor / módulo.

Por lo tanto, cada ángulo se reduce del rango [0,360 [al rango [0,4 [durante toda la ejecución. El resultado se multiplica por 90 y se muestra.

Ç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

Pruébalo en línea!

Posibles ejes del golf:

  • No estoy seguro si se requiere ese mod 4 (ahorraría 2 bytes). Todos los casos de prueba funcionan sin él, pero tal vez exista un caso complicado. Una prueba matemática para validarlo o anularlo sería de primera categoría.
  • No hay cosas implícitas además de mostrar el resultado (comillas de cierre, corchetes de cierre).
Osable
fuente
1
No parece que dé el resultado solicitado en los NNNNNNNNNNNNNNNNNNNNNNNEy SNNNNNNNNNNNNNNNNNNNNNNNElas pruebas de los casos.
Emigna
2
Extraño. Ahora yo también. Debo haber pegado mal o algo, lo siento. Puede acortar el código a v"NESW"yk90*})R¬U¦vXy+;DX-Ä89›180*+360%U}X.
Emigna
1
¡Gran explicación! Podría valer la pena incluir una nota que en 89›realidad significa que la parte entera es mayor que 89, lo que equivale a decir que el número completo es mayor o igual a 90 (que todavía funciona bien porque exactamente 90 nunca debería ocurrir). Actualmente el comentario en el código explicó hace que suene como que está comprobando durante más de 89, mientras que el código pasa a los casos de prueba también verificar claramente correctamente para mayor que 90.
Trichoplax
1
Edité la explicación así, sin embargo, escribí "convertir a entero" ya que no estoy seguro de cómo debe comportarse el operador con los valores negativos de coma flotante. No hay ningún problema aquí ya que funciona en el valor absoluto, pero prefiero no hacer suposiciones demasiado fuertes sobre el operador.
Osable
1
Puede reemplazar v"NESW"yk})con Ç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

Llama fcon la cuerda.

L3viatán
fuente
No puedes tener los dos ...0elseque arrojan SyntaxErrors.
Jonathan Allan
@JonathanAllan ¿Qué versión de Python estás usando? Estoy en 3.5.2 y funciona.
L3viathan
Lo ejecuté en 3.3.3 - ¿puedes eliminar el espacio entre elsey -también? (puede en 3.3.3)
Jonathan Allan
@JonathanAllan ¡Sí puedo! Gracias, eso me ahorra otro byte.
L3viathan
2
@Titus d.findpuede, tuve la idea exacta hace un minuto; ver respuesta actualizada
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;}

Sin golf

// 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;
}
Eyal Lev
fuente
Parece que el uso de flotante no te da la precisión necesaria.
Eyal Lev
44
Bienvenido a PPCG! : D
mbomb007
¿No entrarán en conflicto los nombres de las funciones (ya que los nombres son ambos d)?
clismique
@qwerp, firma diferente (una toma char *, otra toma solo char)
Eyal Lev
2
Los nombres de las funciones no se encuentran en C, ya que están en C ++, por lo que debe cambiar el nombre de una de ellas si desea que sea C.
Klas Lindbäck
3

R, 172146 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)

Sin golf

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. Leer la entrada de stdin
    • Hacer coincidir la entrada por índice con c("N","E","S","W")
    • De índices coincidentes: coincidencia con el vector de grados 0:3*90(en lugar de c(0,90,180,270))
    • Invertir y almacenar como z
  2. Inicialice pal grado equivalente al último carácter en la entrada
  3. Almacenar la longitud de la entrada como l
  4. Iterativamente, calcule el más cercano de los dos posibles rodamientos bisectantes.
  5. Si solo se proporciona una entrada, configure penz
  6. Formatear e imprimir

Pruebe los casos de prueba en R-fiddle (tenga en cuenta que esta es una función debido a que scanno funciona en R-fiddle)

Billywob
fuente
Siempre que la salida sea correcta a 5 decimales, no necesita realizar el redondeo. Del desafío: Outputs 0.00001 and 0.000005 are both correct.Entonces debería poder guardar algunos bytes sin redondear
trichoplax
@trichoplax lo entiendo. ¿Puede la entrada también ser un vector de caracteres de cadena como? c("N","N","E")en lugar de "NNE"? Esto equivale a una lista de Python no anidada ["N","N","E"].
Billywob
Sí. Tenía la intención de "secuencia" para ser un término general que incluye elementos como matrices, vectores, listas, tuplas.
trichoplax
1
Creo que puede guardar 4 bytes si divide todo por 90 e printf (p * 90).
Tito
3

Haskell, 109105103 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

Gracias por -2 byte @xnor!

falla
fuente
La lista exhaustiva de fparece larga, pero tengo problemas para encontrar algo más corto. Lo más cerca que estuve fue f c=90*until(\i->"NESW"!!i==c)(+1)0(35). Creo que puedes reemplazarlo 'W'con _.
xnor
Sí, también esperaba que hubiera algo más corto, pero no encontré nada. Gracias por el _!
falla
3

Dyalog APL , 55 45 38 bytes

Solución

Requiere ⎕IO←0, que es el predeterminado en muchos sistemas. Pide dirección.

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

Explicación

Evita el problema convirtiendo cada letra en un número complejo 1∠ θa + b · i , luego haciendo una reducción de suma de derecha a izquierda (fuerte de APL) mientras se normaliza en cada paso. El θ final se convierte a grados y se normaliza para estar dentro de [0, 360)

'NES'⍳⍞los índices de cada letra de entrada en "NES"; N → 0, E → 1, S → 2, cualquier otra cosa → 3

○2÷⍨convertir a ángulos en radianes; θ = π · x2

¯12○convertir a números complejos en el círculo unitario; e i · θ

(... )/reduzca la lista con ... (es decir, inserte la función entre los elementos de ...)

+÷(|+)... la suma normalizada; x n - 1 + x n| x n - 1 + x n |

12○convertir a ángulo; θ

÷○÷180×convertir a grados; 1π · 1180 · x

360| resto de división cuando se divide por 360

TryAPL en línea!

Anécdota

Si la entrada y la salida fueran unidades complejas ortogonales, la solución completa sería simplemente:

(+÷(|+))/

El resto del código está analizando la entrada y el formato de salida.

Adán
fuente
Noté que las salidas de prueba no coinciden con las del desafío con 5 decimales, lo que hace que esto no sea válido. ¿Dyalog APL tiene la opción de usar doble precisión?
trichoplax
@trichoplax Sí, ⎕FR←1287utiliza flotantes de 128 bits, pero TryAPL no lo permite.
Adám
Creo que cualquier cosa mayor o igual a flotantes de 64 bits debería funcionar (aunque solo he probado en Python). ¿Esto significa que puede hacer que el código sea válido pero que solo funcionará para las personas que han instalado el idioma? Tal vez podría mostrar el código válido completo para el puntaje e incluir la versión en línea que no tiene la precisión requerida para que las personas puedan ver que el algoritmo es correcto.
trichoplax
@trichoplax En realidad, TryAPL usa doble precisión, pero sus casos de prueba acumulan errores más allá de 53 bits.
Adám
Si se puede demostrar que la diferencia se debe a diferencias en la interpretación del estándar IEEE 754, que aún cumplen con el estándar, entonces ajustaré los casos de prueba para asegurarme de que ambas interpretaciones den el mismo resultado a 5 decimales. Elegí los casos de prueba de modo que dieran el mismo resultado a 5 decimales en Python para decimales de precisión flotante (doble precisión) y arbitraria. Lo echaré un vistazo.
trichoplax
2

Common Lisp, 347 327 bytes

Gracias a @Titus por despegar algunas

Esto probablemente se pueda jugar más, pero al menos funciona (creo):

(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

La función dtoma un carácter N, E, W, o Sy vuelve el grado apropiado. La función mobtiene el grado combinado apropiado de dos direcciones dadas. La función fitera a través de la cadena provista, calcula el grado apropiado e imprime como un punto flotante.

artificial
fuente
Mi LISP está oxidado, pero ¿puedo dividir todo por 90 y guardar 6 bytes?
Titus
@Titus, creo que lo haría. Me di cuenta de algunas otras mejoras, así que agregaré esto cuando esté en mi computadora
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_$$$,,,".">:#,_@

Pruébalo en línea!

Explicación

Esto sigue un algoritmo similar a muchas de las otras respuestas, solo que está usando cálculos de punto fijo emulados con enteros ya que Befunge no admite punto flotante.

Gracias a @Titus por la rutina ASCII a 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
James Holderness
fuente
¿Eso solo significa que necesita emular un tipo de punto fijo más grande (más decimales)? Los casos de prueba están diseñados para requerir una precisión doble, que no es más de 17 cifras significativas (un máximo de 16 lugares decimales), y 14 lugares decimales posiblemente sean suficientes.
trichoplax