Nord da Nord da Nord da Sud Est


30

Data una stringa di N, S, E e W, produce un rilevamento (angolo in senso orario da nord in gradi), corretto con 5 decimali.

Nella notazione bussola tradizionale , una stringa è composta da solo 2 di questi caratteri (come NNW o ESE). Qui devi anche accettare le stringhe che contengono tutte e 4 (come WNNNSE) . L'uso di soli 2 simboli consente agli umani di comprendere intuitivamente il significato. Consentire 4 simboli rende orribile la lettura, ma consente modi più brevi di descrivere un rilevamento con una data precisione.

(Come sottolineato nei commenti di user2357112 , risulta che puoi dimostrare che per ogni dato rilevamento , la stringa di 4 simboli avrà esattamente la stessa lunghezza della stringa di 2 simboli, quindi ho basato questa sfida su un presupposto falso. Speriamo che questa mancanza di uno scopo pratico non toglie il godimento della sfida ...)

Il metodo esatto è descritto di seguito ed è equivalente alla notazione tradizionale (si espande su di esso anziché modificarlo).

Ingresso

  • L'input è una singola stringa contenente solo i caratteri NESW.
  • L'input può essere una sequenza di caratteri, se si preferisce, purché ciò non includa alcuna preelaborazione. Ad esempio, [N, [E, [S, [W]]]]non è consentito prendere un elenco nidificato per facilitare l'ordine di elaborazione.
  • Non è consentito assumere personaggi diversi. Non puoi prendere una stringa di 1234invece di NESW.

Produzione

  • L'output deve essere un numero decimale o una rappresentazione di stringa di uno (non un razionale / frazione).
  • Gli zeri finali non devono essere visualizzati. Se il rilevamento è 9.00000, quindi anche l'output 9conta come corretto con 5 decimali.
  • L'output è compreso nell'intervallo [0, 360). Cioè, incluso 0 ma escluso 360.
  • La correttezza viene verificata arrotondando l'output a 5 cifre decimali. Se il cuscinetto è 0,000005, questo arrotondamento a 0,00001. Le uscite 0.00001 e 0.000005 sono entrambe corrette.
  • L'output in notazione scientifica per alcuni input è accettabile. Ad esempio, 1e-5invece di 0.00001.

Conversione

  • Inoltre, il singolo carattere bussola N, E, S, e Wcorrispondono rispettivamente a 0, 90, 180, e 270 gradi.
  • Preparando uno di questi a una stringa si ottiene il rilevamento che taglia in due il rilevamento del carattere singolo e il rilevamento della stringa originale.
  • Viene scelto il più vicino dei due possibili cuscinetti bisecati, in modo che NE rappresenti 45 gradi, non 225 gradi.
  • Ciò è inequivocabile, tranne nel caso in cui l'angolo da bisecare sia di 180 gradi. Pertanto NS, SN, WE, e EWcorrispondono ai cuscinetti non definite, e l'ingresso finiranno mai in uno di questi. Possono tuttavia apparire in qualsiasi altro punto della stringa di input, poiché ciò non causa ambiguità.
  • Se gli ultimi due personaggi sono identici, il personaggio finale sarà ridondante poiché la bisection restituirà lo stesso rilevamento. Poiché ciò non aggiunge nulla alla notazione, il codice non deve gestirlo. Pertanto NN, EE, SS, e WWcorrispondono ai cuscinetti non definite, e l'ingresso finiranno mai in uno di questi. Possono tuttavia apparire in qualsiasi altro punto della stringa di input.

Esempi

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

Casi test

Un invio è valido solo se fornisce un output corretto per tutti i casi di test. Si noti che i casi di test spingono ai limiti di ciò che può essere gestito con doppia precisione. Per le lingue che hanno come impostazione predefinita la precisione singola, sarà probabilmente necessario spendere i byte per specificare la doppia precisione per ottenere output corretti.

Le uscite del test case sono mostrate arrotondate con 5 cifre decimali e con precisione arbitraria. Entrambi sono output validi.

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

