Boxing The Compass

October 12, 2018

Modern navigators use the 360° angles of a circle to point to compass directions, but traditional mariners use compass points with names like SW and ENE.

Your task is to write a program that converts from degrees to compass points. When you are finished, you are welcome to read or run a suggested solution, or to post your own solution or discuss the exercise in the comments below.

Advertisement

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))
    
    (defun direction (heading-degrees)
      (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)
    import System.IO (IOMode(ReadMode), hGetContents, withFile)
    
    -- The 32 compass points defined in the Wikipedia page
    -- 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
    

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

%d bloggers like this: