Względny a absolutny

17

Jeśli ktoś skierowany na północ w punkcie A na tej siatce chciał, aby wskazówki podążały zieloną ścieżką (ponieważ mogą tylko podążać za liniami siatki) do punktu B, możesz im powiedzieć:

Go North, North, West, East, East, South, East, East.

lub równoważnie

Go Forward, Forward, Left, Back, Forward, Right, Left, Forward.
(Jeżeli polecenie „w prawo” , „w lewo” lub „w tył” domyślnie oznacza zwrot w tym kierunku, to idź naprzód.)

Ścieżka od A do B.

Napisz funkcję z jednym argumentem, który tłumaczy te bezwzględne i względne kierunki wzdłuż tej samej ścieżki , a nie tylko w tym samym punkcie. Załóżmy, że kierowana osoba zawsze zaczyna skierowaną na północ.

Jeśli argument jest ciągiem liter NSEW, zwróć równoważne kierunki względne.
np. f("NNWEESEE")zwraca ciąg FFLBFRLF.

Jeśli argument jest ciągiem liter FBLR, zwróć równoważne bezwzględne kierunki.
np. f("FFLBFRLF")zwraca ciąg NNWEESEE.

Pusty ciąg ustępuje. Nie zakładaj żadnych innych przypadków wprowadzania danych.

Jeśli twój język nie ma funkcji lub łańcuchów, użyj tego, co wydaje się najbardziej odpowiednie.

Najkrótszy kod w bajtach wygrywa.

Hobby Calvina
źródło
Czy zakładamy, że człowiek zawsze zaczyna od głowy skierowanej na północ? W ten sposób, w kategoriach względnych, aby iść w kierunku Wschodu, wymagałoby to skrętu w prawo, zamiast po prostu mówić do przodu
Optymalizator
@Optimizer Tak, na północ. I tak do twojej drugiej kwestii. Rrówna się Ena początku.
Calvin's Hobbies
1
Tak! Zmieniłeś swoje zdjęcie, aby potwierdzić to, co zawsze myślałem!
Justin
4
Czy znów jesteś uzależniony od PPCG? ;)
Martin Ender
4
@ MartinBüttner Albo to, albo jestem bardzo dobry w ukrywaniu problemów z pracą domową. ;)
Calvin's Hobbies

Odpowiedzi:

6

CJam, 57 53 49

