# Pirate Treasure

Finding a treasure hidden by pirates is really easy. Everything you need for this is a map. It is widely known that pirates draw maps by hand and describe the algorithm to find a place in the following way: "Stand near a lone palm tree, do 30 steps towards the forest, 15 towards the lake, ..."

A journey through such route is usually a great opportunity to see the scenery... However, nowadays nobody has time for that. That's why treasure seekers have asked you to write a program that would determine the exact location of a treasure using a given map.

# Input

The input consists of multiple instructions <Direction> <Distance>, separated with commas (that are followed by one whitespace each).

Direction is one of the following:
N - North, S - South, E - East, W - West,
NE - Northeast, NW - Northwest, SE - Southeast, SW - Southwest.

Distance is an integer (1 to 1000).

# Output

The result is the coordinates where you end up after finishing the instructions, with three decimal places, separated with a comma and a whitespace. Start location has zero coordinates (0, 0).

The first coordinate is X (East means coordinates larger than zero, West means less than zero).
The second coordinate is Y (North means more than zero, South means less than zero).

# Examples

1. N 3, E 1, N 1, E 3, S 2, W 1

3.000, 2.000

2. NW 10

-7.071, 7.071

3. NE 42, NW 42, SE 42, SW 42

0.000, 0.000

Source (in Ukrainian). Input format is different there.

