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

Pages: 1 2

### 4 Responses to “Boxing The Compass”

1. Pascal Bourguignon said
```
(defparameter *directions*
;; from heading 0 degree up. (N = 0, E = 90)
'(n nne ne ene
e ese se sse
s ssw sw wsw
w wnw nw nnw))

(let* ((divisions  (length *directions*))
(separation (/ 360 divisions))
(offset     (/ separation 2)))
(elt *directions* (truncate (mod (+ heading-degrees offset) 360) separation))))

(loop for d from 0 to 360 by 22 collect (list d (direction d)))
;; --> ((0 n) (22 nne) (44 ne) (66 ene) (88 e) (110 ese) (132 se) (154 sse)
;;      (176 s) (198 ssw) (220 sw) (242 wsw) (264 w) (286 wnw) (308 nw) (330 nnw) (352 n))

```
2. Darren Bane said

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

3. Globules said

A Haskell version. It was difficult, but I resisted the temptation to do the 128 compass points…

```import Text.Printf (PrintfType, printf)
import System.Environment (getArgs, getProgName)

-- https://en.wikipedia.org/wiki/Points_of_the_compass#Compass_points.
points :: [String]
points = ["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"]

-- Convert degrees to a compass point index between 0 and 31.
indexFromDegrees :: (RealFrac a, Integral b) => a -> b
indexFromDegrees deg = (round (deg * 1000) + 5625) `mod` 360000 `div` 11250

-- Convert degrees to the name of a compass point.
pointFromDegrees :: RealFrac a => a -> String
pointFromDegrees deg = points !! indexFromDegrees deg

printPointName :: PrintfType a => Double -> a
printPointName deg = printf "%6.2f°  %s\n" deg (pointFromDegrees deg)

main :: IO ()
main = do
args <- getArgs
prog <- getProgName
case args of
[file] -> withFile file ReadMode \$ \h -> do
degs <- map read . lines <\$> hGetContents h
mapM_ printPointName degs
_      -> putStrLn \$ "Usage: " ++ prog ++ " path"
```
```\$ ./compass input.txt
0.00°  N
16.87°  NbE
16.88°  NNE
33.75°  NEbN
50.62°  NE
50.63°  NEbE
67.50°  ENE
84.37°  EbN
84.38°  E
101.25°  EbS
118.12°  ESE
118.13°  SEbE
135.00°  SE
151.87°  SEbS
151.88°  SSE
168.75°  SbE
185.62°  S
185.63°  SbW
202.50°  SSW
219.37°  SWbS
219.38°  SW
236.25°  SWbW
253.12°  WSW
253.13°  WbS
270.00°  W
286.87°  WbN
286.88°  WNW
303.75°  NWbW
320.62°  NW
320.63°  NWbN
337.50°  NNW
354.37°  NbW
354.38°  N
```
4. Daniel said

Here’s a 32-point compass solution in Python.

```def convert(degrees):
compass_points = [
"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"
]
divisor = 360.0 / len(compass_points)
idx = round(degrees / divisor) % len(compass_points)
return compass_points[idx]

print(convert(70))
print(convert(230))
```

Output:

```ENE
SW
```