punteggio

Questo è . Il punteggio è la lunghezza del codice sorgente in byte e il più breve vince.


Pedanteria

Ho fatto l'errore di pensare che "North by North West" fosse una valida direzione della bussola. Un errore felice, dal momento che ha portato a un'idea di sfida, ma ho scoperto poi dalla pagina di Wikipedia :

"Il titolo del film di Alfred Hitchcock del 1959, North by Northwest, in realtà non è un punto di direzione sulla bussola a 32 venti, ma il film contiene un riferimento a Northwest Airlines ".

Si scopre anche che il metodo utilizzato per questa sfida è coerente solo con i punti cardinali tradizionali fino alla bussola a 16 punti inclusa. La bussola a 32 venti descritta in quella pagina è leggermente diversa e ho trascurato convenientemente la sua esistenza per questa sfida.

Infine, per chiunque pensi che dovrei usare "Southeast" anziché "South East",.


WNNNSE<= quale sarebbe l'output per questa voce di esempio all'inizio del tuo post? sembra invalido per me, ma è difficile da dire.
Tensibai,

@Tensibai Per l'input WNNNSEl'uscita sarebbe 323.4375. Vedi la sezione di esempio per una procedura dettagliata che si applicherebbe allo stesso modo a questo caso.
trichoplax,

L'input è f(N,N,N,S,E)ok?
Karl Napf,

@KarlNapf Ho ampliato la sezione di input per chiarire. Se ho capito bene, il tuo esempio di input con più argomenti sembra equivalente a una sequenza di caratteri, quindi sarebbe accettabile.
trichoplax,

2
"Consentire 4 simboli rende orribile la lettura, ma consente modi più brevi di descrivere un rilevamento con una data precisione." - Sei sicuro di questo? Sembra che tutti gli input che descrivono lo stesso rilevamento abbiano la stessa lunghezza, poiché se si assegna a ciascuno di essi un razionale diadico compreso tra 0 e 1, una stringa lunghezza-N con N> 1 corrisponde sempre a un razionale diadico con denominatore 2 ^ (N +1) nei termini più bassi. Inoltre, consentire più di 2 lettere distinte in un rilevamento non aggiunge alcun potere espressivo; qualsiasi rilevamento espresso con 3 o 4 lettere può essere espresso con 2.
user2357112 supporta Monica il

Risposte:


13

JavaScript (ES6), 84 80 78 74 72 byte

Salvataggio di un byte grazie a @Titus, 1 grazie a @Neil

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

Ci è voluto un po ', ma penso di aver finalmente perfezionato la formula ...

Snippet di prova

Spiegazione

Cominciamo con il caso più semplice: una stringa a carattere singolo. Il risultato è semplicemente la sua posizione (indicizzata 0) nella stringa NESW, moltiplicata per 90.

Per una stringa di due caratteri, il risultato si trova a metà strada tra il risultato del primo carattere e il risultato del secondo. Tuttavia, c'è un problema: se la differenza assoluta tra i due è maggiore di 180 (ad esempio NWo WN), dobbiamo 180 all'angolo in modo che non punti nella direzione opposta.

Per ogni stringa più lunga, il risultato si trova a metà strada tra il risultato del primo carattere e il risultato del resto della stringa. Questo può essere generalizzato nel modo seguente:

  • Se l'input è un singolo carattere, restituisce il suo indice nella stringa per NESW90.
  • In caso contrario, restituisce l'indice del primo carattere nella stringa per NESW45 volte, più metà del risultato del resto della stringa; aggiungere un ulteriore 180 se la differenza assoluta tra i due è maggiore di 90.

Ottimo modo per tagliare il primo carattere dalla stringa! È possibile salvare un byte se si calcola con valori divisi per 45.
Titus

@Titus Posso salvare 2 byte con quella tecnica, grazie!
ETHproductions

1
searchinvece di indexOfsalvarti un byte.
Neil,

