Z północy na północ z północy na południowy wschód


30

Biorąc pod uwagę ciąg N, S, E i W, wyślij łożysko (kąt w kierunku zgodnym z ruchem wskazówek zegara od północy w stopniach), popraw do 5 miejsc po przecinku.

W tradycyjnej notacji kompasu ciąg składa się tylko z 2 takich znaków (takich jak NNW lub ESE). Tutaj musisz również zaakceptować ciągi zawierające wszystkie 4 (jak WNNNSE) . Używanie tylko 2 symboli pozwala ludziom intuicyjnie zrozumieć znaczenie. Dopuszczenie 4 symboli sprawia, że ​​czytanie jest okropne, ale umożliwia krótsze sposoby opisywania namiaru z określoną dokładnością.

(Jak wskazano w uwagach przez user2357112 , okazuje się, można udowodnić, że dla danego łożyska, łańcuch 4 symbol będzie dokładnie taka sama jak długość łańcucha 2 symbolu, tak ja to wyzwanie oparte na fałszywym założeniu. Mam nadzieję, że ten brak praktycznego celu nie umniejsza przyjemności z wyzwania ...)

Dokładna metoda została opisana poniżej i jest równoważna tradycyjnej notacji (rozwija się na niej, a nie zmienia).

Wkład

  • Dane wejściowe to pojedynczy ciąg znaków zawierający tylko znaki NESW.
  • Dane wejściowe mogą być ciągiem znaków, jeśli wolisz, pod warunkiem, że nie obejmuje to żadnego przetwarzania wstępnego. Na przykład pobranie zagnieżdżonej listy w [N, [E, [S, [W]]]]celu ułatwienia kolejności przetwarzania jest niedozwolone.
  • Zabieranie różnych postaci jest niedozwolone. Nie możesz wziąć ciąg 1234zamiast NESW.

Wydajność

  • Dane wyjściowe muszą być liczbą dziesiętną lub reprezentacją ciągu jednego (nie wymierną / ułamkową).
  • Zera końcowe nie muszą być wyświetlane. Jeśli łożysko jest 9.00000, to wynik 9również liczy się jako poprawny do 5 miejsc po przecinku.
  • Dane wyjściowe mieszczą się w zakresie [0, 360). To znaczy, w tym 0, ale z wyłączeniem 360.
  • Poprawność jest sprawdzana poprzez zaokrąglenie wyniku do 5 miejsc po przecinku. Jeśli łożysko ma wartość 0,000005, zaokrągla to do 0,00001. Wyjścia 0,00001 i 0,000005 są poprawne.
  • Dane wyjściowe w notacji naukowej dla niektórych danych wejściowych są dopuszczalne. Na przykład 1e-5zamiast 0.00001.

Konwersja

  • Punkty pojedynczemu znakowi kompas N, E, Si Wodpowiadają 0, 90, 180 i 270 ° odpowiednio.
  • Przygotowanie jednego z nich do struny powoduje, że łożysko przecina łożysko pojedynczego znaku i łożysko oryginalnego ciągu.
  • Wybrano najbliższe z dwóch możliwych dwudzielnych łożysk, tak że NE reprezentuje 45 stopni, a nie 225 stopni.
  • Jest to jednoznaczne, chyba że kąt, który ma być podzielony na dwie części, wynosi 180 stopni. Dlatego NS, SN, WE, i EWodpowiadają niezdefiniowany łożysk, a wejście nigdy nie kończy się w każdym z nich. Mogą jednak pojawiać się gdziekolwiek indziej w ciągu wejściowym, ponieważ nie powoduje to niejednoznaczności.
  • Jeśli dwa ostatnie znaki są identyczne, ostatni znak będzie zbędny, ponieważ bisekcja zwróci ten sam kierunek. Ponieważ nic to nie dodaje do notacji, twój kod nie musi sobie z tym poradzić. Dlatego NN, EE, SS, i WWodpowiadają niezdefiniowany łożysk, a wejście nigdy nie kończy się w każdym z nich. Mogą jednak pojawiać się gdziekolwiek indziej w ciągu wejściowym.

Przykłady

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

Przypadki testowe

