20
\$\begingroup\$

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.

\$\endgroup\$
5
  • 8
    \$\begingroup\$ Bonus points for doing it in Logo? ;) \$\endgroup\$ Commented May 3, 2011 at 21:31
  • \$\begingroup\$ @Peter The output format is strict... But we will see whether people like the picture :D \$\endgroup\$ Commented May 3, 2011 at 21:38
  • 1
    \$\begingroup\$ The first example output should be -3.000, 2.000. \$\endgroup\$
    – Lowjacker
    Commented May 3, 2011 at 21:59
  • \$\begingroup\$ 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. \$\endgroup\$ Commented May 3, 2011 at 22:16
  • \$\begingroup\$ @Lowjacker Yes, thanks. Actually, the input was wrong. \$\endgroup\$ Commented May 4, 2011 at 11:32

14 Answers 14

8
\$\begingroup\$

Ruby 1.9, 175 171 162 153 130 120 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
\$\endgroup\$
1
  • \$\begingroup\$ ?i.to_c can be shortened to 1.i for -4 bytes. \$\endgroup\$
    – MegaTom
    Commented Jun 9, 2019 at 2:37
5
\$\begingroup\$

Python 2, 158 154 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!

\$\endgroup\$
8
  • \$\begingroup\$ You actually have 157 chars, not 158. \$\endgroup\$
    – Lowjacker
    Commented May 3, 2011 at 23:24
  • \$\begingroup\$ I guess I don't need to, but I usually count the trailing newline. \$\endgroup\$ Commented May 4, 2011 at 3:16
  • \$\begingroup\$ [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] \$\endgroup\$ Commented May 4, 2011 at 12:19
  • 1
    \$\begingroup\$ @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. \$\endgroup\$ Commented May 4, 2011 at 15:29
  • 1
    \$\begingroup\$ int class has both imag and real attrs... \$\endgroup\$
    – JBernardo
    Commented Jul 5, 2011 at 22:08
4
\$\begingroup\$

Haskell (291)

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(/=',')
\$\endgroup\$
1
  • \$\begingroup\$ 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. \$\endgroup\$
    – FUZxxl
    Commented May 6, 2011 at 13:58
4
\$\begingroup\$

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 :)

\$\endgroup\$
4
\$\begingroup\$

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

JavaScript, 179 164 170 168 158 156 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
        })
alert(X.toFixed(3)+', '+Y.toFixed(3))
  • 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))

\$\endgroup\$
2
  • 1
    \$\begingroup\$ 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. \$\endgroup\$
    – DocMax
    Commented Jun 14, 2011 at 6:45
  • \$\begingroup\$ Thanks for the regex bit. As for the accuracy issue, I used SQRT2 instead and switched the multiplication to division. \$\endgroup\$
    – Casey Chu
    Commented Jun 14, 2011 at 10:22
2
\$\begingroup\$

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

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

\$\endgroup\$
2
\$\begingroup\$

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.

\$\endgroup\$
2
\$\begingroup\$

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!

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

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

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!

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

J, 93 bytes

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

Try it online!

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

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!

\$\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.