12
\$\begingroup\$

The 32-point compass is... interesting, to say the least.

image

By Denelson83 (Own work) [GFDL or CC-BY-SA-3.0], via Wikimedia Commons

Your challenge is to take a degree measure, and convert it into a direction on the 32-point compass.

Each direction is 11.25 (360 / 32) degrees farther than the previous. For example, N (north) is 0 degrees, NbE (north by east) is 11.25 degrees, NNE (north-northeast) is 22.5 degrees, etc.

As for how you're supposed to get the directions,

  • 0 degrees is N, 90 degrees is E, 180 degrees is S, and 270 degrees is W.

    • These are called cardinal directions.
  • The halfway points between the cardinal directions are simply the cardinal directions they're between concatenated. N or S always go first, and W or E always are second.

    • These are called ordinal directions.
  • The halfway points between the cardinal and ordinal directions are the directions they're between concatenated, again, with a "-" in between. Cardinal directions go first, ordinal second.

    • These are called secondary-intercardinal directions.
  • The halfway points between secondary-intercardinal directions and other directions are the other directions "by" the cardinal direction they're closest to (other than the one directly next to them, of course).

    • I have no idea what these are called :P

If all this explanation hurts your brain as much as mine, you can refer to this chart:

1   North               N
2   North by east       NbE
3   North-northeast     NNE
4   Northeast by north  NEbN
5   Northeast           NE
6   Northeast by east   NEbE
7   East-northeast      ENE
8   East by north       EbN
9   East                E
10  East by south       EbS
11  East-southeast      ESE
12  Southeast by east   SEbE
13  Southeast           SE
14  Southeast by south  SEbS
15  South-southeast     SSE
16  South by east       SbE
17  South               S
18  South by west       SbW
19  South-southwest     SSW
20  Southwest by south  SWbS
21  Southwest           SW
22  Southwest by west   SWbW
23  West-southwest      WSW
24  West by south       WbS
25  West                W
26  West by north       WbN
27  West-northwest      WNW
28  Northwest by west   NWbW
29  Northwest           NW
30  Northwest by north  NWbN
31  North-northwest     NNW
32  North by west       NbW

Here is a more detailed chart and possibly better explanation of the points of the compass.

Your challenge is to take input in degrees, and output the full name of the compass direction it corresponds to, along with its abbreviation.

Test cases:

Input  Output
0      North N
23.97  North-northeast NNE
33.7   Northeast by north NEbN
73.12  East-northeast ENE
73.13  East by north EbN
219    Southwest by south SWbS
275    West W
276    West by north WbN
287    West-northwest WNW

