Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

Summary

The task is to navigate the Mars rover and tell its final coordinates and direction.

Input:

First input:

First your program must take the input which will be in the following format:

[X-Coordinate],[Y-Coordinate],[Direction]

The direction must be: N or S or E or W (Starting letters of North, South, West, East)

Example: 10,20,N ( x = 10, y = 20, direction = N(North))

Second input:

The second input consists of series of R, L, M for right, left and move respectively.

For R and L (right and left) the direction of rover must change accordingly.

For M the rover must move 1 unit ahead in the direction which it was before moving.

Rules for calculating coordinates:

N = Y + 1
E = X + 1
S = Y - 1
W = X - 1

Output:

The final coordinates and the current direction of the rover.


Example:

Enter initial data:      1,2,N

Enter the instructions:  MRMLM

Output:                  2,4,N

The coordinates can be any integer and can be negative.

All the standard loopholes aren't allowed. If providing demo on sites like http://ideone.com etc. is possible, then please do so, so that I can verify :)

This is a popularity contest so be creative!

Following others' advice, I decide to make this a .

share|improve this question
    
Are there limits to the coordinates? –  Teun Pronk Jun 19 at 14:32
5  
This might be more interesting as code-golf instead of popularity-contest. What kind of bonus is given for the use of ideone? –  Kyle Kanos Jun 19 at 14:33
    
@KyleKanos I saw people using it, so just used. Rephrased it ;) –  Amit Joki Jun 19 at 14:35
6  
You know, if you're experiencing negative feedback on your challenges, try running them through the sandbox first. –  Martin Büttner Jun 19 at 14:49
1  
@Geobits thanks. Stated explicitly. –  Amit Joki Jun 19 at 15:09

24 Answers 24

Ruby ≥ 2.0, 101

E,N,W,S=*0..3
x,y,i=eval"a="+gets
gets.bytes{|c|x+=c%2*1i**i=i+1-c&3}
$><<[(x+y.i).rect,"NWSE"[i]]*?,

This solution can be tested here: https://ideone.com/C4PLdE

Note that the solution linked on ideone is one character longer (1.i instead of 1i in line 3). The reason for this is that ideone only supports Ruby 1.9, which doesn't allow the short-hand syntax for complex literals.

share|improve this answer
    
waiting to see it golf further :) –  Amit Joki Jun 19 at 17:07
    
You can replace x,y,i=eval"[#{gets}]" with eval"x,y,i="+gets to save some chars. –  voidpigeon Jun 19 at 17:11
    
@voidpigeon: I'm not sure that actually works due to eval's scoping rules: ruby -e 'eval"x=1";p x' throws a NameError for x at p x. It does work when using constants (eval"X,Y,I="+gets), but since I modify i, this would require an additional i=I to prevent warnings about redefining a constant. But maybe we're talking about different Ruby versions? –  Ventero Jun 19 at 17:14
1  
@Ventero You're right. I tested it in irb and it gave me the proper array as output so I assumed it worked. I really like the eval approach though. –  voidpigeon Jun 19 at 17:19
    
@voidpigeon Ah, you're right, that actually allows a slightly different optimization: x,y,i=eval"*a="+gets. Thanks! –  Ventero Jun 19 at 17:21

Javascript (ES6) 145 141 127

Edit: Removed the need for a translation array using method from edc65's C solution

[x,y,d]=(p=prompt)(s='NESW').split(','),[...p(d=s.search(d))].map(c=>c!='M'?(d+=c>'M'||3,d%=4):d%2?x-=d-2:y-=d-1),p([x,y,s[d]])

Ungolfed/Commented:

s='NESW' // initialize variable for direction mapping
[x,y,d]=prompt().split(',') // get first input, split by commas, map to variables x,y,d
d=s.search(d) // get numeric value for direction
[...prompt()].map(c=> // get second input, map a function to every character in it
    c!='M'? // if char is not M
        (d+=c>'M'||3, // increment d by 1 if char greater than M, otherwise 3 
         d%=4) // modulo by 4 to wrap direction
    : // else
        d%2? // if odd direction
            x-=d-2 // move x position
        : // else
            y-=d-1 // move y position
)
prompt([x,y,s[d]]) // output result
share|improve this answer
    
you can do this?! [a,b,c] = x.split(...) –  edc65 Jun 19 at 17:10
1  
@edc65 Yup! Destructuring Assignment –  nderscore Jun 19 at 17:17
    
Have a look at my C answer. maybe the g array is not needed –  edc65 Jun 20 at 5:37
    
Thanks @edc65 that saves a lot of bytes! –  nderscore Jun 20 at 14:48

Java - 327

