# Thar she blows!

Arrr... Ahoy there, me maties! Unfurl tha' mainsail! Full to starboard! Ah, feel th' wind in yer hair!

Right, me hearties... I be needin' a bit of yer codin' skills! Me crew are a li'l more modernized than meself... I still be preferrin' th' points of th' compass (see here for more info, Arrr...) while me crew are always usin' a headin'... I be wantin' an easy way of convertin' this twaddle they call a headin' into what I be able to understand, Arrr!

What I be needin' is code tha' be takin' input of a number (decimals are okay) such tha' 0 <= the headin' < 360 and it be spittin' out th' answer as th' closest compass point! Arrr!

Here be some examples:

North

North by East

North Northeast

Northeast

East

Now, if'n th' headin' ye be givin' be such that it falls exactly in th' middle of two compass points, don' ye be frettin', me hearties... I be expectin' th' code to spit out Between <point 1> and <point 2>, e.g. heading 5.625 will say Between North and North by East This only be happenin' for a headin' tha' be satisfyin' the equation H = 5.625 + 11.25(N) where H be th' headin' and N be an integer between 0 and 31 inclusive...

Two restrictions tho'...

1) I not be wantin' ye to use arrays for storin' yer data for the points or th' headin's... Tha' be cheatin', sir, an' ye be gettin' a taste of me blunderbuss... This has t' be calculated, jus' like th' old days! Arrr!

2) Shortest code wins, or I'll be makin' ye walk th' plank... Arrr!

-
50 '(Apostrophe) in a single question. Hats off! :D – Wasi Jan 4 '14 at 11:33
Is using an object in javascript with numeric keys cheating? I mean yaarrr! be it cheatin', ya landlubber? – Tim Seguine Jan 5 '14 at 20:35
Shouldn't this be "N be an integer between 0 and 31 inclusive"? – nwellnhof Jan 5 '14 at 21:01
@nwellnhof You're right! Updated... :) – WallyWest Jan 5 '14 at 22:14
@Wasi, you think that's impressive, try typing in pirate! Arrr! – WallyWest Jan 5 '14 at 22:19

## Perl 5.10 using substitution, 231228226 224

@c=(north,east,south,west);
@q=qw(P PbR P-Q QbP Q QbR R-Q RbP);
sub p{\$j=\$_[0]>>3&3;\$_=\$q[7&pop];s/P/\$c[\$j]/;s/Q/\$c[\$j+1&2]\$c[\$j|1]/;s/R/\$c[\$j+1&3]/;s/b/ by /;ucfirst}
\$a=<>/11.25+.5;
say\$a==int\$a&&'Between '.p(\$a-1).' and ',p\$a

Edit: Golfed 2 more bytes using pop. Thanks @Dom Hastings

Edit: 2 bytes less using qw()

-

I be spendin' way too much time on this here treasure hunt, but here's a solution in Java:

public class Aaaaarrrr {

public static void main(String[] aaarrrgs) {

final List<String> points = Arrays.asList("North",
"North by east", "North-northeast", "Northeast by north",
"Northeast", "Northeast by east", "East-northeast",
"East by north", "East", "East by south", "East-southeast",
"Southeast by east", "Southeast", "Southeast by south",
"South-southeast", "South by east", "South", "South by west",
"South-southwest", "Southwest by south", "Southwest",
"Southwest by west", "West-southwest", "West by south", "West",
"West by north", "West-northwest", "Northwest by west",
"Northwest", "Northwest by north", "North-northwest",
"North by west");

float cp = heading / 360.0f * 32.0f;
if (cp % 1 == 0.5f)
System.out.print("Between " + points.get((int)Math.floor(cp)) + " and ");

System.out.println(points.get(Math.round(cp)));

}
}

edit If I minimize the above code and make it real ugly it would become this:

## Java, 770 chars

import java.util.*;class A{public static void main(String[] r){List<String> l=Arrays.asList("North","North by east","North-northeast","Northeast by north","Northeast","Northeast by east","East-northeast","East by north","East","East by south","East-southeast","Southeast by east","Southeast","Southeast by south","South-southeast","South by east","South","South by west","South-southwest","Southwest by south","Southwest","Southwest by west","West-southwest","West by south", "West","West by north","West-northwest","Northwest by west","Northwest","Northwest by north","North-northwest","North by west");float c=Float.parseFloat(r[0])/360.0f*32.0f;if (c%1==0.5f) System.out.print("Between "+l.get((int)Math.floor(c))+" and ");System.out.println(l.get(Math.round(c)));}}
-
+1 for aaarrrgs – Danko Durbić Jan 4 '14 at 12:41
I'm sure that didn't help me on the "shortest code wins" rule, but since I'm using Java anyway... – Jeen Broekstra Jan 4 '14 at 12:52
I admire the approach, though you're using the Arrays.asList command, pardon me here for my Java ignorance, but isn't that using a storage array? Or is this a sneaky way of introducing the array in the form of a list? ;) – WallyWest Jan 5 '14 at 0:30
@Jeen, can ye show me wha' ye could get if ye really honker down and reduce tha' code there? – WallyWest Jan 5 '14 at 0:35
@Eliseod'Annunzio wrt the array, I thought you only meant I couldn't use it to store a mapping between names and heading intervals. This array (list) only stores the actual names. But if that is beyond the rules, I imagine it could be changed to use a switch statement instead (with a few extra chars, unfortunately). Oh and condensed version of same code added. I'll have a think about further whittling it down by actually changing how it works. – Jeen Broekstra Jan 5 '14 at 7:54

## Python, 264

n='north'
e='east'
s='south'
w='west'
b=' by '
def f(H):x,y,z=(n,e,s,w,e,s,w,n,n+e,s+e,s+w,n+w)[int(H%360/90)::4];return(x,x+b+y,x+'-'+z,z+b+x,z,z+b+y,y+'-'+z,y+b+x)[int(H%90*4/45)].capitalize()
h=input()+5.625
print h%11.25and f(h)or'Between '+f(h-1)+' and '+f(h)

This uses capitalisation as per the wikipedia page and should work for any number.

-
Arrr, that be a clever use of a function there... – WallyWest Jan 5 '14 at 0:31

### Arrr Python, 336

A,R,r=int,input()/360.*32,' by #South#north#West#East#south#North#west#east#-#/#Between#and'.split('#')
a=''.join(r[A(c,16)]for c in'6A608A6928A6802A68A6808A4928A402A4A405A4958A1808A18A1805A1958A108A1A107A1957A1705A17A1707A3957A305A3A302A3927A6707A67A6702A6927A607').split('/')
if R%1==.5:print r[11],a[A(R)],r[12],
print a[A(round(R))]

Thanks @Jeen

-
I be a little confused here @AsksAnyway, what be th' use of tha' there leviathan of a string? ... Arrr... – WallyWest Jan 5 '14 at 0:34
It "calculates" the names of the compass points. It's a way of reducing the code size. – AsksAnyway Jan 5 '14 at 10:02
+1 for your "Arrr"... – WallyWest Sep 11 '14 at 23:49

## Perl 5.10, 262257 254

Somewhat similar to one of the Python solutions:

\$n=north;\$e=east;\$s=south;\$w=west;
@d=(\$n,\$n.\$e,\$e,\$s.\$e,\$s,\$s.\$w,\$w,\$n.\$w,\$n);
sub p{\$j=pop;\$i=\$j>>2;ucfirst((\$d[\$i],"\$d[\$i] by \$d[\$i+2&~1]","\$d[\$i+1&~1]-\$d[\$i|1]","\$d[\$i+1] by \$d[\$i&~1]")[\$j&3])}
\$a=<>/11.25+.5;
say\$a==int\$a&&'Between '.p(\$a-1).' and ',p\$a