• Bonus points for doing it in Logo? ;) Commented May 3, 2011 at 21:31
• @Peter The output format is strict... But we will see whether people like the picture :D Commented May 3, 2011 at 21:38
• The first example output should be -3.000, 2.000. Commented May 3, 2011 at 21:59
• with UCB Logo the output format can be obtained as (print (word (form xcor 4 3) ",) (form ycor 4 3)). But I'm not sure how easy parsing the input would be. Commented May 3, 2011 at 22:16
• @Lowjacker Yes, thanks. Actually, the input was wrong. Commented May 4, 2011 at 11:32

## Ruby 1.9, 175171162153130120 117

l=0
gets.scan(/(\w+) (\d+)/){|d,n|l+=n.to_i*?i.to_c**%w[E NE N NW W SW S SE].index(d).quo(2)}
puts'%.3f, %.3f'%l.rect

• ?i.to_c can be shortened to 1.i for -4 bytes. Commented Jun 9, 2019 at 2:37

# Python 2, 158154 150 chars

p=0j
for s in raw_input().split(','):c,d=s.split();v=sum(dict(N=1j,E=1,S=-1j,W=-1)[x]for x in c);p+=v*int(d)/abs(v)
print'%.3f, %.3f'%(p.real,p.imag)


Attempt This Online!

• You actually have 157 chars, not 158. Commented May 3, 2011 at 23:24
• I guess I don't need to, but I usually count the trailing newline. Commented May 4, 2011 at 3:16
• [157] Line 1: D=dict(N=1j,E=1,S=-1j,W=-1) [153] Line 2: is j really needed? [152] Lines 3-4: If you switch to Python 3, raw_inputinput, and even though you have to use parentheses after print, you save 2 characters [150] Commented May 4, 2011 at 12:19
• @BlaXpirit: Thanks for the dict optimization. The j is needed in line 2 in case all the directions are E and W. The resulting p needs to be complex for .real and .imag to work. Commented May 4, 2011 at 15:29
• int class has both imag and real attrs... Commented Jul 5, 2011 at 22:08

import Text.Printf
d=sqrt(0.5)
f"N"n(x,y)=(x,y+n)
f"S"n(x,y)=(x,y-n)
f"E"n(x,y)=(x+n,y)
f"W"n(x,y)=(x-n,y)
f[a,b]n(x,y)=(s,t)where(s,_)=f[b](d*n)(x,y);(_,t)=f[a](d*n)(x,y)
p[]=(0,0)
p(a:b:c)=f a(read b::Float)$p c s(a,b)=printf"%.3f, %.3f"a b main=getLine>>=putStrLn.s.p.words.filter(/=',')  • How about changing the defintion of f to use pattern guards? They have the nice property to not require a line break and should be more breve in this case. Also, use interact. Commented May 6, 2011 at 13:58 ## C99 (319 chars) #define B ;break; #include<math.h> #include<stdio.h> float x,y,w,z,j;int main(void){int k;char c[3];while(scanf("%s%d,",c,&k)==2){j=k;w=1;switch(c[1]){case'E':w=3;default:w-=2;j=sqrt(k*k/2)B case 0:w=z=0;}switch(*c){case'N':z=1 B case'S':z=-1 B case'E':w=1 B default:w=-1;}x+=w*j;y+=z*j;}printf("%5.3f, %5.3f\n",x,y);}  input in stdin, test run at ideone :) # Haskell, 199 characters import Text.Printf import Complex i=0:+(1::Float) e 'S'= -i e d=i^mod(fromEnum d-1)4 g p(d:s:t)=g(p+(signum.sum.map e)d*(fst(reads s!!0):+0))t g(x:+y)[]=printf"%.3f, %.3f"x y main=interact$g 0.words


## JavaScript, 179164170168158156 153 chars

prompt(X=Y=0).replace(/(N|S)?(.)? (\d+)/g,
function(m,y,x,n){
n/=x&&y?Math.SQRT2:1
Y+=y?y<'S'?n:-n:0
X+=x?x<'W'?n:-n:0
})

• 170: fixed accuracy issue
• 168: replaced (E|W) in regex with (.)
• 158: replaced repetitive logic in function with variable d
• 156: reused n instead of a new variable d
• 153: Personally, I think this edit makes it ten times uglier, but it's three characters shorter. It's based on the non-standard behavior that you can call RegExp objects as functions: /./g('string') is the same as /./g.exec('string'):

for(p=prompt(X=Y=0),R=/(N|S)?(.)? (\d+)/g;[,y,x,n]=R(p)||0;X+=x?x<'W'?n:-n:0)n/=x&&y?Math.SQRT2:1,Y+=y?y<'S'?n:-n:0;alert(X.toFixed(3)+', '+Y.toFixed(3))

• Unfortunately, q=.707 fails the "NW 10" input due to rounding errors; I think you need "q=Math.SQRT1_2" which adds 8 chars. On the other hand, you can replace "(E|W)?" with "(.)?" since you have already established north/south/neither and the input is well-formed, saving 2 chars. Commented Jun 14, 2011 at 6:45
• Thanks for the regex bit. As for the accuracy issue, I used SQRT2 instead and switched the multiplication to division. Commented Jun 14, 2011 at 10:22

Scala (367, 332)

var (x,y,s)=(.0,.0,.7071);args.mkString(" ").split(",").foreach{m=>val a=m.trim.split(" ");var (n,u,v)=(a(1).toInt,.0,.0);a(0) match{case "N"=>v=1;case "S"=>v= -1;case "E"=>u=1;case "W"=>u= -1;case "NW"=>{u= -s;v=s};case "NE"=>{u=s;v=s};case "SW"=>{u= -s;v= -s};case "SE"=>{u=s;v= -s}};x += n*u;y += n*v};printf("%1.3f %1.3f\n",x,y)


## Java (459) (445) (402) (382) (363) (352)

import java.util.*;class
M{public
static void main(String[]a){double
x=0,y=0;Scanner
s=new
Scanner(System.in);s.useDelimiter("\\W+");while(s.hasNext()){String
d=s.next();double
z=Math.sqrt(d.length());int
w=s.nextInt();y+=(d.contains("N")?w:d.contains("S")?-w:0)/z;x+=(d.contains("E")?w:d.contains("W")?-w:0)/z;}System.out.format("%1.3f %1.3f",x,y);}}


stdin input

## PowerShell, 178

$input-split','|%{,@{N=0,1 NE=($s=.707106781186548),$s E=1,0 SE=$s,-$s S=0,-1 SW=-$s,-$s W=-1,0 NW=-$s,$s}[($a=-split$_)[0]]*$a[1]}|%{$x+=$_[0]
$y+=$_[1]}
'{0:N3}, {1:N3}'-f$x,$y


This can probably lose up to 10 characters by reducing the accuracy of √2/2.

# C (gcc), 155 152 bytes

-3 bytes thanks to ceilingcat

float x,y,l;D;main(d){for(;scanf("%s%f,",&d,&l)>0;y+=d^78?d^83?0:-l:l)D=d,l/=D>99?D/=256,d&=255,sqrt(2):1,x+=D^87?D^69?0:l:-l;printf("%.3f, %.3f",x,y);}


Try it online!

## Groovy (215)

x=0.0;y=0.0;args.join(' ').split(', ').each{d=it.split(' ');c=d[0]==~/../?Math.sqrt(2):1;s=d[1] as int;a=['N':1,'S':-1,'E':1,'W':-1];m=d[0]=~/N|S/;y+=m?a[m[0]]*(s/c):0;m=d[0]=~/E|W/;x+=m?s/c*a[m[0]]:0};print "$x,$y"


reads input as program arguments. Example:

groovy golf.groovy NW 10, SW 10, W 10


# Perl 5-n, 122 bytes

s,(N|S)?(E|W)? (\d+),$d=$3/($1&$2?2**.5:1);$x+=$2&&$d*(-1)**($2gt F);$y+=$1&&$d*(-1)**($1gt O),ge;printf"%.3f, %.3f",$x,$y


Try it online!

# J, 93 bytes

[:0j3&":@+.@(1#.".@>@{:*(0j1^2%~i.8){~<;._1@' E NE N NW W SW S SE'i.{.)@|:[:(<;._1);._1', ',]


Try it online!

# R, 165 bytes

\(s,L=c(N=1i,S=-1i,E=1,W=-1))sprintf("%.3f, %.3f",Re(b<-sum(mapply(\(x,y)(m=sum(L[el(strsplit(x,""))]))*y/abs(m),(a=read.table(te=gsub(",","
",s)))$V1,a$V2))),Im(b))


Attempt This Online!

This solution is based on the complex plane: N-S is the imaginary axis, E-W – the real one. In my first solution I have used an inner join to match the cardinal directions with the values but then I saw this answer in Python (https://codegolf.stackexchange.com/a/2446/101276) and ended up by borrowing the idea to make a named vector so that subsetting it with a letter will give the value behind that geographic direction:

> L
N     S     E     W
0+1i  0-1i  1+0i -1+0i


It seems that at the end I have got a translation of that already mentioned post, so please consider upvoting it.

In both cases I was using read.table to simultaneously convert a string into a character and a numeric column.

Below is my original golf:

# R, 181 bytes

\(s,r=read.table)sprintf("%.3f, %.3f",Re((x=sum(with(merge(r(te=gsub(",","
",s)),r(te="E 1
W -1
N 1i
S -1i
NE 1+1i
NW -1+1i
SE 1-1i
SW -1-1i"),by=1),(V2.x*V2.y)/abs(V2.y))))),Im(x))


Attempt This Online!