class R{public static void main(String[]a){char c,e=a[2].charAt(0),z[]={78,69,83,87};Integer x=Integer.valueOf(a[0]),y=x.valueOf(a[1]),d=e<70?1:e==83?2:e>86?3:0,i=0;for(;i<a[3].length();d=c>81?(d+1)%4:c<77?(d+3)%4:d){c=a[3].charAt(i++);if(c==77){x=d==1?x+1:d>2?x-1:x;y=d<1?y+1:d==2?y+1:y;}}System.out.print(x+","+y+","+z[d]);}}

With whitespace:

class R{
    public static void main(String[]a){
        char c,e=a[2].charAt(0),z[]={78,69,83,87};
        Integer x=Integer.valueOf(a[0]),y=x.valueOf(a[1]),d=e<70?1:e==83?2:e>86?3:0,i=0;
        for(;i<a[3].length();d=c>81?(d+1)%4:c<77?(d+3)%4:d){
            c=a[3].charAt(i++);
            if(c==77){
                x=d==1?x+1:d>2?x-1:x;
                y=d<1?y+1:d==2?y+1:y;
            }
        }
        System.out.print(x+","+y+","+z[d]);
    }
}

As usual with Java, about half of this is just parsing the input and forming the output. The logic is pretty straightforward.

share|improve this answer

Javascript (E6) 175

Edit Fixed bug, possibly out of range return value for d

139 Logic, 36 I/O

F=(x,y,d,m,D='NESW')=>(d=D.search(d),[...m].map(s=>({M:_=>(y-=[-1,0,1,0][d],x-=[0,-1,0,1][d]),R:_=>d+=1,L:_=>d+=3}[s](),d%=4)),[x,y,D[d]]);
p=prompt,p(F(...p().split(','),p()))

Basic ungolfed

function F(x,y,d,m) // In golf code use arrow sintax instead of 'function'
{
  var D='NESW';
  d = D.search(d); // map from letters to offset position 0..3
  var driver = { // driver object, each function map one of  command letters M,R,L
    M: function() { 
      y -= [-1, 0, 1, 0][d]; // subtract to be sure to have a numeric and not string result 
      x -= [0, -1, 0, 1][d]; // subtract to be sure to have a numeric and not string result 
    },
    R: function() {
       d += 1;
    },
    L: function() {
       d += 3; // with modulo 4 will be like -= 1
    }
  }
  m = [...m]; // string to array, to use iteration function 
  m.forEach(  // array scan, in golf versione use map do nearly the same and is shorter
    function (s) {
      driver[s](); // call driver function
      d = d % 4;   // restrict value to modulo 4
    }
  );  // in golf version, use comma separated expression to avoid 'return'
  return [x,y, D[d]] // return last status
}

Test Test in javascript console in Firefox. It's simpler to test the function F avoiding the popups.

F(1,2,'N','MRMLM')

Output

[ 2, 4, "N" ]
share|improve this answer
    
Nice, this looks a lot like my solution. –  nderscore Jun 19 at 16:39

C 164 180 186

Edit Fixed input format and removed strchr
Edit Removed offset array, calc using bits

p,x,y;main(){char c,d,l[100];scanf("%d,%d,%c%s",&x,&y,&d,l);for(d=d<83?d&1:d>>2&1|2;c=l[p++];d&=3)c-77?d+=c+1:d&1?x+=d-2:(y+=1-d);printf("%d %d %c",x,y,"NESW"[d]);}

Ungolfed

p, x, y;
main()
{
  char c, d, l[100];
  scanf("%d,%d,%c%s",&x,&y,&d,l);
  for (d = d<'S'?d&1:d>>2&1|2; c = l[p++]; d &= 3)
    c-'M'
    ? d += c+1
    : d & 1 ? x+=d-2 : (y+=1-d);
  printf("%d %d %c", x, y, "NESW"[d]);
} 
/*
M 77
R 82 0101 0010 R&3+1==3
L 76 0100 1100 L&3+1==1 
*/
share|improve this answer

Python 2.7 - 197 192 bytes

q='NESW';x,y,d=raw_input().split(',');x=int(x);y=int(y);d=q.find(d);v={0:'y+',1:'x+',2:'y-',3:'x-'}
for c in raw_input():exec['d+','d-',v[d]]['RL'.find(c)]+'=1;d=d%4'
print`x`+','+`y`+','+q[d]

I'm actually super proud of this one.

Explanation

First, let's clean up this mess. I used semicolons instead of line breaks in a lot of places because I think it makes me cool. Here it is normally (this is still 197 bytes, it hasn't been ungolfed at all). Yes, there's still a semicolon, but that one actually saves a byte.

q='NESW'
x,y,d=raw_input().split(',')
x=int(x)
y=int(y)
d=q.find(d)
v={0:'y+',1:'x+',2:'y-',3:'x-'}
for c in raw_input():m=v[d];exec['d+','d-',m]['RL'.find(c)]+'=1;d=d%4'
print`x`+','+`y`+','+q[d]

