Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

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:

> heading 0.1

North

> heading 11.25

North by East

> heading 22.7

North Northeast

> heading 44.99

Northeast

> heading 91

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!

share|improve this question
9  
50 '(Apostrophe) in a single question. Hats off! :D –  Wasi Jan 4 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 at 20:35
1  
Shouldn't this be "N be an integer between 0 and 31 inclusive"? –  nwellnhof Jan 5 at 21:01
    
@nwellnhof You're right! Updated... :) –  WallyWest Jan 5 at 22:14
    
@Wasi, you think that's impressive, try typing in pirate! Arrr! –  WallyWest Jan 5 at 22:19

5 Answers 5

up vote 6 down vote accepted

Perl 5.10 using substitution, 231 228 226 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

Four newlines added for readability.

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

Edit: 2 bytes less using qw()

share|improve this answer

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

        float heading = Float.parseFloat(aaarrrgs[0]);

        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)));}}
share|improve this answer
21  
+1 for aaarrrgs –  Danko Durbić Jan 4 at 12:41
2  
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 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 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 at 0:35
2  
@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 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.

share|improve this answer
1  
Arrr, that be a clever use of a function there... –  WallyWest Jan 5 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

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

Perl 5.10, 262 257 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

Four newlines added for readability.

Edit: Three bytes less thanks to @Dom Hastings

share|improve this answer
    
Hey @nwellnhof, Looks pretty comprehensive! You can save a few more chars, removing the ; at the end of sub p and switch shift to pop. –  Dom Hastings Jan 5 at 19:45
    
@nwellhoff I didn't know Perl could accept strings without them being in quotes? (re: line 1) –  WallyWest Jan 5 at 22:17
1  
@Eliseod'Annunzio Perl accepts strings without quotes in non-strict mode if they don't clash with function names or reserved words. –  nwellnhof Jan 5 at 22:38

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

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