Relative vs Absolute

CJam, 57 53 49

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

Previous version

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

Example:

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

Output:

FFLBFRLF
NNWEESEE

How it works

{
  "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. ";
}

JavaScript (E6) 84 86 88 92 104

Edit: using & instead of %, different operator precedence (less brackets) and works better with negative numbers
Edit2: | instead of +, op precedence again, -2. Thanks DocMax
Edit3: array comprehension is 2 chars shorter than map(), for strings

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

Test In FireFox/FireBug console

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

Output

FFLBFRLF NNWEESEE

C++, 99 97 94 bytes

−3 bytes thans to ceilingcat

The following is formatted as a lambda expression. It takes one char* argument and overwrites it.

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

For those who are not familiar with this feature (like myself 1 hour ago), use it as follows:

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

Some explanations:

  • When using code like flag ? (x = y) : (x += z), the second pair of parentheses is required in C. So I used C++ instead!
  • C++ requires specifying a return type for a function. Unless I use a lambda expression, that is! An added bonus is I don't need to waste 1 character on the name of the function.
  • The code *s*9%37&4 tests the first byte; the result is 4 if it's one of NESW; 0 otherwise
  • The code *s%11/3 converts the bytes NESW to 0, 1, 2, 3
  • The code *s%73%10 converts the bytes FRBL to 0, 9, 6, 3 (which is 0, 1, 2, 3 modulo 4)
  • When converting relative directions to absolute, I don't need the d variable. I tried rearranging code to eliminate it completely, but it seems impossible...

Tags:

Code Golf