Let's begin!

q='NESW'

First we define q as the string 'NESW'. We use it twice later, and len("q='NESW';qq") < len("'NESW''NESW'").

x,y,d=raw_input().split(',')

Here we split the first line of inpupt at each comma. Our x coord is stored in x, y in y, and the first letter of our direction in d.

x=int(x)
y=int(y)

Then we just make the coords ints. (I was shocked that I couldn't think of a better way to convert two strings to ints. I tried x,y=map(int,(x,y)) but that turns out to be longer.)

d=q.find(d)

This converts our direction to an integer. 0 is north, 1 is east, 2 is south and 3 is west.

v={0:'y+',1:'x+',2:'y-',3:'x-'}

This is where the fun starts.

When we go north, Y increases by 1. So this dictionary takes 0 and gives the string 'y+', for "increase y". It gives similar results for other directions: y or x followed by + or -.

We'll come back to this.

for c in raw_input():
    m=v[d]
    exec['d+','d-',m]['RL'.find(c)]+'=1;d=d%4'

I've gone to the liberty of ungolfing this one slightly.

For each character in the second line of input, we do two things. First, we set the variable m to whatever our dictionary from before gives us for our current direction. There's no reason we need this to happen every time, but it's easier than just making it happen when we need it.

Next, we create a list with three elements: 'd+', 'd-', and m. EDITOR'S NOTE: I think I can get away with not using the variable m at all. I think I can just put v[d] in the list directly. That'll save me a couple bytes if it works, but I don't feel like testing it until I'm done this explanation so y'all can deal. (Yep, it worked.)

We look for the current character of the input in the string 'RL'. str.find returns -1 if it doesn't find the character, so this converts an R to a 0, an L to a 1 and anything else to -1. Of course, the only other input we can have is M, but it's less characters to make it work for everything.

We use that number as the index for the list we created. Python list indices start at the end if they're negative, so we get the first element if the input is R, the second if it's L, and the last if it's M. For for convenience's sake, I'm about to assume that we're facing north, but a similar principle applies for other directions.

The possible values we're working with are 'd+' for R, 'd-' for L and 'y+' for M. Then, we attach '=1;d=d%4' to the end of each one. That means our possible values are...

d+=1;d=d%4
d-=1;d=d%4
y+=1;d=d%4

That's valid python code! That's valid python code that does exactly what we want to do for each of those input characters! (The d=d%4 part just keeps our directions sane. Again, don't need to do it every time, but it's less characters.)

All we have to do is execute the code we get for each character, print it out (converting our direction back to a string), and we're done!

share|improve this answer

C, 148 150 151

p,x[2];main(){char c,d,l[99],*j="%d,%d,%c%s";scanf(j,x,x+1,&d,l);for(d=d%8%5;c=l[p++];d-=c%23)x[d&1]-=c%2*~-(d&2);printf(j,*x,x[1],"ENWS"[d&3],"");}

A tweak of @edc65's solution to use my ASCII value abuse approach.

Specifically:

  • d%8%5 maps the characters ENWS to 0,1,2,3 respectively
  • c%23 turns L into 7, M into 8 and R into 13. Because d (the direction variable) is always used mod 4, this effectively makes L add -1 mod 4, M add 0 mod 4, and R add 1 mod 4.
  • d&1 is 1 for NS and 0 for EW directions.
  • d&2 is 2 for WS and 0 for NE directions.
  • ~-(d&2) is 1 for WS and -1 for NE directions.
  • c%2 is 1 for M and 0 for LR.
share|improve this answer
    
Why 23, and what is c%(2*(1-(d&2))) –  tolos Jun 20 at 16:17
    
@tolos: Added some explanation. Also shortened by 2 characters :) –  nneonneo Jun 20 at 16:46

Python 3 (with turtle graphics), 251 199 bytes

Wise pythonistas, please be gentle, for this is my first ever attempt at a program written in your fine language.

Turtles on Mars!

from turtle import*
p="NESW"
mode("logo")
x,y,d=input().split(',')
setx(int(x))
sety(int(y))
seth(p.find(d)*90)
for c in input():fd(1)if c=="M"else[lt,rt][c>'L'](90)
print(pos(),p[int(heading()/90)])

This challenge maps quite naturally to logo-style turtle graphics, for which python has an import, of course.

Reads input from two lines from STDIN.

Output:

$ { echo 1,2,N; echo MRMLM; } | python ./rover.py 
(2.00,4.00) N
$ 

What I especially like about this program is it actually graphically displays the rover's path. Add exitonclick() to the end of the program so the graphical output persists until user click:

enter image description here

I'm pretty sure this can be golfed significantly more - any suggestions welcome! I'm making this CW, because I hope the community can golf it some more.