{"NESW""FRBL"_3$&!!:Q$:R^^f#0\{{+0\}Q*_@-R=\}%);}

Poprzednia wersja

{"NESW""FRBL"_3$0=#W>:Q{\}*:R;f#0\{{+0\}Q*_@-R=\}%);}

Przykład:

{"NESW""FRBL"_3$0=#W>:Q{\}*:R;f#0\{{+0\}Q*_@-R=\}%);}:T;
"NNWEESEE"T
N
"FFLBFRLF"T

Wynik:

FFLBFRLF
NNWEESEE

Jak to działa

{
  "NESW""FRBL"             " Push the two strings. ";
  _3$0=#W>                 " Check if the first character is in FRBL. ";
  :Q                       " Assign the result to Q. ";
  {\}*                     " Swap the two strings if true. ";
  :R;                      " Assign the top string to R and discard it. ";
  f#                       " Find each character of the input in the string. ";
  0\                       " Push a 0 under the top of the stack. ";
  {                        " For each item (index of character): ";
    {                      " If Q: ";
      +0\                  " A B -> 0 (A+B) ";
    }Q*
    _@-                    " C D -> D (D-C) ";
    R=                     " E -> E-th character in R ";
    \                      " Swap the top two items. ";
  }%
  );                       " Discard the last item in the list. ";
}
jimmy23013
źródło
6

C ++, 99 97

Poniższe sformatowano jako wyrażenie lambda. Wymaga jednego char*argumentu i zastępuje go.

[](char*s){for(int d=0,n=0,c=*s*9%37&4;*s;d+=n)c?n=*s%11/3-d:n+=*s%73%10,*s++="NESWFRBL"[c|n&3];}

Dla tych, którzy nie znają tej funkcji (jak ja 1 godzinę temu), użyj jej w następujący sposób:

#include <iostream>

int main()
{
    char s[] = "NNWEESEE";
    auto x = [](char*s){for(int d=0,n=0,c=*s*9%37&4;*s;d+=n)c?n=*s%11/3-d:n+=*s%73%10,*s++="NESWFRBL"[c|n&3];};

    x(s); // transform from absolute to relative
    std::cout << s << '\n';

    x(s); // transform from relative to absolute
    std::cout << s << '\n';
}

Kilka wyjaśnień:

  • Podczas używania kodu podobnego flag ? (x = y) : (x += z), druga para nawiasów jest wymagana w C. Więc zamiast tego użyłem C ++!
  • C ++ wymaga określenia typu zwracanego funkcji. Chyba że użyję wyrażenia lambda! Dodatkową zaletą jest to, że nie muszę marnować 1 znaku na nazwę funkcji.
  • Kod *s*9%37&4testuje pierwszy bajt; wynik wynosi 4, jeśli jest jednym z NESW; 0 w przeciwnym razie
  • Kod *s%11/3konwertuje bajty NESWna 0, 1, 2, 3
  • Kod *s%73%10konwertuje bajty FRBLna 0, 9, 6, 3 (czyli 0, 1, 2, 3 modulo 4)
  • Podczas konwersji kierunków względnych na bezwzględne nie potrzebuję dzmiennej. Próbowałem zmienić układ kodu, aby go całkowicie wyeliminować, ale wydaje się to niemożliwe ...
anatolig
źródło
1
Bardzo podoba mi się sposób, w jaki zamieniasz litery na cyfry. :)
Emil
6

JavaScript (E6) 84 86 88 92 104

Edycja: przy użyciu & zamiast% inny priorytet operatora (mniej nawiasów) i działa lepiej z liczbami ujemnymi
Edit2: | zamiast +, znowu pierwszeństwo op, -2. Dzięki DocMax
Edit3: zrozumienie tablicy jest o 2 znaki krótsze niż map () dla ciągów

F=p=>[o+=c[d=n,n=c.search(i),n<4?4|n-d&3:n=n+d&3]for(i of n=o='',c='NESWFRBL',p)]&&o

Testuj w konsoli FireFox / FireBug

console.log(F('NNWEESEE'),F('FFLBFRLF'))

Wynik

FFLBFRLF NNWEESEE
edc65
źródło
@Optimizer nie więcej. I mając nadzieję, że jeszcze bardziej się zmniejszy.
edc65
Co && ona końcu znaczy?
bebe
2
@bebe funkcja mapy zwraca tablicę, w jej ramach, jako efekt uboczny, wypełniam ciąg o, który muszę zwrócić. array && valueewaluuj do valuedowolnej tablicy do ocenytruthy
edc65
1
Wreszcie! Patrzę na ten, odkąd osiągnął 88. O ile mi czegoś nie brakuje, możesz zastąpić 4+(n-d&3)go 4|n-d&3i zapisać 2 znaki.
DocMax
4

APL, 72

{^/⍵∊A←'NESW':'FRBL'[1+4|-2-/4,3+A⍳⍵]⋄A[1+4|+\'RBLF'⍳⍵]}

Jeśli konfiguracje tłumacza można zmienić bez kary, wynik wynosi 66 , zmieniając ⎕IOna 0:

{^/⍵∊A←'NESW':'FRBL'[4|-2-/0,A⍳⍵]⋄A[4|+\'FRBL'⍳⍵]}
TwiNight
źródło
3

Python, 171 139

Nie jest to tak krótkie jak inne rozwiązania, ale myślę, że powinno to być względnie dobre dla tego, co można zrobić z Pythonem:

def f(i):a,b='NWSE','FLBR';I=map(a.find,'N'+i);return''.join((b[I[k+1]-I[k]],a[sum(map(b.find,i)[:k+1])%4])[-1in I]for k in range(len(i)))

Rozszerzona wersja dla nieco lepszej czytelności:

def f(i):
    a, b = 'NWSE', 'FLBR'
    I = map(a.find,'N'+i)     # translate to numbers assuming abs. directions
    J = map(b.index,i)        # translate to numbers assuming rel. directions
    if not -1 in I:
        o = [b[I[k+1]-I[k]] for k in range(len(i))]    # rel. dir. is differences of abs. dir.
    else:
        o = [a[sum(J[:k+1])%4] for k in range(len(i))] # abs. dir. is sum of all rel. dir. so far
    return ''.join(o)
Emil
źródło
1

Idź, 201

type q string;func F(s q)q{d,z:=byte(0),make([]byte,len(s));for i,c:=range[]byte(s){if(c^4)*167%3<2{c=c*156%5;z[i],d="LBRF"[(d-c)%4],c-1;}else{c=(c^43)*3%7-1;d=(d+c)%4;z[i]="NESW"[d];};};return q(z);}

Wersja do odczytu:

func F(s string) string {
    d, z, R, A := 0, make([]byte, len(s)), "LBRFLBR", "NESW"
    for i, c := range []byte(s) {
        switch c {
        case 'N': c = R[d+3]; d = 0
        case 'E': c = R[d+2]; d = 1
        case 'S': c = R[d+1]; d = 2
        case 'W': c = R[d]; d = 3
        case 'F': c = A[d]
        case 'R': d = (d + 1) % 4; c = A[d]
        case 'B': d = (d + 2) % 4; c = A[d]
        case 'L': d = (d + 3) % 4; c = A[d]
        }
        z[i] = c
    }
    return string(z)
}

David
źródło
1

GNU sed, 356 bajtów

Wyzwanie wymaga prostej transformacji w strumieniu postaci. sed, edytor strumieni to oczywisty wybór języka ;-)