All capitalization must be preserved, as in the test cases. Maximum number of decimal places is 2. All input numbers will be greater than or equal to 0, and less than 360. If a decimal point is present, there will be digits on both sides (you don't have to handle .1 or 1.).

This is , so the shortest code in bytes wins.

\$\endgroup\$
  • \$\begingroup\$ @WallyWest Hmm, this one allows arrays, has different capitalization, and has no "between," but I didn't notice that (possibly because of the... interesting title :P). I'll see what I can do to make it different enough... \$\endgroup\$ – Doorknob Feb 23 '14 at 22:33
  • 3
    \$\begingroup\$ @WallyWest There, now you have to output the abbreviation too. Along with all the other differences, that should be enough to make it a non-dup. (oh, also this one has dashes too) \$\endgroup\$ – Doorknob Feb 23 '14 at 22:36
  • \$\begingroup\$ @WallyWest There be no answers in "R" to your previous question (there weren't even any in "C"!) I hopes we'll see some this time, shipmates! \$\endgroup\$ – Level River St Feb 25 '14 at 9:33
  • \$\begingroup\$ Would have been more fun if there were input from -360 to 360 degree (negative means anti-clockwise) and a bonus!. \$\endgroup\$ – Mukul Kumar Feb 25 '14 at 17:05
4
\$\begingroup\$

Perl, 250 236 231 188 187

Edit: Some bytes off exploiting symmetry (as I've seen in @bazzargh solution)

+Edit: And some evil tricks...

+Edit: Back to where I started (working with list, not string), and exploiting more symmetry = 1 byte off and a whole lot uglier.

$_=((@_=(1,@_=qw(1b3 1-13 13b1 13 13b3 3-13 3b1),3,map{y/1/2/r}reverse@_)),map{y/312/421/r}@_)[int<>/11.25+.5];print ucfirst s/\w/(' by ',north,south,east,west)[$&]/ger,' ',y/1-4-/NSEW/dr

Pretty-printed:

$_=(
    (@_=
        (
            1,
            @_=qw(1b3 1-13 13b1 13 13b3 3-13 3b1),
            3,
            map{y/1/2/r}reverse@_
        )
    ),map{y/312/421/r}@_
)[int<>/11.25+.5];

print ucfirst s/\w/(' by ',north,south,east,west)[$&]/ger,' ',y/1-4-/NSEW/dr

5.014 required because of r modifier.

\$\endgroup\$
  • \$\begingroup\$ You have a typo in your code: sourth should be south (2nd statement that starts with s/b/ by ... \$\endgroup\$ – RononDex Feb 25 '14 at 13:39
  • \$\begingroup\$ Those first 3 regexps can be replaced by y/NS/SN/; for 10 chars \$\endgroup\$ – bazzargh Feb 25 '14 at 17:51
  • \$\begingroup\$ @bazzargh, yes, and not only that ;-) \$\endgroup\$ – user2846289 Feb 25 '14 at 17:54
6
\$\begingroup\$

Javascript 470 453 438 434 432 421 404

s=String;s.prototype.a=s.prototype.replace;var a=prompt()/11.25,a=a+0.5|0,b,k,c=a,d=c%8,c=c/8|0,e=["north","east","south","west"],f,g,h;f=e[c];g=e[(c+1)%4];h=f==e[0]|f==e[2]?f+g:g+f;b="1;1 by 2;1-C;C by 1;C;C by 2;2-C;2 by 1".split(";")[d].a(1,f).a(2,g).a("C",h);k=b.a(/north/g,"N").a(/east/g,"E").a(/south/g,"S").a(/west/g,"W").a(/by/g,"b").a(/[\s-]/g,"");b=b[0].toUpperCase()+b.slice(1);alert(b+" "+k)

You can copy this code to your console and execute it. It prompts you for the degrees input and outputs the result with alert();

Ungolfed Javascript can be found at this fiddle: http://jsfiddle.net/AezL3/11

\$\endgroup\$
  • \$\begingroup\$ +1 Nice but be careful : "All capitalization must be preserved, as in the test cases." \$\endgroup\$ – user16229 Feb 25 '14 at 10:15
  • \$\begingroup\$ @BenH Which test case fails the capitalization check? Thanks for this, btw. This came in handy for my web interface I'm writing. \$\endgroup\$ – Steven Lu Jan 5 '16 at 5:56
  • \$\begingroup\$ By the way, this does die for 355 degrees to 360 degrees. The fix is easy. Just make calcPoint(32) do what 0 does, so you can do this with %32 or any similar. \$\endgroup\$ – Steven Lu Jan 5 '16 at 6:01
  • \$\begingroup\$ @StevenLu it took me a while to figure out what you means, but this line var name = calcPoint(input % 32); does the trick \$\endgroup\$ – Orwellophile Oct 20 '17 at 10:03
4
\$\begingroup\$

Haskell 415 372 347 330 317 304 301C

Ended up converging on a solution like @VadimR's (and the symmetry's back!). Usage: h 219 outputs "Southwest by south SWbS"

d"N"="north"
d"S"="south"
d"E"="east"
d"W"="west"
d"b"=" by "
d"-"="-"
d(x:y)=d[x]++d y
e(x:y)=x:tail(d$x:y)
k 'N'='S'
k 'S'='N'
k 'E'='W'
k x=x
r="N NbE N-NE NEbN NE NEbE E-NE EbN E EbS E-SE SEbE SE SEbS S-SE SbE "
p=words$r++(map k r)
g x=p!!mod(round$x/11.25)32
h x=e(g x)++(filter(/='-')$' ':g x)

3 more chars gone, thanks @shiona.

\$\endgroup\$
  • \$\begingroup\$ drop 1 is same as tail. Also if I'm not mistaken you can do e l@(x:_)=x:tail$d l to shave still one more char. \$\endgroup\$ – shiona Feb 25 '14 at 17:17
  • \$\begingroup\$ can't believe I missed that. Thanks! \$\endgroup\$ – bazzargh Feb 25 '14 at 17:41

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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