Changes:

  • s is now a list, inlined.
  • Used ternary for body of for loop.
  • Inlined n, removed unnecessary slice.
  • Removed unnecessary space in import statement.
  • Removed import string to use builtin string method
  • Switched to Python 3 to shorten raw_input
share|improve this answer
    
@isaacg Thanks - nice golfing! –  DigitalTrauma Jun 20 at 19:28

GolfScript, 116 98 88 84 71

~'NESW':^@?:&;{4%[{&(4%:&;}{&[{)}{\)\}{(}{\(\}]=~}{&)4%:&;}]=~}/]`&^1/=

This should get the coordinates and the instructions as arguments the following way:1 2 'N' 'MRMLM'. The arguments are made into a string and are pushed into the stack.

If you want to test this online, go to web golfscript and paste a semicolon followed with a string with the arguments (e.g. ;"1 2 'N' 'MRMLM'") before the code (here's a link with an example).

Examples of output:

1 2 'N' 'MRMLM'                    -> [2 4]N  
5 6 'E' 'MMLMRMRRMMML'             -> [5 7]S
1 2 'N' 'MMMMRLMRLMMRMRMLMRMRMMRM' -> [1 8]N


My Previous Attempts

84 chars:

~:i;'NESW':k\?:d;{i(\:i;4%[{d(4%:d;}{d[{)}{\)\}{(}{\(\}]=~}{d)4%:d;}]=~i}do]`d k 1/=

88 chars:

