17
\$\begingroup\$

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 .

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

22 Answers 22

7
\$\begingroup\$

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.

\$\endgroup\$
5
  • \$\begingroup\$ waiting to see it golf further :) \$\endgroup\$
    – Amit Joki
    Commented Jun 19, 2014 at 17:07
  • \$\begingroup\$ You can replace x,y,i=eval"[#{gets}]" with eval"x,y,i="+gets to save some chars. \$\endgroup\$
    – afuous
    Commented Jun 19, 2014 at 17:11
  • \$\begingroup\$ @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? \$\endgroup\$
    – Ventero
    Commented Jun 19, 2014 at 17:14
  • 1
    \$\begingroup\$ @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. \$\endgroup\$
    – afuous
    Commented Jun 19, 2014 at 17:19
  • \$\begingroup\$ @voidpigeon Ah, you're right, that actually allows a slightly different optimization: x,y,i=eval"*a="+gets. Thanks! \$\endgroup\$
    – Ventero
    Commented Jun 19, 2014 at 17:21
5
\$\begingroup\$

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
\$\endgroup\$
3
  • \$\begingroup\$ you can do this?! [a,b,c] = x.split(...) \$\endgroup\$
    – edc65
    Commented Jun 19, 2014 at 17:10
  • 1
    \$\begingroup\$ @edc65 Yup! Destructuring Assignment \$\endgroup\$
    – nderscore
    Commented Jun 19, 2014 at 17:17
  • \$\begingroup\$ Have a look at my C answer. maybe the g array is not needed \$\endgroup\$
    – edc65
    Commented Jun 20, 2014 at 5:37
3
\$\begingroup\$

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.

\$\endgroup\$
3
\$\begingroup\$

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" ]
\$\endgroup\$
1
  • \$\begingroup\$ Nice, this looks a lot like my solution. \$\endgroup\$
    – nderscore
    Commented Jun 19, 2014 at 16:39
3
\$\begingroup\$

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 
*/
\$\endgroup\$
2
\$\begingroup\$

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.
\$\endgroup\$
2
  • \$\begingroup\$ Why 23, and what is c%(2*(1-(d&2))) \$\endgroup\$
    – user21677
    Commented Jun 20, 2014 at 16:17
  • \$\begingroup\$ @tolos: Added some explanation. Also shortened by 2 characters :) \$\endgroup\$
    – nneonneo
    Commented Jun 20, 2014 at 16:46
2
\$\begingroup\$

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
\$\endgroup\$
0
2
\$\begingroup\$

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=
\$\endgroup\$
1
  • \$\begingroup\$ 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) \$\endgroup\$
    – masterX244
    Commented Jun 22, 2014 at 9:01
1
\$\begingroup\$

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());
\$\endgroup\$
1
  • 5
    \$\begingroup\$ I can see unnecessarily long variables names ;). Also, in code golf nobody cares about proper variable scoping, so drop those var s. \$\endgroup\$ Commented Jun 19, 2014 at 15:41
1
\$\begingroup\$

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)
\$\endgroup\$
1
\$\begingroup\$

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!

\$\endgroup\$
1
\$\begingroup\$

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;
}
\$\endgroup\$
1
\$\begingroup\$

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

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
$
\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
\$\begingroup\$

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.

\$\endgroup\$
1
  • \$\begingroup\$ Nice! I like this a lot. \$\endgroup\$ Commented Jun 20, 2014 at 3:13
0
\$\begingroup\$

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
\$\endgroup\$
2
  • 1
    \$\begingroup\$ 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. \$\endgroup\$
    – Joey
    Commented Jun 20, 2014 at 12:55
  • \$\begingroup\$ @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 \$\endgroup\$
    – user16402
    Commented Jun 20, 2014 at 14:26
0
\$\begingroup\$

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

\$\endgroup\$
0
\$\begingroup\$

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
\$\endgroup\$
0
\$\begingroup\$

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)

\$\endgroup\$
1
  • \$\begingroup\$ Welcome to PPCG. This is code-golf, so the shortest answer wins. You can start by making your variable names one char long. \$\endgroup\$ Commented Jun 19, 2014 at 20:48
0
\$\begingroup\$

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.

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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