@Neil Grazie ancora! Sono riuscito a giocare a golf con altri tre riorganizzando completamente l'equazione.
ETHproductions

10

C # 6, 226 217 207 185 byte

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

Modifica: -10 byte "prendendo in prestito" l'idea dall'invio di ETHproductions
-22 byte grazie 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);

Penso che sia possibile ridurre la regolazione della portata a [0,360) più breve usando%
trichoplax

@trichoplax Non taglierai i decimali?
Tito


1
Salva 10 byte con b=(b+360)%360;invece di b+=b>360?-360:b<0?360:0;. Salva altri 12 byte dividendo tutto per 90 e return b*90;.
Tito

1
Qui ci sono altri 10 byte: unisci i due compiti e rimuovi le parentesi graffe: b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0)+8)/2%4;quindi distribuisci +8ai risultati ternarib=(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 byte

  • -7 byte con l'operatore di coalescenza null
  • -2 byte non sostituendo N(e altro, perché ciò consente di mettere la traduzione in testa al loop: Nè vero, ma valuta0 nel calcolo).
  • +41 byte per il fissaggio della dissezione ( tosse )
  • -7 byte direttamente e -16 ispirati indirettamente al codice di @ ETHproductions
  • -3 byte sostituendo strtrcon uno dei miei bit giocoleria

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;

Questa è ufficialmente la prima volta in assoluto che utilizzo l'operatore null coalescing. Corri con-r .

PHP 7.1

Gli offset di stringa negativi nella prossima versione di PHP salveranno 12 byte:
sostituisci strlen($s=$argv[1])con 0e $scon $argv[1].


Byte gratuiti per (quasi) tutti:

  • Calcolando con 0,1,2,3 anziché 0,90,180,270 e moltiplicando il risultato finale con 90 si risparmieranno due byte e probabilmente consentirà un ulteriore golf.
  • Ci sono alcuni schemi nei codici ASCII dei caratteri. Prova uno di questi nella tua lingua:
    • (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

5

Python 3, 133 113 byte

Sto solo migliorando la risposta di @ L3viathan perché ho appena creato questo account e quindi non posso ancora fare commenti.

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

Benvenuti in Programming Puzzles & Code Golf e buon miglioramento ...
trichoplax,

Non ho visto la tua risposta, ma Titus ha avuto un'idea simile, e in più ne ho avuta un'altra, sono sceso a 98 ora :)
L3viathan,

5

05AB1E ,48 42 37 32 byte

6 byte salvati grazie a Emigna. Risparmiato 5 byte grazie all'idea di Titus di lavorare sul range [0,4 [e moltiplicare per 90 alla fine. Salvati 5 byte grazie alla padronanza di Adnan delle antiche metamorfosi xor / modulo.

Quindi ogni angolo viene ridotto dalla gamma [0,360 [alla gamma [0,4 [per tutta l'esecuzione. Il risultato viene quindi moltiplicato per 90 e visualizzato.

Ç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

Provalo online!

Potenziali assi del golf:

  • Non sono sicuro se è necessaria quella mod 4 (risparmierebbe 2 byte). Tutti i casi di test funzionano senza di essa, ma forse esiste un caso complicato. Una prova matematica per convalidarla o annullarla sarebbe di prim'ordine.
  • Non ci sono elementi impliciti oltre alla visualizzazione del risultato (virgolette di chiusura, parentesi quadre di chiusura).

1
Non sembra dare il risultato richiesto sui casi di test NNNNNNNNNNNNNNNNNNNNNNNEe SNNNNNNNNNNNNNNNNNNNNNNNE.
Emigna,

2
Strano. Adesso lo faccio anche io. Devo aver incollato qualcosa di sbagliato o qualcosa del genere, scusa. Puoi abbreviare il codice fino a v"NESW"yk90*})R¬U¦vXy+;DX-Ä89›180*+360%U}X.
Emigna,

1
Grande spiegazione! Potrebbe valere la pena includere una nota che in 89›realtà significa che la parte intera è maggiore di 89, il che equivale a dire che il numero completo è maggiore o uguale a 90 (che funziona ancora bene perché esattamente 90 non dovrebbe mai accadere). Attualmente il commento nel codice spiegato fa sembrare che stia controllando per più di 89, mentre il tuo codice supera i casi di test, quindi sta chiaramente controllando correttamente per più di 90.
trichoplax

1
Ho modificato la spiegazione così, tuttavia ho scritto "cast to integer" poiché non sono sicuro di come l'operatore debba comportarsi con valori a virgola mobile negativi. Qui non ci sono problemi poiché funziona sul valore assoluto, ma preferisco non fare ipotesi troppo forti sull'operatore.
Osable,

1
Puoi sostituirlo v"NESW"yk})con Ç30^5%:)
Adnan,

