Let's move the Mars rover!

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 .

• Are there limits to the coordinates? – Teun Pronk Jun 19 '14 at 14:32
• 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 '14 at 14:33
• @KyleKanos I saw people using it, so just used. Rephrased it ;) – Amit Joki Jun 19 '14 at 14:35
• You know, if you're experiencing negative feedback on your challenges, try running them through the sandbox first. – Martin Ender Jun 19 '14 at 14:49
• @Geobits thanks. Stated explicitly. – Amit Joki Jun 19 '14 at 15:09

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. • waiting to see it golf further :) – Amit Joki Jun 19 '14 at 17:07 • You can replace x,y,i=eval"[#{gets}]" with eval"x,y,i="+gets to save some chars. – afuous Jun 19 '14 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 '14 at 17:14 • @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. – afuous Jun 19 '14 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 '14 at 17:21 Javascript (ES6) 145141 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 • you can do this?! [a,b,c] = x.split(...) – edc65 Jun 19 '14 at 17:10 • @edc65 Yup! Destructuring Assignment – nderscore Jun 19 '14 at 17:17 • Have a look at my C answer. maybe the g array is not needed – edc65 Jun 20 '14 at 5:37 Java - 327 class R{public static void main(String[]a){char c,e=a.charAt(0),z[]={78,69,83,87};Integer x=Integer.valueOf(a),y=x.valueOf(a),d=e<70?1:e==83?2:e>86?3:0,i=0;for(;i<a.length();d=c>81?(d+1)%4:c<77?(d+3)%4:d){c=a.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.charAt(0),z[]={78,69,83,87}; Integer x=Integer.valueOf(a),y=x.valueOf(a),d=e<70?1:e==83?2:e>86?3:0,i=0; for(;i<a.length();d=c>81?(d+1)%4:c<77?(d+3)%4:d){ c=a.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. 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" ] • Nice, this looks a lot like my solution. – nderscore Jun 19 '14 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;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; 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 */ C, 148 150151 p,x;main(){char c,d,l,*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,"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. • Why 23, and what is c%(2*(1-(d&2))) – user21677 Jun 20 '14 at 16:17 • @tolos: Added some explanation. Also shortened by 2 characters :) – nneonneo Jun 20 '14 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: 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 • @isaacg Thanks - nice golfing! – Digital Trauma Jun 20 '14 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= • 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 '14 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);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); 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. • may be ideone and the option is Pascal? – Amit Joki Jun 19 '14 at 15:15 • "When I started it was not code-golf yet." Is that your excuse for coding in Delphi? ;) – Martin Ender Jun 19 '14 at 15:16 • What's up with the spaces around =? Why are they needed? Also, the variable names seem way too long to me – John Dvorak Jun 19 '14 at 17:20 • @m.buettner ssshh, dont spill the beans :P – Teun Pronk Jun 20 '14 at 6:45 • @JanDvorak Like I said, it wasn't tagged as code-golf – Teun Pronk Jun 20 '14 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;y=+q;e=+d.indexOf(q);}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()); • I can see unnecessarily long variables names ;). Also, in code golf nobody cares about proper variable scoping, so drop those var s. – Martin Ender Jun 19 '14 at 15:41 Python (263) input = raw_input("Initial: ") input2 = raw_input("Command: ") position = [int(input), int(input), input] 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 += move[position] position += move[position] else: position = bearings[(bearings.index(position) + 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),int(i),i] 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+=m[p] p+=m[p] p = b[(b.index(p)+m[c])%4] print ','.join(str(s) for s in p) 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' printx+','+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' printx+','+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! 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;
}

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')
• Hah hah! Great to see Haskell so far behind the pack, for a change :D – GreenAsJade Jun 20 '14 at 10:41
• f=many digit MUCH LOL - SUCH WOW – tomsmeding Jun 22 '14 at 6:31
• Splitting the input and using read multiple times took more characters to do than using parsec... – gxtaillon Jun 22 '14 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=$[(dtr LR -+<<<$s1+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$

PowerShell, 170167 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.

Python, 135 137138

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,v,'SWNE'[d&3])

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

Try it in ideone.

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'
printx+','+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.

• Nice! I like this a lot. – undergroundmonorail Jun 20 '14 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

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} in N) z=$[z+1];;S) z=$[z-1];;W) z=$[z-1];;E) z=$[z+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} in N) z=$[z+1];;S) z=$[z-1];;W) z=$[z-1];;E) z=$[z+1];;esac&&o=P${z[@]}|y \  ,`
} #end loop
p $o #print output • 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 '14 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 – user16402 Jun 20 '14 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

PHP - 224

Well, I gave it a try.

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

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 in m[1:3]] #See if vertical or horizontal
j=[-1,1][cords in m[0:2]] #See if negative or positive
cords[i]+=j
else:
i=[-1,1][n=='R'] #Translate turn to numerals
cords=m[m.index(cords)+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)

• Welcome to PPCG. This is code-golf, so the shortest answer wins. You can start by making your variable names one char long. – Digital Trauma Jun 19 '14 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.