# Traveling on a flat Earth

Coordinates in the flat-Earth world consist of latitude (x) and longitude (y), which are integers in the range 0...9999. Much like Gaussian integers, but they are always written using this notation:

411S 370E


That is, with S or N appended to the latitude, and E or W appended to the longitude, with space(s) between the two components.

# Goal

Write a program (not a function) that reads two coordinates, separated by whitespace, and outputs their sum. The first coordinate is a starting point, the second one is a displacement, and the output is the resulting position.

# Input/Output

Since this challenge is partially about formatting, I'll try to define the input and output formats unambiguously.

The preferred input format has 1 space between the coordinate components, no leading zeros, and a newline character between the two coordinates. The program must be able to read the preferred format.

The output can contain any amount of whitespace and leading zeros. If it's different from the preferred input format, the program must be able to read this format too.

Just to make it clear, the input cannot (will not) contain any additional formatting characters. Just spaces and newlines where needed.

# Scoring

This is an experiment on a new winning condition. I'll choose the winner by accepting an answer in a few weeks. If a better answer appears afterwards, I'll change the accepted answer.

The score for the program is its byte count. The winning program is one that is shorter than 400 bytes, has the fewest byte count, but is written in the most verbose programming language. To determine the winner:

• Remove programs with byte count 400 or more (they can participate but cannot win)
• Consider only the shortest program for each programming language
• The longest program wins

Polyglots compete against programs in all languages in which they are valid (e.g. if a program is valid in both bash and sh, it competes against programs in both languages).

# Test cases

In the test cases, the first two lines are the input, and the third line is the output.

0S 0E
0S 0W
0N 0E


(the direction of zero doesn't matter, both in input and output)

0S 9999E
9999N 9999W
9999N 0E


(maximal values)

42S 314W
42N 2718W
0N 3032W


(the direction of zero doesn't matter in the output)

5555N 8888W
7777S 0E
2222S 8888W


(no negative values; change the direction if you need to change the sign)

0001N        4545W
0999N        5454W
1000N        9999W


(if the program outputs leading zeros and several spaces, it must be able to read them; it must also be able to read input that doesn't contain them)

8888N 8888W
9999N 9999W


(invalid input - any behavior is acceptable, including crash and infinite loop)

• I'm genuinely curious if this scoring mechanism will work out, but I feel like it's game-able. In particular, I could write a (suboptimal) solution at exactly 399 bytes in some crazy hard esolang (or one of my own) and even though it might be easily golfable, it would be somewhat unlikely that anyone else would be willing to learn the language just to beat my score in this challenge. – Martin Ender May 4 '16 at 7:34
• I hope it's clear now. Please look for "preferred input format" in the text and ask for further clarification if it's still ambiguous. – anatolyg May 4 '16 at 8:54
• @anatolyg I find that paragraph very misleading. You talk about "flexibility" and a preferred input format, but then require all solutions to use exactly that format. Where is the flexibility and what is "preferred" about this format? I think for this challenge it's fine to require one very specific format, but then the specification should unambiguously say so. – Martin Ender May 4 '16 at 9:13
• No unary input for me? – Leaky Nun May 4 '16 at 9:25
• @MartinBüttner The flexibility is in the output. Not much though. – anatolyg May 4 '16 at 10:01

# ABAP, 377 365 bytes

REPORT r.PARAMETERS: x TYPE string,y TYPE string.DEFINE m.SHIFT &1 RIGHT CIRCULAR.TRANSLATE &1 USING 'W-E+S-N+'. END-OF-DEFINITION. DEFINE o.&1 = |{ &1 * 1 SIGN = RIGHTPLUS DECIMALS = 0 }|.TRANSLATE &1 using &2. END-OF-DEFINITION.
SPLIT: x AT space INTO DATA(a) DATA(b),y AT ' ' INTO DATA(c) DATA(d). m: a,b,c,d.a = a + c.b = b + d.o: a '-S+N',b '-W+E'.WRITE: a, b.


Ungolfed:

REPORT r.
PARAMETERS: x TYPE string,
y TYPE string.
DEFINE m.
SHIFT &1 RIGHT CIRCULAR.
TRANSLATE &1 USING 'W-E+S-N+'.
END-OF-DEFINITION.

DEFINE o.
&1 = |{ &1 * 1 SIGN = RIGHTPLUS DECIMALS = 0 }|.
TRANSLATE &1 using &2.
END-OF-DEFINITION.

SPLIT: x AT space INTO DATA(a) DATA(b),y AT ' ' INTO DATA(c) DATA(d).
m: a,b,c,d.
a = a + c.
b = b + d.
o: a '-S+N',b '-W+E'.
WRITE: a, b.


It was actually challenging to be within 400 characters.

Some notes:

• Original version had ADD c TO a. which is one of my favourite verbose statements.
• The built-in editor would not accept this as a 1 liner
• Using subroutines with FORM and PERFORM exploded the char count, so I kept to macros
• Chaining statements with colons is discouraged outside of data declarations, but was needed for saving bytes
• + without a preceding space is an offset operator, requiring many spaces in the code
• ABAP writes a space after numbers, hence the trick to just replace the sign
• In order to use RIGHTPLUS the expression needed to be a number, so the need to mulitply with 1, but then the format has decimals.. so hence DECIMALS
• Great! A modern language I have never heard of! – anatolyg Sep 7 '16 at 12:22

## JavaScript (ES6), 118 bytes

s=>(g=([i,j,k,l,m,n],[o,p])=>(i=(j>p?-i:+i)+(n>p?-j:+j))<0?-i+o:i+p)(a=s.match(/\d+|\w/g),"SN")+' '+g(a.slice(2),"WE")


# MATLAB, 327304296290282276267259 255 253 bytes

I think I'm closing in on a limit now. I've managed to remove 51, 60 68 72 74 bytes from an answer I thought was well golfed. =)

Removed 8 bytes by taking the input inside the strsplit, thanks to Luis Mendo. Removed another 6 bytes by taking all the input into one cell array instead of two. Removed another 8 bytes by taking both last statements inside disp(). Removed 6 bytes by removing char and some brackets. This wasn't possible in a previous revision of the answer. Splitting the cell elements into four variables costed 15 bytes, but saved 24, thus 9 bytes saved! 8 additional bytes due to improved disp scheme. 5*~~s saves two bytes compared to (s>0)*5. Thus 4 new bytes saved (for s and t). Taking the opposite of this last expression saves yet another 2 bytes, 83-5*~s is shorter than 78+5*~~s

Golfed code:

x=strsplit([input('','s'),' ',input('','s')]);[a,b,c,d]=x{:};f=@str2num;n=@num2str;i=@sign;s=f(a(1:end-1))*i(a(end)-79)+f(c(1:end-1))*i(c(end)-79);t=f(b(1:end-1))*i(b(end)-79)+f(d(1:end-1))*i(d(end)-79);disp([n(abs(s)),83-5*~s,32,n(abs(t)),87-18*~t,''])


Same code, but with line breaks:

x=strsplit([input('','s'),' ',input('','s')]);
[a,b,c,d]=x{:};
f=@str2num;
n=@num2str;
i=@sign;
s=f(a(1:end-1))*i(a(end)-79)+f(c(1:end-1))*i(c(end)-79);
t=f(b(1:end-1))*i(b(end)-79)+f(d(1:end-1))*i(d(end)-79);
disp([n(abs(s)),78+5*~~s,32,n(abs(t)),69+18*~~t,''])


Test cases:

Save the above as flat_earth.m

flat_earth
0S 0E
0S 0W
0N 0E

flat_earth
0S 9999E
9999N 9999W
9999N 0E

flat_earth
42S 314W
42N 2718W
0N 3032W

flat_earth
5555N 8888W
7777S 0E
2222S 8888W

flat_earth
0001N        4545W
0999N        5454W
1000N 9999W


# R, 196 bytes

R is pretty verbose, by golfing standards. Let's see...

i=scan(,'');l=nchar(i);S=W=-;N=E=c;n=as.double(substr(i,1,l-1));d=substr(i,l,l);for(j in 1:4)n[j]=get(d[j])(n[j]);o=c(n[1]+n[3],n[2]+n[4]);cat(paste0(abs(o), ifelse(o<0,c("S", "W"),c("N","E"))))


Ungolfed:

input = scan(,'')       # Take input from stdin, separating at newlines and spaces
length = nchar(input)   # Get the number of characters in each input
S=W=-                 # These two lines create aliases of - (the minus function)
N=E=c                   # and c (the concatenate function).
# We will later treat the NSEW part of the coordinate
# as a call to a function, to ensure that the numbers
# are treated with the correct polarity.
numbers = as.double(substr(input, 1, length-1))
# Strip the last character off of every coordinate, convert
# to integer
directions = substr(input, length, length)
# Strip off the numbers and grab the cardinal directions
for(j in 1:4)
numbers[j] = get(directions[j])(numbers[j])
# For our four numbers, treat the cardinal direction as
# a function, which is mapped to - for south and west, and
# c for north and east (which is essentially identity)
output = c(numbers[1]+numbers[3], numbers[2]+numbers[4])
# Add together the numbers
cat(paste0(abs(output), ifelse(output<0, c("S", "W"), c("N","E"))))
# Output the absolute values of the new coordinates, followed
# by "S" or "W" if the number is negative and "N" or "E" if
# the number is positive


Edit to add: I just looked at the other answers, and I'm surprised that my entry is one of the shortest! Perhaps R isn't as verbose as I thought...

# Java, 372 bytes

import static java.lang.System.*;class A{public static void main(String[]v){String l=" ",s=console().readLine()+l+console().readLine();Integer i=0,n[]=new Integer[4],y;for(;i<4;i++)n[i]=i.parseInt(s.replaceAll("[A-Z] *",l).split(l)[i])*(s.replaceAll("\\d| ","").charAt(i)==(i%2<1?83:87)?1:-1);i=n[0]+n[2];y=n[1]+n[3];out.println((i<0?-i+"N":i+"S")+l+(y<0?-y+"E":y+"W"));}}


### Ungolfed

import static java.lang.System.console;
import static java.lang.System.out;

class A {
public static void main(String[] v) {
String l = " ", s = console().readLine() + l + console().readLine();
Integer i = 0, n[] = new Integer[4], y;
for (; i < 4; i++)
n[i] = i.parseInt(s.replaceAll("[A-Z] *", l).split(l)[i]) * (s.replaceAll("\\d| ", "").charAt(i) == (i % 2 < 1 ? 83 : 87) ? 1 : -1);
i = n[0] + n[2];
y = n[1] + n[3];
out.println((i < 0 ? -i + "N" : i + "S") + l + (y < 0 ? -y + "E" : y + "W"));
}
}


### Notes

• Save as A.java, compile with javac A.java, run with java A. Then enter the inputs line separated or as two separate inputs on stdin.

### Outputs:

0S 0E
0S 0W
0S 0W

0S 9999E
9999N 9999W
9999N 0W

42S 314W
42N 2718W
0S 3032W

5555N 8888W
7777S 0E
2222S 8888W

0001N        4545W
0999N        5454W
1000N 9999W

8888N 8888W
9999N 9999W
18887N 18887W


# SQL (PostGreSQL 9.4), 305 bytes

PREPARE p(char,char)AS
SELECT string_agg(abs(n)||substr('SNNEEW',i+sign(n)::int,1),' ')FROM(SELECT i,sum(to_number(v,'9999')*CASE right(v,1)WHEN'N'THEN 1 WHEN'E'THEN 1 ELSE -1 END)n
FROM(SELECT CASE WHEN v~'[NS]' THEN 2 ELSE 5 END i,v
FROM regexp_split_to_table($1||' '||$2,' ')v)i
GROUP BY i ORDER BY i)g


Implemented as a prepared statement that takes 2 character parameters. One parameter for each input line.

It is called as follows

execute p('0S 9999E','9999N 9999W');


and outputs a row containing a single character column for the result. 9999N 0E

# Java, 308 bytes

import java.util.*;class x{public static void main(String[]a){Scanner r=new Scanner(System.in);int[]v=new int[2];int l,x,g,i;for(i=5;i-->1;System.out.println(i<3?""+x*g+"ENWS".charAt(i-g):"")){String s=r.next();x=Integer.parseInt(s.substring(0,l=s.length()-1));x=v[i%2]+=x*=s.charAt(l)>80?-1:1;g=x<0?-1:1;}}}


A more readable version:

import java.util.*;
class x
{
public static void main(String[]args)
{
Scanner r = new Scanner(System.in);
int[] v = new int[2];
for (int i = 5; i-->1; )
{
String s = r.next();
int l = s.length() - 1;
int x = Integer.parseInt(s.substring(0, l));
x = v[i%2] += x *= s.charAt(l) > 'N' ? -1 : 1;
int g = x < 0 ? -1 : 1;
System.out.println(i < 3?"" + x * g + "ENWS".charAt(i-g):"");
}
}
}


Golfing in Java is a special kind of fun. The following two lines of code do the same, but the first one is shorter:

(x<0?-x:x)
Math.abs(x)


The code reads 4 tokens from standard input. For each token, the part up to the last character is converted to int, and the last character optionally flips its sign.

Then it adds the value that was read 2 iterations ago. Java initializes arrays to 0, so at the first two iterations this will do the right thing.

Then it will format the values and print them. However, in the first two iterations, it prints the empty string instead (so two extra linebreaks appear in the output).

It uses some funky arithmetic so the iteration variable (4,3,2 or 1) and the sign (-1 or 1) can be combined to a zero-based index into the string "ENWS".

# Perl 6, 130 bytes

my (\h,\v)=[Z+] lines».split(' ')».map: {m/(.*)(.)/;$1 eq'S'|'W'??-$0!!$0} say "{abs h}{h <0??'S'!!'N'} {abs v}{v <0??'W'!!'E'}"  # Ruby, 186 bytes It's too short, sorry. I did my best. x=-1 puts gets.scan(/\d+\D/).map{|i|i.to_i*(i[-1]=~/[WS]/?-1:1)}.zip(gets.scan(/\d+\D/).map{|i|i.to_i*(i[-1]=~/[WS]/?-1:1)}).map{|a,b|a+b}.map{|s|s.abs.to_s+%w"NNS EEW"[x+=1][s<=>0]}*' '  # C - 267 bytes I though C would be long... might as well just put it up. ;_; #include <stdio.h> #include <stdlib.h> int main(){int x,y,z,w;char m,n,o,p;scanf("%d%c %d%c",&x,&m,&y,&n);scanf("%d%c %d%c",&z,&o,&w,&p);int a=x*(m<'O'?1:-1)+z*(o<'O'?1:-1),b=y*(n<'F'?1:-1)+w*(p<'F'?1:-1);printf("%d%c %d%c\n",abs(a),a<0?'S':'N',abs(b),b<0?'W':'E');}  ## Befunge-93, 240 bytes v v$      <
>&>~:" "-!|
vp01p02   <
v$< >&>~:" "-!| vp03p04 < v$      <
>&>~:" "-!|
vp05p06   <
v$< >&>~:" "-!| vp07p08 < v>30g70g40g80g-! _-:0 v1+ \v\g04_01-*80g v>10g50g20g60g-! _-:0 v1+ \v\g02_01-*60g @>.," ",.,  Note that the interpreter has a single line input box. Pasting the preferred format replaces the newline with a space. Getting integer values with & already consumes leading spaces and zeros, so the preferred format can be read to the stack with &~&~&~&~ alone. Adding steps to put the values in a blank line so that one can retrieve and compare the vectors one coordinate at a time, the following 136 byte program (excluding notes right of line) can be used: v | blank line to store data > &10p~20p&30p~40pv | read and store first vector vp08~p07&p06~p05&< | (backwards) read and store second vector v>30g70g40g80g-! | load E/W coordinates _-:0 v1+ | subtract or add (based on direction) \v\g04_01-*80g | change directions if negative v>10g50g20g60g-! | load N/S coordinates _-:0 v1+ | subtract or add (based on direction) \v\g02_01-*60g | change directions if negative @>.," ",., | output  The Catch: The output forces an additional space after integers, so it is impossible to output in the preferred format. For example, output will appears as 1000 N 9999 W instead of 1000N 9999W. To check for and ignore spaces before each coordinate's direction on input, four additional loops (one for each coordinate) are needed. A single loop is shown below:  v$      <            | throw out " " and repeat
>&>~:" "-!|            | (start read number) get and check character
vp01p02   <            | store


The resulting program can have multiple spaces anywhere in the input (except between digits).

Example Input: 0001 N 4545 W 0999 N 5454 W

# Lua, 333 328 bytes

Features high-level invalid input system and absolutely innovative infinite loop for repeated use.

m=math.abs p=print::e::c={}for i=1,2 do for s in io.read():gmatch'%S+'do c[#c+1]=s end end for i=1,4 do n=c[i]:sub(1,-2)d=c[i]:sub(-1,-1)c[i]=d==("N"or"E")and n or-n end x=c[2]+c[4]y=c[1]+c[3]a=m(x)b=m(y)if(a or b)>9999 then p'Invalid input\n'goto e end x=x<0 and a.."W"or a.."E"y=y<0 and b.."S"or b.."N"p(y.." "..x.."\n")goto e


Enjoy ;)

Edit: saved 5 bytes from renaming math.abs as m and print as p

PHP 291 Bytes.

<?php $E=0;$N=0;$l=explode(PHP_EOL,STDIN);foreach($l as $i){$x=explode(' ',$i);$s=(substr($x[0],-1,1)=='N')?1:-1;$N=$N+((substr($x[0],0,-1)*$s));$s=(substr($x[1],-1,1)=='E')?1:-1;$E=$E+((substr($x[1],0,-1))*$s);}$l=($E<=0)?'W':'E';$u=($N<=0)?'S':'N';echo'<br/>'.abs($N).$u.' '.abs($E).$l;  Does not do anything clever, just plods through the problem. <?php$lines = explode(PHP_EOL, STDIN);
foreach ($lines as$line) {
$bits = explode(' ',$line);
$sign = (substr($bits[0],-1, 1) == 'N')? 1 : -1;
$N =$N + ( (substr($bits[0],0,-1) *$sign) );
$sign = (substr($bits[1],-1, 1) == 'E')? 1 : -1;
$E =$E + ( (substr($bits[1],0,-1)) *$sign );
}
$side = ($E<=0)?'W':'E';
$up = ($N<=0)?'S':'N';
echo '<br />'.abs($N).$up.' '.abs($E).$side;


The rules should have an additional clause saying only the language with at least 2 entries can win.

• I count 291. But your breakdown can be golfed down to 205. Nice approach. – Titus Sep 7 '16 at 0:04
• :-( You are quite right. Must have been a late night. – Paul Drewett Sep 7 '16 at 10:10
• but thanks for the inspiration. – Titus Sep 7 '16 at 11:08

# PHP, 169 bytes

Inspired by @Paul Drewett:

<?for($i=2;$i--;$e+=$p[1]*(substr($p[1],-1,1)<W?:-1))$n+=($p=explode(' ',trim(fgets(STDIN))))[0]*(substr($p[0],-1)<S?:-1);echo abs($n),'NS'[$n<0],' ',abs($e),'EW'[$e<0];


breakdown

for($i=2;$i--;                                  // loop twice
$e+=$p[1]*(substr($p[1],-1,1)<W?:-1) // add longitude to result )$n+=
($p=explode(' ',trim(fgets(STDIN)))) // read line, split at blank [0]*(substr($p[0],-1)<S?:-1)                // add latitude to result
;
echo abs($n),'NS'[$n<0],' ',abs($e),'EW'[$e<0]; // print result


# PHP, 206197 195 bytes

literally speaking, "moste verbose" would probably be Mathematica or Mathlab?

<?function i(){preg_match('#\d+(.) (\d+)(.)#',fgets(STDIN),$m);return[$m[0]*($m[1]<S?:-1),$m[2]*($m[3]<W?:-1)];}echo abs($v=($a=i())[0]+($b=i())[0]),'NS'[$v<0],' ',abs($v=$a[1]+$b[1]),'EW'[$v<0];  • output is pretty unformatted, not even a trainling newline • prints large numbers for too large result Now, how can I double the size of this ... breakdown function i() // read a pair of coordinates from STDIN, return signed values { // read line from STDIN and take (number,character,number,character) from it // will produce something like ["111N 222E","N","222","E"] preg_match('#\d+(.) (\d+)(.)#',fgets(STDIN),$m);
return[
// using a numerical operation on $m[0] casts the string to number (int in this case)$m[0]*($m[1]<S?:-1) // convert latitude to signed int: multiply with -1 for$m[1]=='S'
,
$m[2]*($m[3]<W?:-1) // convert longitude to signed int
];
}
$a=i();$b=i();  // read coordinates from STDIN
echo            // output:
abs($v=$a[0]+$b[0]) // 1. unsigned sum of latitudes ,'NS'[$v<0]             // 2. direction depending on sign
,' ',                   // 3. delimiter
abs($v=$a[1]+$b[1]), // 4. unsigned sum of longitudes 'EW'[$v<0]              // 5. direction depending on sign
;


# GolfScript - 111 bytes

{~)}:"S":"E";{}:"N":"W";"
"/~[{' '/[{.-1<~\-1>~}/]\}2*]zip[{{+}*}/](.0<{abs'S'}{'N'}if' '+@~.0<{abs'E'}{'W'}if


### Explanation

{~)}:"S":"E";    # Aliases these as *-1
{}:"N":"W";      # Alieses to nop
"\n"/~           # Splits lines
[{' '/[{.-1<~\-1>~}/]\}2*]zip    # Parses the input as vectors and applies the aliases
[{{+}*}/]                         # Vector sum
(.0<{abs'S'}{'N'}if' '+@          # Formats output
~.0<{abs'E'}{'W'}if


# Python 2.7 - 232 175 bytes

Works for all of the test cases. Always inserts N or W for 0. I'm sure a better Python golfer than me could shave a good few more bytes off.

f=(raw_input().split(" ")+raw_input().split(" "))
for x in range(4):
i=f[x]
if "S" in i or "E" in i:i="-"+i
f[x]=int(i[:-1])
n=f[0]+f[2]
q=f[1]+f[3]
print str(abs(n))+("S" if n<0 else "N"),str(abs(q))+("E" if q<0 else "W")


EDIT

Golfed off a mighty 57 bytes due to some great tips from @mbomb007 and @Titus plus by spotting the fact that I could combine the two raw_inputs with a space then just use one .split() which splits on the space without specifying it. The algorithm is the same but just much better golfed.

f=(raw_input()+" "+raw_input()).split()
for x in 0,1,2,3:
i=f[x]
if i[-1]in"SE":i="-"+i
f[x]=int(i[:-1])
n=f[0]+f[2]
q=f[1]+f[3]
printabs(n)+"NS"[n<0],abs(q)+"WE"[q<0]

• replace ...str(x)... with ...x...; replace ("E" if q<0 else "W") with "WE"[q<0] – mbomb007 Sep 6 '16 at 15:16
• This should get you started. See the Python tips page – mbomb007 Sep 6 '16 at 15:26
• Thanks @mbomb007. Much appreciated. Will check out the tips page and see what else I can do. – ElPedro Sep 6 '16 at 15:38
• repl.it/DRWh – mbomb007 Sep 6 '16 at 15:57
• "S" in i or "E" in i can surely be written i in "ES" or similar. – Titus Sep 6 '16 at 15:59