5

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

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

Chiama fcon la stringa.


Non puoi avere i due ...0elseche lanciano SyntaxErrors.
Jonathan Allan,

@JonathanAllan Quale versione di Python stai usando? Sono al 3.5.2 e funziona.
L3viathan,

L'ho eseguito su 3.3.3 - puoi rimuovere lo spazio tra elsee -anche? (possibile in 3.3.3)
Jonathan Allan il

@JonathanAllan Sì, posso! Grazie, questo mi fa risparmiare un altro byte.
L3viathan

2
@Titus d.find, ho avuto l'idea esatta un minuto fa; vedi risposta aggiornata.
L3viathan,

5

C, 184 byte

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

sembra che l'utilizzo di float non ti dia la precisione necessaria.
Eyal Lev,

4
Benvenuti in PPCG! : D
mbomb007,

I nomi delle funzioni non sono in conflitto tra loro (poiché i nomi sono entrambi d)?
clismique,

@qwerp, firma diversa (uno prende carattere *, l'altro prende solo carattere)
Eyal Lev

2
I nomi delle funzioni non sono alterati in C, come in C ++, quindi è necessario rinominarne uno se si desidera che sia C.
Klas Lindbäck

3

R, 172 146 byte

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

spiegato

  1. Leggi input da stdin
    • Abbina input per indice a c("N","E","S","W")
    • Dagli indici corrispondenti: abbina al vettore dei gradi 0:3*90(invece dic(0,90,180,270) )
    • Invertire e conservare come z
  2. Inizializzare p al grado equivalente all'ultimo carattere in input
  3. Memorizza la lunghezza dell'input come l
  4. Iterativamente, calcola il più vicino dei due possibili cuscinetti bisecati.
  5. Se viene fornito un solo ingresso, impostare psuz
  6. Formatta e stampa

Prova i casi di test su R-fiddle (nota che questa è una funzione a causa del scanmancato funzionamento di R-fiddle)


A condizione che l'output sia corretto con 5 cifre decimali, non è necessario eseguire l'arrotondamento. Dalla sfida: Outputs 0.00001 and 0.000005 are both correct.quindi dovresti essere in grado di salvare alcuni byte non arrotondando
trichoplax

@trichoplax ho capito. L'input può anche essere un vettore di caratteri stringa come. c("N","N","E")invece di "NNE"? Ciò equivale a un elenco Python non nidificato ["N","N","E"].
Billywob,

Sì. Intendevo "sequenza" un termine generale per includere cose come array, vettori, elenchi, tuple.
trichoplax,

1
Penso che puoi risparmiare 4 byte se dividi tutto per 90 e printf (p * 90).
Tito

3

Haskell, 109 105 103 byte

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

Grazie per -2 byte @xnor!


L'elenco completo per fsembra lungo, ma ho problemi a trovare qualcosa di più corto. Il più vicino che ho ricevuto è stato f c=90*until(\i->"NESW"!!i==c)(+1)0(35). Penso che puoi sostituirlo 'W'con _.
xnor

Sì, mi aspettavo anche che ci fosse qualcosa di più corto, ma non ho trovato nulla. Grazie per il _!
Flawr

3

Dyalog APL , 55 45 38 byte

Soluzione

Richiede ⎕IO←0, che è predefinito su molti sistemi. Chiede una direzione.

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

Spiegazione

Risolve il problema convertendo ogni lettera in un numero complesso 1∠ θa + b · i , quindi facendo una riduzione della somma da destra a sinistra (il forte di APL) mentre si normalizza ad ogni passo. Il θ finale viene quindi convertito in gradi e normalizzato per essere entro [0, 360):

'NES'⍳⍞gli indici di ciascuna lettera di input in "NES"; N → 0, E → 1, S → 2, qualsiasi altra cosa → 3

○2÷⍨convertire in angoli in radianti; θ = π · x2

¯12○converti in numeri complessi sul cerchio unitario; e i · θ

(... )/riduci l'elenco con ... (ovvero inserisci la funzione tra gli elementi di ...)

+÷(|+)... la somma normalizzata; x n - 1 + x n| x n - 1 + x n |

12○converti in angolo; θ

÷○÷180×convertire in gradi; 1π · 1180 · x

360| resto della divisione quando diviso per 360

ProvaAPL online!

aneddoto

Se input e output fossero unità complesse ortogonali, l'intera soluzione sarebbe solo:

(+÷(|+))/

Il resto del codice sta analizzando l'input e formattando l'output.


Ho notato che le uscite del test non corrispondono a quelle della sfida con 5 cifre decimali, rendendolo non valido. Dyalog APL ha la possibilità di utilizzare la doppia precisione?
trichoplax,

@trichoplax Sì, ⎕FR←1287utilizza float a 128 bit, ma TryAPL non lo consente.
Adám,

Penso che dovrebbe funzionare qualsiasi cosa maggiore o uguale a float a 64 bit (ho provato solo in Python). Questo significa che puoi rendere valido il codice ma funzionerà solo per le persone che hanno installato la lingua? Forse potresti mostrare il codice completo valido per il punteggio e includere la versione online che non ha la precisione richiesta in modo che la gente possa vedere che l'algoritmo è corretto.
trichoplax,

@trichoplax In realtà, TryAPL utilizza una doppia precisione, ma i casi di test accumulano errori oltre i 53 bit.
Adám,

Se si può dimostrare che la differenza è dovuta alle differenze di interpretazione dello standard IEEE 754, che sono ancora conformi allo standard, allora regolerò i casi di test per assicurarmi che entrambe le interpretazioni forniscano lo stesso risultato con 5 cifre decimali. Ho scelto i casi di test in modo tale che abbiano dato lo stesso risultato a 5 cifre decimali in Python sia per i decimali float (doppia precisione) che arbitrari di precisione. Ci darò un'occhiata.
trichoplax,

2

Lisp comune, 347 327 byte

Grazie a @Titus per il decollo

Questo può probabilmente essere giocato a golf di più, ma almeno funziona (penso):

(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

Funzione dprende un personaggio N, E, W, o Se restituisce il livello appropriato. La funzione mottiene il grado combinato appropriato di due direzioni date. La funzione fscorre attraverso la stringa fornita, calcola il grado appropriato e lo stampa come virgola mobile.


Il mio LISP è arrugginito, ma se si divide tutto per 90 si risparmiano 6 byte?
Tito

@Titus Penso che sarebbe. Ho realizzato alcuni altri miglioramenti, quindi lo aggiungerò quando sarò al mio computer
Artificialnull

2

Befunge, 183 181 175 byte

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

Provalo online!

Spiegazione

Questo segue un algoritmo simile a molte delle altre risposte, solo che utilizza calcoli a virgola fissa emulati con numeri interi poiché Befunge non supporta il virgola mobile.

Grazie a @Titus per la routine da 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

Significa solo che devi emulare un tipo di punto fisso più grande (più decimali)? I casi di test sono progettati per richiedere una doppia precisione, che non è più di 17 cifre significative (un massimo di 16 cifre decimali) e 14 cifre decimali potrebbero essere sufficienti.
trichoplax,

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.