Boxing The Compass
October 12, 2018
There are 360° in a circle but 16 compass points, so each compass point encompasses 22.5°, thus 11.25° left and right of the actual heading. So our function adds 11.25°, divides by 22.5°, rounds down, takes the result mod 16, and looks up the compass heading in a table:
(define (compass d) (vector-ref '#(N NNE NE ENE E ESE SE SSE S SSW SW WSW W WNW NW NNW) (modulo (inexact->exact (floor (/ (+ d 11.25) 22.5))) 16)))
Here are some examples:
> (compass 70) ENE > (compass 230) SW
You can run the program at https://ideone.com/i3GlHe.
directions(
[n, nne, ne, ene,
e, ese, se, sse,
s, ssw, sw, wsw,
w, wnw, nw, nnw]).
compass(D, Result) :-
directions(Directions),
length(Directions, Divisions),
Separation is 360 / Divisions,
Offset is Separation / 2,
I is mod(floor((D + Offset) / Separation), Divisions) + 1,
nth(I, Directions, Result).
A Haskell version. It was difficult, but I resisted the temptation to do the 128 compass points…
Here’s a 32-point compass solution in Python.
Output: