Nord für Nord für Nord für Südost

30

Geben Sie bei einer Folge von N, S, E und W eine Peilung aus (Winkel im Uhrzeigersinn von Norden in Grad), die auf 5 Dezimalstellen genau ist.

In der herkömmlichen Kompassnotation besteht eine Zeichenfolge nur aus zwei dieser Zeichen (wie NNW oder ESE). Hier müssen Sie auch Zeichenfolgen akzeptieren, die alle 4 enthalten (wie WNNNSE) . Die Verwendung von nur 2 Symbolen ermöglicht es dem Menschen, die Bedeutung intuitiv zu verstehen. Das Zulassen von 4 Symbolen erschwert das Lesen, ermöglicht jedoch kürzere Möglichkeiten, eine Peilung mit einer bestimmten Genauigkeit zu beschreiben.

(Wie in den Kommentaren von user2357112 ausgeführt , können Sie nachweisen, dass die Zeichenfolge mit 4 Symbolen für jede Peilung genau die gleiche Länge hat wie die Zeichenfolge mit 2 Symbolen. Daher habe ich diese Herausforderung auf einer falschen Annahme basiert. Hoffentlich beeinträchtigt dieses Fehlen eines praktischen Zwecks nicht Ihre Freude an der Herausforderung ...)

Die genaue Methode wird im Folgenden beschrieben und entspricht der herkömmlichen Notation (sie wird erweitert, anstatt sie zu ändern).

Eingang

  • Die Eingabe ist eine einzelne Zeichenfolge, die nur die Zeichen enthält NESW.
  • Die Eingabe kann eine Folge von Zeichen sein, sofern dies keine Vorverarbeitung beinhaltet. Es ist beispielsweise [N, [E, [S, [W]]]]nicht zulässig , eine verschachtelte Liste zu verwenden, um die Verarbeitungsreihenfolge zu verbessern.
  • Das Verwenden anderer Zeichen ist nicht zulässig. Sie können nicht eine Reihe von nehmen 1234statt NESW.

Ausgabe

  • Die Ausgabe muss eine Dezimalzahl oder eine Zeichenfolgendarstellung von eins sein (kein Rational / Bruch).
  • Nachgestellte Nullen müssen nicht angezeigt werden. Wenn die Peilung stimmt, zählt 9.00000die Ausgabe 9auch mit 5 Dezimalstellen als korrekt.
  • Die Ausgabe liegt im Bereich [0, 360). Das heißt, einschließlich 0, aber ausschließlich 360.
  • Die Richtigkeit wird überprüft, indem die Ausgabe auf 5 Dezimalstellen gerundet wird. Wenn das Lager 0,000005 ist, wird es auf 0,00001 gerundet. Die Ausgaben 0.00001 und 0.000005 sind beide korrekt.
  • Die Ausgabe in wissenschaftlicher Notation für einige Eingaben ist akzeptabel. Zum Beispiel 1e-5anstelle von 0.00001.

Umwandlung

  • Das einzelne Zeichen Kompaßstriche N, E, S, und Wentsprechen 0, 90, 180 und 270 Grad sind.
  • Das Voranstellen einer dieser Zeichenfolgen führt dazu, dass die Peilung die Peilung des einzelnen Zeichens und die Peilung der ursprünglichen Zeichenfolge halbiert.
  • Das nächstgelegene der beiden möglichen halbierenden Lager wird so gewählt, dass NE 45 Grad und nicht 225 Grad darstellt.
  • Dies ist eindeutig, es sei denn, der zu halbierende Winkel beträgt 180 Grad. Daher NS, SN, WE, und EWentsprechen nicht definiert Lager, und der Eingang wird nie in einer dieser Punkte enden. Sie können jedoch an einer anderen Stelle in der Eingabezeichenfolge erscheinen, da dies keine Mehrdeutigkeit verursacht.
  • Wenn die letzten beiden Zeichen identisch sind, ist das letzte Zeichen überflüssig, da die Halbierung dieselbe Peilung ergibt. Da dies der Notation nichts hinzufügt, muss Ihr Code dies nicht verarbeiten. Daher NN, EE, SS, und WWentsprechen nicht definiert Lager, und der Eingang wird nie in einer dieser Punkte enden. Sie können jedoch an einer anderen Stelle in der Eingabezeichenfolge erscheinen.

Beispiele

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

Testfälle

Eine Einreichung ist nur gültig, wenn sie für alle Testfälle die richtige Ausgabe liefert. Beachten Sie, dass die Testfälle an die Grenzen dessen gehen, was mit doppelter Genauigkeit gehandhabt werden kann. Bei Sprachen, die standardmäßig mit einfacher Genauigkeit arbeiten, müssen Sie wahrscheinlich die Bytes für die Angabe der doppelten Genauigkeit verwenden, um korrekte Ausgaben zu erhalten.

Testfallausgaben werden auf 5 Dezimalstellen gerundet und auch auf eine willkürliche Genauigkeit dargestellt. Beides sind gültige Ausgaben.

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

Wertung

Das ist . Die Punktzahl ist die Länge des Quellcodes in Bytes und die kürzesten Gewinne.


Pedanterie

Ich habe den Fehler gemacht, zu denken, dass "North by North West" eine gültige Kompassrichtung ist. Ein glücklicher Fehler, da er zu einer Herausforderungsidee führte, die ich dann von der Wikipedia-Seite entdeckte :

"Der Titel des Alfred Hitchcock-Films von 1959, North by Northwest, ist eigentlich kein Richtungspunkt auf dem 32-Wind-Kompass, sondern der Film enthält einen Verweis auf Northwest Airlines. "

Es stellt sich auch heraus, dass die für diese Herausforderung verwendete Methode nur mit traditionellen Kompasspunkten bis einschließlich des 16-Punkte-Kompasses übereinstimmt. Der auf dieser Seite beschriebene 32-Wind-Kompass unterscheidet sich geringfügig und ich habe seine Existenz für diese Herausforderung leicht übersehen.

Schließlich für alle, die denken, ich sollte "Südosten" anstelle von "Südosten" verwenden,.

Trichoplax
quelle
WNNNSE<= Was wäre die Ausgabe für diesen Beispieleintrag zu Beginn Ihres Beitrags? es klingt für mich ungültig, aber es ist schwer zu sagen.
Tensibai
@Tensibai Für die Eingabe wäre WNNNSEdie Ausgabe 323.4375. Im Beispielabschnitt finden Sie eine exemplarische Vorgehensweise, die in diesem Fall auf die gleiche Weise angewendet werden würde.
Trichoplax
Ist die Eingabe in f(N,N,N,S,E)Ordnung?
Karl Napf
@ KarlNapf Ich habe den Eingabebereich erweitert, um dies zu verdeutlichen. Wenn ich das richtig verstehe, scheint Ihre Beispieleingabe mit mehreren Argumenten einer Folge von Zeichen zu entsprechen, daher wäre dies akzeptabel.
Trichoplax
2
"Das Zulassen von 4 Symbolen erschwert das Lesen, ermöglicht aber kürzere Möglichkeiten, eine Peilung mit einer bestimmten Genauigkeit zu beschreiben." - Bist du dir da sicher? Es sieht so aus, als hätten alle Eingaben, die dieselbe Peilung beschreiben, dieselbe Länge, denn wenn Sie jedem Peilung ein dyadisches Rational von 0 bis 1 zuweisen, entspricht eine Länge-N-Zeichenfolge mit N> 1 immer einem dyadischen Rational mit Nenner 2 ^ (N +1) in niedrigsten Begriffen. Das Zulassen von mehr als zwei unterschiedlichen Buchstaben in einem Lager fügt keine Ausdruckskraft hinzu. Jede Peilung, die mit 3 oder 4 Buchstaben ausgedrückt wird, kann mit 2 ausgedrückt werden.
user2357112 unterstützt Monica

Antworten:

13

JavaScript (ES6), 84 80 78 74 72 Byte

Dank @Titus ein Byte gespeichert, dank @Neil ein Byte

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

Es hat eine Weile gedauert, aber ich glaube, ich habe die Formel endlich perfektioniert ...

Testschnipsel

Erläuterung

Beginnen wir mit dem einfachsten Fall: einer Zeichenfolge. Das Ergebnis ist einfach die (0-indizierte) Position im String NESW, multipliziert mit 90.

Bei einer Zeichenfolge mit zwei Zeichen liegt das Ergebnis in der Mitte zwischen dem Ergebnis des ersten Zeichens und dem Ergebnis des zweiten Zeichens. Es gibt jedoch einen Haken: Wenn der absolute Unterschied zwischen den beiden Werten größer als 180 ist (z. B. NWoder WN), müssen wir den Winkel auf 180 einstellen, damit er nicht in die entgegengesetzte Richtung zeigt.

Bei längeren Zeichenfolgen liegt das Ergebnis in der Mitte zwischen dem Ergebnis des ersten Zeichens und dem Ergebnis des Restes der Zeichenfolge. Dies kann auf folgende Weise verallgemeinert werden:

  • Wenn es sich bei der Eingabe um ein einzelnes Zeichen handelt, geben Sie den Index in der Zeichenfolge NESWmal 90 zurück.
  • Andernfalls geben Sie den Index des ersten Zeichens in der Zeichenfolge NESWmal 45 plus die Hälfte des Ergebnisses der restlichen Zeichenfolge zurück. Addieren Sie weitere 180, wenn die absolute Differenz zwischen den beiden Werten größer als 90 ist.
ETHproductions
quelle
Hervorragende Möglichkeit, das erste Zeichen von der Saite zu trennen! Sie können ein Byte speichern, wenn Sie mit Werten geteilt durch 45 rechnen.
Titus
@Titus Ich kann mit dieser Technik 2 Bytes sparen, danke!
ETHproductions
1
searchanstatt indexOfdir ein Byte zu sparen.
Neil
@ Neil Nochmals vielen Dank! Ich schaffte es, drei weitere zu gewinnen, indem ich die Gleichung komplett umstellte.
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 durch "Ausleihen" der Idee von ETHproductions
-22 Bytes dank @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);
Link Ng
quelle
Ich denke, Sie können Ihre Reichweitenanpassung wieder auf [0,360] verkürzen, indem Sie%
Trichoplax
@trichoplax Schneidet das nicht die Dezimalstellen?
Titus
1
@Titus C #% funktioniert sowohl für Gleitkommazahlen als auch für ganze Zahlen .
Trichoplax
1
Sparen Sie 10 Bytes mit b=(b+360)%360;anstelle von b+=b>360?-360:b<0?360:0;. Speichern Sie weitere 12 Bytes, indem Sie alles durch 90 und teilen return b*90;.
Titus
1
Hier sind noch 10 Bytes: Zusammenführen der beiden Zuordnungen und Entfernen der geschweiften Klammern: b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0)+8)/2%4;Dann verteilen+8 sie auf die ternären Ergebnisseb=(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 mit dem Null-Koaleszenzoperator
  • -2 Bytes durch nicht ersetzen N(und mehr, weil das erlaubt, die Übersetzung auf den Schleifenkopf zu setzen: Nist wahr, wird aber 0in der Berechnung ausgewertet .)
  • +41 Bytes zur Korrektur der Zweiteilung ( Husten )
  • -7 Bytes direkt und -16 indirekt vom @ ETHproductions-Code inspiriert
  • -3 Bytes durch Ersetzen strtrmit einem meiner Bit-Jonglieren

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;

Dies ist offiziell das erste Mal, dass ich den Null-Koaleszenz-Operator verwende. Laufen Sie mit -r.

PHP 7.1

Negative String-Offsets in der kommenden PHP-Version sparen 12 Bytes:
Ersetzen Sie strlen($s=$argv[1])mit 0und $smit $argv[1].


Freie Bytes für (fast) alle:

  • Wenn Sie mit 0,1,2,3 anstelle von 0,90,180,270 rechnen und das Endergebnis mit 90 multiplizieren, sparen Sie zwei Bytes und können wahrscheinlich weiter Golf spielen.
  • Es gibt einige Muster in den ASCII-Codes der Zeichen. Probieren Sie eine dieser in Ihrer Sprache:
    • (a/2%6+2)%5
    • a<87?a/2&3^3:3 oder a/2&3^3*(a<87)
    • a&1?a&2|a/4&1:0
    • a/.8-1&3
Titus
quelle
5

Python 3, 133 113 Bytes

Ich habe gerade die Antwort von @ L3viathan verbessert, weil ich gerade diesen Account erstellt habe und daher noch keine Kommentare abgeben kann.

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
quelle
Willkommen bei Programming Puzzles & Code Golf und eine schöne Verbesserung ...
Trichoplax
Ich habe Ihre Antwort nicht gesehen, aber Titus hatte eine ähnliche Idee, und ich hatte eine andere, ich bin jetzt auf 98
gesunken
5

05AB1E ,48 42 37 32 Bytes

6 Bytes gespart dank Emigna. 5 Bytes gespart dank der Idee von Titus, den Bereich [0,4 [zu bearbeiten und am Ende mit 90 zu multiplizieren. 5 Bytes gespart dank Adnans Beherrschung der alten Xor / Modulo-Metamorphose.

So wird jeder Winkel während der Ausführung von Bereich [0,360] auf Bereich [0,4] reduziert. Das Ergebnis wird dann mit 90 multipliziert und angezeigt.

Ç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

Probieren Sie es online!

Mögliche Golfachsen:

  • Ich bin mir nicht sicher, ob dieser Mod 4 benötigt wird (er würde 2 Bytes sparen). Alle Testfälle funktionieren ohne, aber vielleicht gibt es einen kniffligen Fall. Ein mathematischer Beweis, um es entweder zu validieren oder zu annullieren, wäre erstklassig.
  • Es gibt keine impliziten Dinge außer dem Anzeigen des Ergebnisses (schließende Anführungszeichen, schließende Klammern).
Osable
quelle
1
Scheint nicht das gewünschte Ergebnis für die NNNNNNNNNNNNNNNNNNNNNNNEund SNNNNNNNNNNNNNNNNNNNNNNNETestfälle zu liefern .
Emigna
2
Seltsam. Jetzt mache ich das auch. Ich muss falsch oder so eingefügt haben, sorry. Sie können den Code auf kürzen v"NESW"yk90*})R¬U¦vXy+;DX-Ä89›180*+360%U}X.
Emigna
1
Tolle Erklärung! Es könnte sich lohnen, eine Anmerkung hinzuzufügen, die 89›tatsächlich bedeutet, dass der ganzzahlige Teil größer als 89 ist, was bedeutet, dass die vollständige Zahl größer oder gleich 90 ist (was immer noch gut funktioniert, da genau 90 niemals vorkommen sollte). Gegenwärtig klingt der Kommentar im erklärten Code so, als würde nach mehr als 89 gesucht, während Ihr Code die Testfälle besteht, sodass eindeutig korrekt nach mehr als 90
gesucht wird.
1
Ich habe die Erklärung so bearbeitet, aber ich habe "cast to integer" geschrieben, da ich nicht sicher bin, wie sich der Operator gegenüber negativen Gleitkommawerten verhalten soll. Es gibt hier kein Problem, da es auf dem absoluten Wert funktioniert, aber ich bevorzuge es, keine zu starken Annahmen über den Operator zu machen.
Osable
1
Sie können ersetzen v"NESW"yk})mitÇ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

Ruf fmit der Schnur an.