~:i;'NESW':k\?:d;{i(\:i;'MRL'?[{d[{)}{\)\}{(}{\(\}]=~}{d)4%:d;}{d(4%:d;}]=~i}do]`d k 1/=

98 chars:

 ~1/:i;:d;{'NESW'd?}:k;{k[{)}{\)\}{(}{\(\}]=~}:M;{k'ESWN'1/=:d;}:R;{k'WNES'1/=:d;}:L;{i(\:i;~i}do d

116 chars:

[~])\~"NESW":k 1/:d?{d(1/+:d;}:f*:y;:x;{("MRL"?[{k d 0=?[{y):y}{x):x}{y(:y}{x(:x}]=~;}{f}{d)1/\+:d;}]=~.}do x y d 0=
share|improve this answer
    
btw: the old versions of the post are stored so you can see howthey were in the past (just click on the "Edited xxx ago" link) –  masterX244 Jun 22 at 9:01

Delphi (819)

When I started it was not yet. Will edit later.

Can't find a compiler online though.

uses SysUtils;type TDirection = (dNorth, dEast, dSouth, dWest);var x,y:int64;dir:TDirection;input:string;c:char;function gd(C:Char):TDirection;var o:integer;begin o:=ord(dir);if C='L'then o:=o-1else if c='R'then o:=o+1else if c='N'then exit(dNorth)else if c='E'then exit(dNorth)else if c='S'then exit(dNorth)else if c='W'then exit(dNorth);if o>3 then exit(dNorth);if o<0 then exit(dWest);exit(TDirection(o))end;function DirLetter:string;begin if dir=dNorth then exit('N');if dir=dEast then exit('E');if dir=dSouth then exit('S');if dir=dWest then exit('W');end;begin Readln(x,y,input);dir := gd(Input[1]);readln(Input);Input:=UpperCase(Input);for C in Input do begin if C<>'M' then dir:=gd(C)else case dir of dNorth:y:=y+1;dEast:x:=x+1;dSouth:y:=y-1;dWest:x:=x-1;end;end;writeln(Format('%d,%d,%s',[x,y,DirLetter]));end.

Ungolfed

uses
  SysUtils;
type
  TDirection = (dNorth, dEast, dSouth, dWest);

var
  x,y:int64;
  dir:TDirection;
  input:string;
  c:char;

  function gd(C:Char):TDirection;
  var
    o:integer;
  begin
    o:=ord(dir);
    if C='L' then
      o:=o-1
    else if c='R' then
      o:=o+1
    else if c='N' then
      exit(dNorth)
    else if c='E' then
      exit(dNorth)
    else if c='S' then
      exit(dNorth)
    else if c='W' then
      exit(dNorth);

    if o>3 then exit(dNorth);
    if o<0 then exit(dWest);
    exit(TDirection(o))
  end;
  function DirLetter:string;
  begin
    if dir=dNorth then exit('N');
    if dir=dEast then exit('E');
    if dir=dSouth then exit('S');
    if dir=dWest then exit('W');
  end;
begin
  Readln(x,y,input);
  dir := gd(Input[1]);
  readln(Input);
  Input:=UpperCase(Input);
  for C in Input do
  begin
    if C<>'M' then
      dir:=gd(C)
    else
      case dir of
        dNorth:y:=y+1;
        dEast:x:=x+1;
        dSouth:y:=y-1;
        dWest:x:=x-1;
      end;
  end;
  writeln(Format('%d,%d,%s',[x,y,DirLetter]));
end.
share|improve this answer
    
may be ideone and the option is Pascal? –  Amit Joki Jun 19 at 15:15
4  
"When I started it was not code-golf yet." Is that your excuse for coding in Delphi? ;) –  Martin Büttner Jun 19 at 15:16
    
What's up with the spaces around =? Why are they needed? Also, the variable names seem way too long to me –  Jan Dvorak Jun 19 at 17:20
    
@m.buettner ssshh, dont spill the beans :P –  Teun Pronk Jun 20 at 6:45
    
@JanDvorak Like I said, it wasn't tagged as code-golf –  Teun Pronk Jun 20 at 6:46

Javascript (353)

This is my first real attempt at code golf, seems to work at least!

var xx=[0,1,0,-1];var yy=[1,0,-1,0];var d=["N","E","S","W"];var e=0;var x,y=0;function sa(p){q=p.split(",");x=+q[0];y=+q[1];e=+d.indexOf(q[2]);}function sb(t){var g=t.split(",");for(var u=0;u<g.length;u++){if(g[u]=='R'){e++;if(e>3)e=0;}if(g[u]=='L'){e--;if(e<0)e=3;}if(g[u]=='M'){x+=+xx[e];y+=+yy[e];}}alert(x+","+y+","+d[e]);}sa(prompt());sb(prompt());
share|improve this answer
4  
I can see unnecessarily long variables names ;). Also, in code golf nobody cares about proper variable scoping, so drop those var s. –  Martin Büttner Jun 19 at 15:41

Python (263)

input =  raw_input("Initial: ")
input2 = raw_input("Command: ")

position = [int(input[0]), int(input[2]), input[4]]

bearings = "NESW"
turns = {"L" : -1, "M": 0, "R" : 1}
move = {"N" : [0, 1], "E" : [1, 0], "S" : [0, -1], "W" : [-1, 0]}

for c in input2:
    turn = turns[c];
    if (turn == 0):
        position[0] += move[position[2]][0]
        position[1] += move[position[2]][1]
    else:
        position[2] = bearings[(bearings.index(position[2]) + turn)%4]

print "Output: ", ','.join((str(s) for s in position))

There must be a more elegant way of doing this also, it doesn't need the branch after the else.

http://ideone.com/eD0FwD

The input is awful, I wanted to do it with split(',') but came across casting issues between the ints and strings. Ideally I also wanted to add the old position with the moving position... oh it's code-golf now. Oh well whatever, I'll leave it here, might give inspiration. Other ideas I had were using modulo 4 of the direction after mapping the initial bearing to an index. Also merging the turns and move arrays to one since none of the keys collide.

even so, shortening variable names and removing spaces it's 263:

i=raw_input()
j=raw_input()
p=[int(i[0]),int(i[2]),i[4]]
b="NESW"
m={"N":[0,1],"E":[1,0],"S":[0,-1],"W":[-1,0],"L":-1,"M":0,"R":1}
for c in j:
    if (m[c]==0):
        p[0]+=m[p[2]][0]
        p[1]+=m[p[2]][1]
    p[2] = b[(b.index(p[2])+m[c])%4]
print ','.join(str(s) for s in p)
share|improve this answer

C - 350

Save as rover.c:

#include<stdio.h>
#include<string.h>
#include<math.h>
int main(){char c,*C="NWSE-WN";float x,y,d,k=M_PI/2;scanf("%f,%f,%c",&x,&y,&c);d=(strchr(C,c)-C)*k;do{switch(getchar()){case'R':d+=k;break;case'L':d-=k;break;case'M':x+=sin(d);y+=cos(d);break;case EOF:printf("%g,%g,%c\n",x,y,C[(int)(sin(d)+2*cos(d)+4.5)]);}}while(!feof(stdin));return 0;}

Compile:

gcc -o rover rover.c -lm

Sample run:

$ echo 1,2,N MRMLM | ./rover
2,4,N

Ideone

Ungolfed:

#include <stdio.h>
#include <string.h>
#include <math.h>

int main()
{
    /* String is used for input and output, pi/2 == 90 degrees */
    char c, *C = "NWSE-WN";
    float x, y, d, k = M_PI/2;

    /* Get starting parameters */
    scanf("%f,%f,%c", &x, &y, &c);

    /* Convert the direction NWSE into radians */
    d = (strchr(C, c) - C) * k;

    /* Process each character */
    do
    {
        /* Recognize R(ight), L(eft), M(ove) or EOF */
        switch (getchar())
        {
            case 'R':
                /* Turn right 90 degrees */
                d += k;
                break;

            case 'L':
                /* Turn left 90 degrees */
                d -= k;
                break;

            case 'M':
                /* Advance 1 unit in the direction specified */
                x += sin(d);
                y += cos(d);
                break;

            case EOF:
                /* Output - formula is specially crafted so that S,E,W,N
                    map to indices 2,3,5,6 to reuse part of string */
                printf("%g,%g,%c\n", x, y, C[(int)(sin(d) + 2*cos(d) + 4.5)]);
        }
    }
    while (!feof(stdin));

    return 0;
}
share|improve this answer

Haskell - 412 bytes

import Text.Parsec
import Text.Parsec.String
n='N'
s='S'
e='E'
w='W'
d(x,y,c)'M'|c==n=(x,y+1,c)|c==s=(x,y-1,c)|c==e=(x+1,y,c)|c==w=(x-1,y,c)
d(x,y,c)e=(x,y,i c e)
i 'N''R'=e
i 'N''L'=w
i 'S''R'=w
i 'S''L'=e
i 'E''R'=s
i 'E''L'=n
i 'W''R'=n
i 'W''L'=s
f=many digit
g=char ','
o=oneOf
main=interact(\s->show$parse(do x<-f;g;y<-f;g;c<-o"NSEW";newline;b<-many$o"MRL";return$foldl(\x c->d x c)(read x,read y,c)b)""s)

Tested with :

$ printf "1,2,N\nMRMLM" | ./rv
Right (2,4,'N')
share|improve this answer
    
Hah hah! Great to see Haskell so far behind the pack, for a change :D –  GreenAsJade Jun 20 at 10:41
    
f=many digit MUCH LOL - SUCH WOW –  tomsmeding Jun 22 at 6:31
    
Splitting the input and using read multiple times took more characters to do than using parsec... –  gxtaillon Jun 22 at 12:14

Bash+coreutils, 159 bytes

t()(tr $2 0-3 $1<<<$d)
IFS=, read x y d
d=`t '' NESW`
for s in `fold -1`;{
[ $s = M ]&&((`t yxyx;t ++-`=1))||d=$[(d`tr LR -+<<<$s`1+4)%4]
}
echo $x,$y,`t NESW`

Input is read from 2 lines of STDIN.

Output:

$ { echo 1,2,N; echo MRMLM; } | ./rover.sh
2,4,N
$
share|improve this answer

PowerShell, 170 167 166

[int]$x,[int]$y,$e,$m="$input"-split'\W'
$d='NESW'.indexof($e)
switch([char[]]$m){'R'{$d++}'L'{$d--}'M'{iex(-split'$y++ $x++ $y-- $x--')[$d%4]}}
"$x,$y,"+'NESW'[$d%4]

Can't seem to golf this down further, which is a bit embarrassing. But all the obvious hacks don't really work here.

I can't iex the input because a) N, S, E and W would have to be functions for that to work (or I'd need to prefix that with $ and b) 1,2,N would have to parse the N in expression mode, not being able to run a command.

The switch seems to be the shortest way of doing the movement. Hash table with script blocks or strings isn't shorter either and for every other way apart from the switch I'd have the overhead of the explicit loop.

I can't get rid of the IndexOf because a pipeline with ? is longer, still.

I also can't get rid of the explicit types in the initial declaration because I have mixed types there, so a simple |%{+$_} doesn't help and every other option is longer.

Sometimes I hate input handling in PowerShell.

share|improve this answer

Python, 135 137 138

S,W,N,E=0,1,2,3;a,b,d=input();v=[b,a]
for c in map(ord,raw_input()):d+=c%23;v[d&1]+=c%2*~-(d&2)
print'%d,%d,%s'%(v[1],v[0],'SWNE'[d&3])

Abuses the ASCII values of L, M and R to avoid using any conditional statements.

Try it in ideone.

share|improve this answer

C 300 218 203 188

Try with http://www.compileonline.com/compile_c_online.php pass arguments to stdin, e.g. 1,2,N MRMLM, which are space separated. First is the initial conditions following by movement.

Edit: Huge improvement from automatic scanf formatting -- thanks to Yimin Rong for the idea.
Edit: No need to convert final direction, just index into string.
Edit: (alright I'm done now.) Shoved everything into a for loop; replaced equality check with XOR; replaced if...else with ternary. Replaced scanf and printf format strings with same variable.

x,y,p,d,c;main(){char b[9],*f="%d,%d,%c %s";scanf(f,&x,&y,&p,b);for(p=(p&16)>>3|p>>2&p&1;d=b[c++];d^77?p=((d&4)/2)+p+1&3:(y+=!p?1:p==2?-1:0,x+=p&1?p&2?-1:1:0));printf(f,x,y,"NESW"[p],"");}

ungolfed:

// uncomment to fix implicit declaration of printf
//#include <stdio.h>

// change to local definition to remove type definition warning
x,y,p,d,c;

main()
{
    //int x,y,p,d,c;
    char b[9],*f="%d,%d,%c %s";

    // Parse input. Thank you scanf.
    scanf(f,&x,&y,&p,b);

    // convert N,E,S,W into 0,1,2,3. NESW is chosen to be able
    // to rotate clockwise and counter-clockwise.
    // Look at ASCII and try to find bit fields to map to 00,01,10,11
    // This can be done using the 4th ASCII bit for the largest bit,
    // and bitwise ANDing the 0th and 2nd ASCII bit
    // N 0x4e = 0100 1110 -> xxx0 x1x0 -> program 0
    // E 0x45 = 0100 0101 -> xxx0 x1x1 -> program 1
    // S 0x53 = 0101 0011 -> xxx1 x0x1 -> program 2
    // W 0x57 = 0101 0111 -> xxx1 x1x1 -> program 3
    // This is slightly better than the ternary approach:
    //     p = p&78?0:p&69?1:p&83?2:3;
    for(p=(p&16)>>3|p>>2&p&1;

        d=b[c++];

        // Movement explanation:
        //
        //     if(d!=77)
        d^77

        // Rotate position orientation
        // R = 0x52 = 0101 0010
        // L = 0x4c = 0100 1100
        // Rotating right is the same as adding one to the position orientation,
        // modulus four; rotating left is the same as subtracting one, is the 
        // same as adding three modulus four. Use the 2nd bit of the input
        // to decide if this is a plus one or plus three operation.
        // Can drop the parenethses by replacing %4 with &3
        ? p = ((d&4)/2)+p+1&3

        // Else it must be an 'M'
        // 
        //     y += !p ? 1 : (p == 2 ? -1 : 0),
        //
        // The only condition for !p to be true is if p==0, which is North.
        // Otherwise if p==2, direction is South.
        // Comma separated so both expressions are executed without using
        // brackets.
        // 
        //     x += p&1 ? (p&2 ? -1 : 1) : 0;
        // 
        // East and West, being encoded as 1 and 3 uniquely share the first
        // (least) bit. Then the only check that needs to happen is whether
        // this is a 1 or a 3, which happens with p&2.
        :(
            y += !p ? 1 : p==2 ? -1 : 0,
            x += p&1 ? p&2 ? -1 : 1 : 0
        )
    );

    printf(f,x,y,"NESW"[p],"");

    // need a return type
    //return 0;
}

Lessons learned:

  • Know the tools. scanf does automatic type conversion, no need to call atoi or anything. For future reference, stdin will be much shorter than trying to parse command line arguments.
  • Never use if...else. Ternary is much shorter.
  • Modulo 2^x is the same as bitwise AND 2^x - 1 for positive integers.
  • Don't forget about indexing into strings (1["asdf"] = "asdf"[1]).
  • When calling scanf and printf with the same input and output, the format string can be saved and reused between the two.
  • Global variables are initialized to zero.
share|improve this answer
    
Just 8 chars for the move commands? –  edc65 Jun 19 at 20:31

Python 2.7, 170 149

N,E,S,W=q='NESW'
x,y,d=input()
d=q.find(d)
for c in raw_input():exec['d+','d-','yx'[d%2]+'+-'[d/2]]['RL'.find(c)]+'=1;d%=4'
print`x`+','+`y`+','+q[d]

Things I changed from the original:

Aliased raw_input, changed the v[d] dictionary, which should have been a list anyways, to some string selection, used %=.

Edit: used tuple unpacking and eval(raw_input())==input() to save 21 characters.

Heavily borrowed from @undergroundmonorail, but with lots of improvements.

share|improve this answer
    
Nice! I like this a lot. –  undergroundmonorail Jun 20 at 3:13

Bash/SHELF, 243 235

"SHEll goLF" is a golfing library for Bash which provides a few useful aliases. This is a valid answer as the library existed and was on GitHub before the challenge was posted.

Sorry, I can't get this to work on ideone.

How to run

This takes the initial position (separated by commas as specified; this adds a lot of characters to the code) as its first argument, and the instructions on standard input.

source shelf.sh #you must load SHELF first
source rover.sh 1,2,N<<<MRMLM #now run the script via source so it has access to SHELF

Sample output

2,4,N

Code

o=$1
D(){ o=`y NESW $1<<<$o`;}
for x in `Y . '& '`;{
d $x R&&D ESWN
d $x L&&D WNES
d $x M&&z=(`y , \ <<<$o`)&&case ${z[2]} in N) z[1]=$[z[1]+1];;S) z[1]=$[z[1]-1];;W) z[0]=$[z[0]-1];;E) z[0]=$[z[0]+1];;esac&&o=`P ${z[@]}|y \  ,`
}
p $o

Explanation

d is for comparison; it returns 0 if its two arguments are equal and 1 otherwise, it can then have other commands chained onto it with && and ||.

y is like tr (but done through sed).

Y is like sed 's/.../.../g' for its two arguments.

P is echo -e -n; p is just echo -e.

o=$1 #save first argument to variable
D(){ o=`y NESW $1<<<$o`;} #define an alias to turn R or L
for x in `Y . '& '`;{ #add a space after every character on stdin and loop for each one
d $x R&&D ESWN #turn R using alias
d $x L&&D WNES #turn L using alias

The next bit is profoundly ugly, with about 145 chars on one line. If the current command is M, turn the commas in $o into spaces, convert to array and save to $z. Then, do a switch...case block for the last element of $z (the direction the rover is pointing. Change coordinates accordingly, then convert $z back into a comma-separated string and save to $o.

d $x M&&z=(`y , \ <<<$o`)&&case ${z[2]} in N) z[1]=$[z[1]+1];;S) z[1]=$[z[1]-1];;W) z[0]=$[z[0]-1];;E) z[0]=$[z[0]+1];;esac&&o=`P ${z[@]}|y \  ,`
} #end loop
p $o #print output
share|improve this answer
1  
Shouldn't the sourcing of shelf.sh be part of the solution instead? Like you'd have to require certain packages in Ruby or import them in Python as well if you need them. –  Joey Jun 20 at 12:55
    
@Joey good point, but I don't think people import PYG when writing a Python program with it, or Rebmu (AFAIK) when writing a Rebol program with it –  professorfish Jun 20 at 14:26

Haskell, 291

data D=W|S|E|N deriving(Show,Read,Enum)
main=interact$(\(x,y)->tail$map show y++[show(toEnum x::D)]>>=(',':)).(\(a:b:_)->foldl(\(f,j@[g,h])i->case i of 'M'->(f,[g+rem(f-1)2,h+rem(f-2)2]);'L'->(mod(f+1)4,j);'R'->(mod(f-1)4,j))((\(c,d,e)->(fromEnum(e::D),[c::Int,d]))$read('(':a++")"))b).lines

I wasn't sure how flexible the input and output string format was, so I made sure it looked exactly like the example (minus the prompts, of course), but that added a lot of extra characters. Ideone link

share|improve this answer

PHP - 224

Well, I gave it a try.

$n=explode(",",$argv[1]);$d=($e=$n[2])==W?0:($e==N?1:($e==E?2:3));for(;$i<strlen($n[3]);)if(($o=$n[3][$i++])==M)$n[$d%2]+=$d>1?-1:1;else$d=$o==R?($d+1)%4:($d==0?3:$d-1);echo"{$n[0]},{$n[1]},".($d==1?N:($d==2?E:($d==3?S:W)));

Input in STDIN, e.g.:

$ php mars_rover.php 1,2,N,MMMRRRRRMM
-1,5,E
$ php mars_rover.php 1,2,N,MMMMRLMRLMMRMRMLMRMRMMRM
1,8,N
$ php mars_rover.php 3,-2,W,MMMMLM
7,-3,S
share|improve this answer

Python3 (288)

Implementation using heavy use of ternary ifs.

m=['N','E','S','W']
cords=[int(n) for n in input().split()] + [input()] #Convert first inputs to integers and retrieve third
for n in input(): #Get instructions
    if n=='M':
        i=[1,0][cords[2] in m[1:3]] #See if vertical or horizontal
        j=[-1,1][cords[2] in m[0:2]] #See if negative or positive
        cords[i]+=j
    else:
        i=[-1,1][n=='R'] #Translate turn to numerals
        cords[2]=m[m.index(cords[2])+i] #Change direction relative to current orientation
print(cords)

Omitting the obvious input grumbles, giving the direction strings intrinsic values may have benefited the script size. However, the approach here is perfectly functional (so I believe)

share|improve this answer
    
Welcome to PPCG. This is code-golf, so the shortest answer wins. You can start by making your variable names one char long. –  DigitalTrauma Jun 19 at 20:48

Python 3 (143)

I=input
a,b,D=I().split(',')
w='ENWS'
d=w.find(D)
x=int(a)+int(b)*1j
for c in I():x+=(c=='M')*1j**d;d+='ML'.find(c)
print(x.real,x.imag,w[d%4])

http://ideone.com/wYvt7J

We use Python's built-in complex number type to store the pair of coordinates. The direction is computed by taking the imaginary unit 1j to the power of d, which stores the direction mod 4. Rotating is done by incrementing or decrementing d. The expression 'ML'.find(c) gives the amount we want to change d: 1 for L, 0 for M, and -1 (the default for not found) for R.

Python doesn't have a short way to convert a complex number to a tuple, so we have to make costly calls to .real and .imag.

share|improve this answer

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.