/[FRBL]/bx                                     # Jump to label x if relative
:y                                             # label y (start of abs->rel loop)
/[FRBL]$/q                                     # quit if string ends in rel char
s/(^|[FRBL])N/\1F/;ty                          # Substitute next abs char with
s/(^|[FRBL])E/\1R/;tr                          #     rel char, then jump to
s/(^|[FRBL])S/\1B/;tb                          #     relevant rotation label if
s/(^|[FRBL])W/\1L/;tl                          #     a match was found
by                                             # loop back to y
:r;y/NESW/WNES/;by                             # Rotation labels: transform then
:b;y/NESW/SWNE/;by                             #     loop back to y
:l;y/NESW/ESWN/;by
:x                                             # label x (start of rel->abs loop)
/^[NESW]/q                                     # quit if string starts w/ abs char
/F([NESW]|$)/s/F([NESW]|$)/N\1/                # Matches for each direction:
/R([NESW]|$)/y/NESW/ESWN/;s/R([NESW]|$)/E\1/   #     rotate, then substitute
/B([NESW]|$)/y/NESW/SWNE/;s/B([NESW]|$)/S\1/
/L([NESW]|$)/y/NESW/WNES/;s/L([NESW]|$)/W\1/
bx                                             # loop back to x

(Komentarze i spacje usuwane do celów obliczania wyniku golfa)

Wynik:

$ sed -rf absrel.sed <<< NNWEESEE
FFLBFRLF
$ sed -rf absrel.sed <<< FFLBFRLF
NNWEESEE
$ 

Wyjaśnienie:

Chodzi o to, że kiedy zmieniamy układ odniesienia, zawsze istnieje bezpośrednie odwzorowanie między {N, E, S, W}i{F, R, B, L} .

W przypadku wartości bezwzględnej do względnej pracujemy w przód przez łańcuch. Dla każdego znaku możemy mapować {N, E, S, W}do {F, R, B, L}, a następnie obróć pozostałe [NESW]znaki zgodnie z charakterem po prostu odwzorowanym, a następnie przejść do następnego znaku.

W przypadku wartości względnej do absolutnej robimy odwrotnie. Pracujemy wstecz przez sznurek, obracając wszystkie kolejne [NESW]znaki zgodnie z postacią znajdującą się bezpośrednio przed nią. Następnie mapę tę postać {N, E, S, W}do {F, R, B, L}, aż dojdziemy do początku łańcucha.

Cyfrowa trauma
źródło
0

Haskell, 224

import Data.Function
i=flip(\x->length.takeWhile(/=x))
r=['F','R','B','L']
a=['N','E','S','W']
f s@(x:_)|elem x a=map((r!!).(`mod`4).(4-))$zipWith((-)`on`(i a))('N':s)(s)|True=tail$map((a!!).(`mod`4)).scanl(+)(0)$map(i r) s

To przypisuje liczby obrotów do względnych kierunków, a numery orientacji do bezwzględnych kierunków, a następnie znajduje obrót między kolejnymi orientacjami lub orientacje po kolejnych obrotach. iFunkcja znajdzie indeks w dwóch legendy.

archaephyrryx
źródło