Przedłożenie jest ważne tylko wtedy, gdy daje poprawne dane wyjściowe dla wszystkich przypadków testowych. Zauważ, że przypadki testowe przekraczają granice tego, co można obsługiwać z podwójną precyzją. W przypadku języków domyślnie ustawionych na pojedynczą precyzję prawdopodobnie będziesz musiał wydać bajty, aby określić podwójną precyzję w celu uzyskania poprawnych wyników.

Wyniki przypadków testowych są zaokrąglone do 5 miejsc po przecinku, a także z dowolną dokładnością. Oba są prawidłowymi danymi wyjściowymi.

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

Punktacja

To jest . Wynik to długość kodu źródłowego w bajtach, a najkrótsza wygrana.


Pedanteria

Popełniłem błąd, myśląc, że „North by North West” jest ważnym kierunkiem kompasu. Szczęśliwy błąd, ponieważ doprowadził do pomysłu na wyzwanie, ale potem odkryłem na stronie Wikipedii :

„Tytuł filmu Alfreda Hitchcocka z 1959 roku, North by Northwest, nie jest właściwie punktem orientacyjnym na 32-wiatrowym kompasie, ale film zawiera odniesienie do Northwest Airlines ”.

Okazuje się również, że metoda zastosowana do tego wyzwania jest zgodna tylko z tradycyjnymi punktami kompasu do 16-punktowego kompasu włącznie. 32-wiatrowy kompas opisany na tej stronie jest nieco inny i wygodnie przeoczyłem jego istnienie w tym wyzwaniu.

Wreszcie, dla każdego, kto uważa, że ​​powinienem używać „południowo-wschodniej” zamiast „południowo-wschodniej”,.


WNNNSE<= jaki byłby wynik dla tego przykładowego wpisu na początku Twojego postu? dla mnie to brzmi nieważnie, ale trudno powiedzieć.
Tensibai

@Tensibai W przypadku danych wejściowych WNNNSEwyjście będzie 323.4375. W sekcji przykładowej znajduje się przewodnik, który miałby zastosowanie w ten sam sposób do tego przypadku.
trichoplax

Czy dane wejściowe są w f(N,N,N,S,E)porządku?
Karl Napf,

@KarlNapf Rozszerzyłem sekcję wprowadzania w celu wyjaśnienia. Jeśli dobrze rozumiem, twoje przykładowe dane wejściowe z wieloma argumentami wydają się równoważne sekwencji znaków, więc byłoby to dopuszczalne.
trichoplax

2
„Dopuszczenie 4 symboli sprawia, że ​​czytanie jest okropne, ale pozwala na krótsze sposoby opisywania namiaru z określoną dokładnością”. - Czy jesteś tego pewien? Wygląda na to, że wszystkie dane wejściowe opisujące to samo łożysko mają tę samą długość, ponieważ jeśli przypiszesz każdemu łożysku racjonalność dynastyczną od 0 do 1, łańcuch N długości o wartości N> 1 zawsze odpowiada wymiarze dyadycznemu o mianowniku 2 ^ (N +1) w najniższych kategoriach. Ponadto, dopuszczenie więcej niż 2 odrębnych liter w łożysku nie dodaje żadnej ekspresyjnej mocy; dowolne łożysko wyrażone za pomocą 3 lub 4 liter można wyrazić za pomocą 2.
użytkownik2357112 obsługuje Monikę

Odpowiedzi:


13

JavaScript (ES6), 84 80 78 74 72 bajty

Zapisano bajt dzięki @Titus, 1 dzięki @Neil

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

Minęło trochę czasu, ale myślę, że w końcu udoskonaliłem formułę ...

Testowy fragment kodu

Wyjaśnienie

Zacznijmy od najprostszego przypadku: łańcucha jednoznakowego. Wynikiem jest po prostu jego (indeksowana 0) pozycja w ciągu NESW, pomnożona przez 90.

W przypadku ciągu dwóch znaków wynik znajduje się w połowie drogi między wynikiem pierwszego znaku a wynikiem drugiego. Jest jednak pewien haczyk: jeśli absolutna różnica między nimi jest większa niż 180 (np. NWLub WN), musimy 180 do kąta, aby nie wskazywał przeciwnego kierunku.

