Convert degrees to one of the 32 points of the compass

  • 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.


    @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...

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

    @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!

    Would have been more fun if there were input from -360 to 360 degree (negative means anti-clockwise) and a bonus!.

    For people not looking for a challenge, the easy solution is to find the possible output for which the distance is minimal from the input angle, using a lookup table angle <-> name.

  • user2846289

    user2846289 Correct answer

    7 years ago

    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}[email protected]_)),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}[email protected]_
    )
    ),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.


    You have a typo in your code: ***sourth*** should be ***south*** (2nd statement that starts with ***s/b/ by ...***

    Those first 3 regexps can be replaced by y/NS/SN/; for 10 chars

    @bazzargh, yes, and not only that ;-)

License under CC-BY-SA with attribution


Content dated before 7/24/2021 11:53 AM

Tags used