Cardinal Direction
Wednesday, November 19, 2025
Cardinal direction
describes points on a compass — North (N), East (E), South (S),
and West (W).
In addition to those, there are also 4 intercardinal directions (Northwest
or NW, NE, SW, SE), 8 secondary intercardinal directions
(North-Northwest or NNW, WNW, NNE, ENE, WSW, SSW,
ESE, SSE), as well as 16 tertiary intercardinal directions
(Northwest-by-North or NWbN, etc.).
In fact, you can see all the points of the compass divided into 32 textual directions:
I like puzzles and sometimes those come from code golfing. I stumbled across two symmetric challenges on the Code Golf and Coding Challenges Stack Exchange:
I thought it would be a good task to code in Factor.
We start by enumerating the descriptive names for all 32 points of the compass. For convenience we use the quoted words vocabulary.
CONSTANT: directions qw{
N NbE NNE NEbN NE NEbE ENE EbN
E EbS ESE SEbE SE SEbS SSE SbE
S SbW SSW SWbS SW SWbW WSW WbS
W WbN WNW NWbW NW NWbN NNW NbW
}
Then, parsing a compass degrees to a textual name involves rounding to the nearest 32-point:
: compass>string ( compass -- str )
360/32 / round >integer 32 mod directions nth ;
We can use some test cases from the challenges to check that it works:
{ "N" } [ 0 compass>string ] unit-test
{ "NNE" } [ 23.97 compass>string ] unit-test
{ "NEbN" } [ 33.7 compass>string ] unit-test
{ "ENE" } [ 73.12 compass>string ] unit-test
{ "EbN" } [ 73.13 compass>string ] unit-test
{ "SWbS" } [ 219 compass>string ] unit-test
{ "W" } [ 275 compass>string ] unit-test
{ "WbN" } [ 276 compass>string ] unit-test
{ "WNW" } [ 287 compass>string ] unit-test
And the reverse converts the name back to compass degrees by grabbing the index and multiplying:
: string>compass ( str -- compass )
directions index 360/32 * ;
It might not be the shortest solution, but it works and it was fun to build!