L3viathan
quelle
Sie können nicht die zwei haben, die ...0elsesie SyntaxErrors werfen.
Jonathan Allan
@ JonathanAllan Welche Version von Python verwenden Sie? Ich bin auf 3.5.2 und es funktioniert.
L3viathan
Ich habe es auf 3.3.3 ausgeführt - können Sie das Leerzeichen zwischen elseund -auch entfernen ? (can in 3.3.3)
Jonathan Allan
@ JonathanAllan Ja, ich kann! Danke, das erspart mir ein weiteres Byte.
L3viathan
2
@Titus d.findkann, ich hatte die genaue Idee vor einer Minute; Siehe aktualisierte Antwort.
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;
}
Eyal Lev
quelle
Die Verwendung von float bietet anscheinend nicht die erforderliche Präzision.
Eyal Lev
4
Willkommen bei PPCG! : D
mbomb007
Werden die Namen der Funktionen nicht miteinander in Konflikt stehen (da die Namen beide sind d)?
Clismique
@qwerp, andere Signatur (eine nimmt Zeichen *, andere nimmt nur Zeichen)
Eyal Lev
2
Funktionsnamen werden in C nicht wie in C ++ mit Namen verkümmert, daher müssen Sie einen von ihnen umbenennen, wenn Sie möchten, dass er C
lautet
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

Erklärt

  1. Liest die Eingabe von stdin
    • Passen Sie die Eingabe nach Index an an c("N","E","S","W")
    • Von übereinstimmenden Indizes: Übereinstimmung mit dem Gradvektor 0:3*90(anstelle von c(0,90,180,270))
    • Umkehren und speichern als z
  2. Initialisieren Sie pauf den Grad, der dem letzten Zeichen in der Eingabe entspricht
  3. Länge der Eingabe speichern als l
  4. Berechnen Sie iterativ das nächstgelegene der beiden möglichen halbierenden Lager.
  5. Wenn nur ein Eingang angegeben ist, setzen Sie ihn paufz
  6. Formatieren und drucken

Probieren Sie die Testfälle für R-Fiddle aus (beachten Sie, dass dies eine Funktion ist, da scanR-Fiddle nicht funktioniert).

Billywob
quelle
Vorausgesetzt, die Ausgabe ist auf 5 Dezimalstellen genau, müssen Sie die Rundung nicht durchführen. Aus der Herausforderung: Outputs 0.00001 and 0.000005 are both correct.So sollten Sie in der Lage sein, einige Bytes zu retten, indem Sie nicht runden
Trichoplax
@ Trichoplax Ich verstehe. Kann die Eingabe auch ein Vektor von Zeichenketten sein wie. c("N","N","E")statt "NNE"? Dies entspricht einer nicht verschachtelten Python-Liste ["N","N","E"].
Billywob
Ja. Ich wollte, dass "Sequenz" ein allgemeiner Begriff ist, der Dinge wie Arrays, Vektoren, Listen und Tupel umfasst.
Trichoplax
1
Ich denke, Sie können 4 Bytes sparen, wenn Sie alles durch 90 und printf (p * 90) teilen.
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

Vielen Dank für -2 Byte @xnor!

Fehler
quelle
Die vollständige Liste fsieht lang aus, aber ich habe Probleme, etwas Kürzeres zu finden. Am nächsten war ich f c=90*until(\i->"NESW"!!i==c)(+1)0(35). Ich glaube , Sie können ersetzen 'W'mit _.
16.
Ja, ich habe auch erwartet, dass es etwas kürzeres gibt, aber nichts gefunden. Danke für das _!
Fehler
3

Dyalog APL , 55 45 38 Bytes

Lösung

Benötigt ⎕IO←0, was bei vielen Systemen Standard ist. Fragt nach richtung

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

Erläuterung

Geht um das Problem , indem man jeden Buchstaben in eine komplexe Zahl 1∠ & thgr;a + b · i , dann tun eine Summe Reduktion von rechts nach links (APL forte) , während Normalisieren bei jedem Schritt. Das endgültige θ wird dann in Grad umgerechnet und so normiert, dass es innerhalb von [0, 360] liegt:

'NES'⍳⍞die Indizes jedes eingegebenen Buchstabens in "NES"; N → 0, E → 1, S → 2, alles andere → 3

○2÷⍨in Winkel im Bogenmaß umrechnen; θ = π · x2

¯12○auf dem Einheitskreis in komplexe Zahlen umwandeln; e i · θ

(... )/reduzieren Sie die Liste mit ... (dh fügen Sie die Funktion zwischen die Elemente von ... ein)