W przypadku dowolnego dłuższego ciągu wynik leży w połowie między wynikiem pierwszego znaku i wynikiem pozostałej części łańcucha. Można to uogólnić w następujący sposób:

  • Jeśli dane wejściowe to pojedynczy znak, zwróć jego indeks w ciągu NESW90 razy.
  • W przeciwnym razie zwróć indeks pierwszego znaku w ciągu NESW45 razy plus połowę wyniku z pozostałej części łańcucha; dodać dodatkowe 180, jeśli absolutna różnica między nimi jest większa niż 90.

Doskonały sposób na odcięcie pierwszego znaku od sznurka! Możesz zapisać jeden bajt, jeśli obliczasz wartości podzielone przez 45.
Titus

@Titus Dzięki tej technice mogę zapisać 2 bajty, dzięki!
ETHprodukcje

1
searchzamiast indexOfoszczędzać bajt.
Neil,

@Neil Jeszcze raz dziękuję! Udało mi się zagrać w golfa jeszcze trzy, całkowicie zmieniając równanie.
ETHprodukcje

10

C # 6, 226 217 207 185 bajtów

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

Edycja: -10 bajtów dzięki pomysłowi „pożyczenia” ze zgłoszenia ETHproductions
-22 bajtów dzięki @Titus

Bez golfa

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

Myślę, że możesz skrócić regulację zasięgu z powrotem do [0,360), używając%
trichoplax

@trichoplax Czy to nie ułamki dziesiętne?
Tytus


1
Zaoszczędź 10 bajtów b=(b+360)%360;zamiast b+=b>360?-360:b<0?360:0;. Zaoszczędź kolejne 12 bajtów dzieląc wszystko przez 90 i return b*90;.
Tytus

1
Oto jeszcze 10 bajtów: scal dwa przypisania i usuń nawiasy klamrowe: b=(b+f(c)+(b-f(c)>2?4:f(c)-b>2?-4:0)+8)/2%4;następnie +8przekaż wyniki do potrójnych wynikówb=(b+f(c)+(b-f(c)>2?12:f(c)-b>2?4:8))/2%4;
Tytus

8

PHP, 95 88 86 100 127 104 101 bajtów

  • -7 bajtów z zerowym operatorem koalescencji
  • -2 bajty, nie zastępując N(i więcej, ponieważ pozwala to wstawić tłumaczenie do głowy pętli: Njest prawdą, ale uwzględnia to 0w obliczeniach).
  • +41 bajtów do naprawy bisekcji ( kaszel )
  • -7 bajtów bezpośrednio i -16 pośrednio zainspirowanych kodem @ ETHproductions
  • -3 bajty przez zastąpienie strtrjednym z moich żonglerek

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;

Jest to oficjalnie pierwszy raz, kiedy korzystam z zerowego operatora koalescencyjnego. Uruchom z -r.

PHP 7.1

Ujemne przesunięcia ciąg w nadchodzącej wersji PHP pozwoli zaoszczędzić 12 bajtów:
Wymień strlen($s=$argv[1])się 0i $sz $argv[1].


Darmowe bajty dla (prawie) wszystkich:

  • Obliczenie za pomocą 0,1,2,3 zamiast 0,90,180,270 i pomnożenie wyniku końcowego przez 90 pozwoli zaoszczędzić dwa bajty i prawdopodobnie pozwoli na dalszą grę w golfa.
  • W kodach ASCII znaków są pewne wzorce. Wypróbuj jedną z nich w swoim języku:
    • (a/2%6+2)%5
    • a<87?a/2&3^3:3 lub a/2&3^3*(a<87)
    • a&1?a&2|a/4&1:0
    • a/.8-1&3

5

Python 3, 133 113 bajtów

Poprawiam odpowiedź @ L3viathan, ponieważ właśnie utworzyłem to konto i dlatego nie mogę jeszcze komentować.

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

Witamy w Programowaniu łamigłówek i golfa
kodowego

Nie widziałem twojej odpowiedzi, ale Tytus miał podobny pomysł, a ponadto miałem inny, jestem teraz na poziomie 98 :)
L3viathan

5

05AB1E ,48 42 37 32 bajty

Zaoszczędź 6 bajtów dzięki Emignie. Zaoszczędzono 5 bajtów dzięki pomysłowi Tytusa, aby pracować w zakresie [0,4 [i pomnożyć przez 90 na końcu. Oszczędność 5 bajtów dzięki opanowaniu przez Adnana starożytnej metamorfozy xor / modulo.

Tak więc każdy kąt jest redukowany z zakresu [0,360 [do zakresu [0,4 [podczas wykonywania). Wynik jest następnie mnożony przez 90 i wyświetlany.

Ç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

Wypróbuj online!

Potencjalne osie gry w golfa:

  • Nie jestem pewien, czy ten mod 4 jest wymagany (pozwoliłby zaoszczędzić 2 bajty). Wszystkie przypadki testowe działają bez niego, ale być może istnieje trudna sprawa. Matematyczny dowód, aby go zweryfikować lub unieważnić, byłby na najwyższym poziomie.
  • Nie ma żadnych ukrytych treści poza wyświetlaniem wyniku (zamykające znaki cudzysłowu, zamykające nawiasy).

1
Nie wydaje się, aby dać żądany wynik na NNNNNNNNNNNNNNNNNNNNNNNEi SNNNNNNNNNNNNNNNNNNNNNNNEtestowych przypadkach.
Emigna

2
Dziwne. Teraz też to robię. Przepraszam, musiałem źle wkleić. Możesz skrócić kod do v"NESW"yk90*})R¬U¦vXy+;DX-Ä89›180*+360%U}X.
Emigna

1
Świetne wyjaśnienie! Warto dodać uwagę, że 89›tak naprawdę oznacza to, że część całkowita jest większa niż 89, co jest równoważne z twierdzeniem, że pełna liczba jest większa lub równa 90 (co nadal działa dobrze, ponieważ dokładnie 90 nigdy nie powinno wystąpić). Obecnie komentarz w objaśnionym kodzie brzmi, jakby sprawdzał na więcej niż 89, podczas gdy twój kod przechodzi przypadki testowe, więc wyraźnie poprawnie sprawdza na więcej niż 90.
trichoplax

1
Zredagowałem to wyjaśnienie, jednak napisałem „rzut na liczbę całkowitą”, ponieważ nie jestem pewien, jak operator powinien zachowywać się w stosunku do ujemnych wartości zmiennoprzecinkowych. Nie ma tu problemu, ponieważ działa na wartości bezwzględnej, ale wolę nie przyjmować zbyt silnych założeń dla operatora.
Osable

1
Można wymienić v"NESW"yk})z Ç30^5%:)
Adnan

5

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

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

Zadzwoń fza pomocą łańcucha.


Nie możesz mieć dwóch, ...0elsektóre wyrzucają Składnia Błędów.
Jonathan Allan

@JonathanAllan Jakiej wersji Pythona używasz? Mam wersję 3.5.2 i działa.
L3viathan

Uruchomiłem go na 3.3.3 - czy możesz usunąć spację między elsei -też? (może w 3.3.3)
Jonathan Allan

@JathanathanAllan Tak, mogę! Dzięki, to oszczędza mi kolejny bajt.
L3viathan

2
@Titus d.findmoże, jeszcze minutę temu miałem dokładny pomysł; zobacz zaktualizowaną odpowiedź.
L3viathan

5

C 184 bajty

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

Bez golfa

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

wydaje się, że użycie float nie zapewnia wymaganej precyzji.
Eyal Lev

4
Witamy w PPCG! : D
mbomb007

Czy nazwy funkcji nie będą ze sobą sprzeczne (ponieważ obie są nazwami d)?
clismique

@qwerp, inny podpis (jeden przyjmuje char *, drugi przyjmuje tylko char)
Eyal Lev

2
Nazwy funkcji nie są nazwami zniekształconymi w C, tak jak w C ++, więc musisz zmienić nazwę jednego z nich, jeśli chcesz, aby był C.
Klas Lindbäck

3

R, 172 146 bajtów

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)

Bez golfa

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

Wyjaśnił

  1. Czytaj dane wejściowe ze standardowego wejścia
    • Dopasuj dane wejściowe według indeksu do c("N","E","S","W")
    • Z dopasowanych wskaźników: dopasuj do wektora stopni 0:3*90(zamiast c(0,90,180,270))
    • Odwróć i zapisz jako z
  2. Zainicjuj pdo stopnia odpowiadającego ostatniemu znakowi na wejściu
  3. Zapisz długość danych wejściowych jako l
  4. Iteracyjnie obliczyć najbliższe z dwóch możliwych dwudzielnych łożysk.
  5. Jeśli podano tylko jedno wejście, ustaw pnaz
  6. Formatuj i drukuj

Wypróbuj przypadki testowe na skrzypcach typu R (zauważ, że jest to funkcja, ponieważ scannie działa na skrzypcach typu R)


Pod warunkiem, że wynik jest poprawny do 5 miejsc po przecinku, nie trzeba wykonywać zaokrąglania. Z wyzwania: Outputs 0.00001 and 0.000005 are both correct.Powinieneś być w stanie zaoszczędzić trochę bajtów, nie zaokrąglając
trichoplax

@trichoplax Rozumiem. Czy dane wejściowe mogą być również wektorem ciągów znaków takich jak. c("N","N","E")zamiast "NNE"? Jest to odpowiednik nie zagnieżdżonej listy python ["N","N","E"].
Billywob,

Tak. Zamierzałem, aby „sekwencja” była ogólnym terminem obejmującym takie rzeczy, jak tablice, wektory, listy, krotki.
trichoplax

1
Myślę, że możesz zapisać 4 bajty, jeśli podzielisz wszystko przez 90 i printf (p * 90).
Tytus

3

Haskell, 109 105 103 bajtów

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

Dzięki za -2 bajty @xnor!


Wyczerpująca lista fwygląda na długą, ale mam problem ze znalezieniem czegoś krótszego. Najbliżej było f c=90*until(\i->"NESW"!!i==c)(+1)0(35). Myślę, że można zastąpić 'W'z _.
xnor

Tak, spodziewałem się też, że będzie coś krótszego, ale niczego nie znalazłem. Dzięki za _!
flawr

3

Dyalog APL , 55 45 38 bajtów

Rozwiązanie

Wymaga ⎕IO←0, co jest domyślne w wielu systemach. Pyta o kierunek.

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

Wyjaśnienie

Rozwiązuje ten problem, konwertując każdą literę na liczbę zespoloną 1∠ θa + b · i , a następnie wykonując redukcję sumy od prawej do lewej (forte APL) podczas normalizacji na każdym kroku. Końcowe θ jest następnie konwertowane na stopnie i znormalizowane w zakresie [0, 360):

'NES'⍳⍞indeksy każdej litery wejściowej w „NES”; N → 0, E → 1, S → 2, cokolwiek innego → 3

○2÷⍨przelicz na kąty w radianach; θ = π · x2

¯12○konwertować na liczby zespolone w kole jednostkowym; e i · θ

(... )/zmniejsz listę za pomocą ... (tzn. wstaw funkcję między elementami ...)

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

12○przelicz na kąt; θ

÷○÷180×przelicz na stopnie; 1π · 1180 · x

360| pozostała część podziału po podzieleniu przez 360

Wypróbuj APL online!

Anegdota

Gdyby dane wejściowe i wyjściowe były prostymi jednostkami złożonymi, całe rozwiązanie byłoby po prostu:

(+÷(|+))/

Reszta kodu analizuje dane wejściowe i formatuje dane wyjściowe.


Zauważyłem, że wyniki testu nie pasują do wyników w wyzwaniu do 5 miejsc po przecinku, co czyni to nieważnym. Czy APL Dyalog ma opcję podwójnej precyzji?
trichoplax

@trichoplax Tak, ⎕FR←1287wykorzystuje 128-bitowe zmiennoprzecinkowe, ale TryAPL nie pozwala na to.
Adám

Myślę, że wszystko większe lub równe 64-bitowym liczbom zmiennoprzecinkowym powinno działać (testowałem jednak tylko w Pythonie). Czy to oznacza, że ​​możesz uczynić kod poprawnym, ale będzie on działał tylko dla osób, które zainstalowały ten język? Może możesz pokazać pełny poprawny kod wyniku i dołączyć wersję online, która nie ma wymaganej dokładności, aby ludzie mogli zobaczyć, że algorytm jest poprawny.
trichoplax

@trichoplax W rzeczywistości TryAPL używa podwójnej precyzji, ale przypadki testowe kumulują błędy przekraczające 53 bity.
Adám

Jeśli można wykazać, że różnica wynika z różnic w interpretacji standardu IEEE 754, które są nadal zgodne ze standardem, dostosuję przypadki testowe, aby upewnić się, że obie interpretacje dadzą ten sam wynik z dokładnością do 5 miejsc po przecinku. Wybrałem przypadki testowe, aby dały ten sam wynik do 5 miejsc po przecinku w Pythonie zarówno dla liczb zmiennoprzecinkowych (podwójna precyzja), jak i dowolnych miejsc dziesiętnych. Zajrzę do tego.
trichoplax

2

Common Lisp, 347 327 bajtów

Dzięki @Titus za zdjęcie kilku

To może być bardziej golfa, ale przynajmniej działa (myślę):

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

Stosowanie:

* (f "WNE")
337.50000
NIL

Funkcja dprzyjmuje postać N, E, W, lub Si zwraca odpowiedni stopień. Funkcja motrzymuje odpowiedni łączny stopień dwóch podanych kierunków. Funkcja fiteruje podany ciąg, oblicza odpowiedni stopień i drukuje go jako zmiennoprzecinkowy.


Mój LISP jest zardzewiały, ale czy podzielenie wszystkiego przez 90 pozwala zaoszczędzić 6 bajtów?
Tytus

@Titus Myślę, że tak. Wprowadziłem kilka innych ulepszeń, więc dodam to, gdy będę przy komputerze
sztuczny

2

Befunge, 183 181 175 bajtów

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

Wypróbuj online!

Wyjaśnienie

Jest to zgodne z algorytmem podobnym do wielu innych odpowiedzi, tylko wykorzystuje obliczenia stałoprzecinkowe emulowane liczbami całkowitymi, ponieważ Befunge nie obsługuje liczb zmiennoprzecinkowych.

Dzięki @Titus za procedurę ASCII-to-int.

 ~ : 5 6* ` _$        while ((c = getchar()) > 30)  // ends with any ctrl char or EOF
> + 2 %6 / 2            push(c / 2 % 6 + 2)         // partial conversion to int

                      do {
  5%                    dir = pop() % 5             // completes the conversion to int   
  4*:00p                dir *= 4; lowres_dir = dir  // used by the 180-flip calculation
  "Z}"4*:***            dir *= 22500000             // this is 90000000 / 4 
  20g_                  if (!first_pass) {
    +2/                   dir = (dir+last_dir)/2    // last_dir is second item on stack
    00g10g-               diff = lowres_dir - last_lowres_dir
    :8`\0\-8`+!!          flip = diff>8 || -diff>8
    "}0"*:*5**+           dir += flip * 180000000   // add 180 degrees if we need to flip
    "Z2("*:**%            dir %= 360000000          // keep within the 360 degree range
                        }
  020p                  first_pass = false
  :"Z}"4*:**/10p        last_lowres_dir = dir / 22500000
  \                     last_dir = dir              // saved as second item on stack
  :!_                 } while (!stack.empty())

$                     pop()                         // this leaves the final dir on top
5+55+/                dir = (dir + 5)/10            // round down to 5 decimal places
"d":*:*+              dir += 100000000              // add a terminating digit
                      while (true) {                // convert into chars on stack
:55 + % 6 8 * +\ : _    push(dir%10+'0'); if (!dir) break
   > < 5 5 : /+ 5 5     dir /= 10
                      }

$$$                   pop() x 3                     // drop the chars we don't need
,,,                   putchar(pop()) x 3            // output first three chars
"."                   push('.')                     // add a decimal point
>:#,_@                while(c=pop()) putchar(c)     // output the remaining chars

Czy to tylko oznacza, że ​​musisz emulować większy typ stałego punktu (więcej miejsc po przecinku)? Przypadki testowe są zaprojektowane tak, aby wymagały podwójnej precyzji, czyli nie więcej niż 17 cyfr znaczących (maksymalnie 16 miejsc po przecinku), a 14 miejsc po przecinku może być wystarczające.
trichoplax

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.