+÷(|+)... die normalisierte Summe; x n - 1 + x n| x n - 1 + x n |

12○in Winkel umwandeln; θ

÷○÷180×in grad umrechnen; 1π · 1180 · x

360| Divisionsrest bei Division durch 360

TryAPL online!

Anekdote

Wenn Eingabe und Ausgabe als orthogonale komplexe Einheiten wären, wäre die gesamte Lösung einfach:

(+÷(|+))/

Der Rest des Codes analysiert die Eingabe und formatiert die Ausgabe.

Adam
quelle
Ich stelle fest, dass die Testausgaben nicht mit denen in der Abfrage mit 5 Dezimalstellen übereinstimmen, was diese ungültig macht. Hat Dyalog APL die Option, doppelte Genauigkeit zu verwenden?
Trichoplax
@trichoplax Ja, ⎕FR←1287verwendet 128-Bit-Floats, aber TryAPL lässt dies nicht zu.
Adám
Ich denke, alles, was größer oder gleich 64-Bit-Floats ist, sollte funktionieren (ich habe es allerdings nur in Python getestet). Heißt das, Sie können den Code gültig machen, aber er funktioniert dann nur für Personen, die die Sprache installiert haben? Möglicherweise können Sie den vollständigen gültigen Code für die Partitur anzeigen und die Online-Version einfügen, die nicht die erforderliche Genauigkeit aufweist, damit die Benutzer sehen können, dass der Algorithmus korrekt ist.
Trichoplax
@trichoplax Tatsächlich verwendet TryAPL doppelte Genauigkeit, aber Ihre Testfälle häufen Fehler über 53 Bit an.
Adám
Wenn gezeigt werden kann, dass der Unterschied auf Unterschiede in der Interpretation des IEEE 754-Standards zurückzuführen ist, die immer noch standardkonform sind, passe ich die Testfälle an, um sicherzustellen, dass beide Interpretationen das gleiche Ergebnis mit 5 Dezimalstellen ergeben. Ich habe die Testfälle so ausgewählt, dass sie in Python das gleiche Ergebnis mit 5 Dezimalstellen für Gleitkommazahlen (doppelte Genauigkeit) und Dezimalstellen mit willkürlicher Genauigkeit liefern. Ich werde es mir ansehen.
Trichoplax
2

Gemeines Lisp, 347 327 Bytes

Vielen Dank an @Titus fürs Abheben

Dies kann wahrscheinlich mehr Golf gespielt werden, aber zumindest funktioniert es (glaube ich):

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

Verwendung:

* (f "WNE")
337.50000
NIL

Funktion dnimmt ein Zeichen N, E, W, oder Sund gibt den entsprechenden Grad. Die Funktion merhält den passenden kombinierten Grad zweier gegebener Richtungen. Die Funktion fdurchläuft die angegebene Zeichenfolge, berechnet den entsprechenden Grad und gibt ihn als Gleitkomma aus.

künstlich
quelle
Mein LISP ist verrostet, aber kann das Teilen durch 90 6 Bytes sparen?
Titus
@Titus Ich denke es würde. Ich habe einige andere Verbesserungen realisiert, also füge ich diese hinzu, wenn ich an meinem Computer bin
künstlich
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_$$$,,,".">:#,_@

Probieren Sie es online!

Erläuterung

Dies folgt einem ähnlichen Algorithmus wie bei vielen anderen Antworten, verwendet jedoch Festkomma-Berechnungen, die mit Ganzzahlen emuliert wurden, da Befunge keine Gleitkomma-Berechnungen unterstützt.

Vielen Dank an @Titus für die ASCII-to-Int-Routine.

 ~ : 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
quelle
Bedeutet das nur, dass Sie einen größeren Festkommatyp (mehr Dezimalstellen) emulieren müssen? Die Testfälle erfordern eine doppelte Genauigkeit, die nicht mehr als 17 signifikante Stellen (maximal 16 Dezimalstellen) beträgt, und 14 Dezimalstellen sind möglicherweise ausreichend.
Trichoplax