3D compass point from 3D coordinates
Given 3 dimensional (3D) Cartesian coordinates (x, y, z), output the 3D compass point that comes nearest to describing the direction from the origin.
Definitions
Directions
In reality, the direction of North changes as you move across the surface of the globe. This challenge is based in a simplified universe where each compass point always denotes the same direction, but it is in 3D. The individual directions are defined as follows:
- East: the positive x direction, from the origin towards (1, 0, 0).
- West: the negative x direction, from the origin towards (-1, 0, 0).
- North: the positive y direction, from the origin towards (0, 1, 0).
- South: the negative y direction, from the origin towards (0, -1, 0).
- Up: the positive z direction, from the origin towards (0, 0, 1).
- Down: the negative z direction, from the origin towards (0, 0, -1).
Compass points
A compass point consists of 1, 2, or 3 letters from EWNSUD
(being the initial letters of the directions mentioned). A compass point is defined as follows (the definitions deliberately use different terms than real world compass points to avoid the conflict of redefining existing terms):
- A primary compass point is 1 letter.
- A secondary compass point is 2 letters, denoting the direction half way between them.
- A secondary compass point cannot combine opposing directions. EW, NS, and UD are not valid secondary compass points.
- A secondary compass point cannot be a repeated letter. EE, WW, NN, SS, UU, and DD are not valid secondary compass points.
- The order of letters in a secondary compass point is always z axis direction (U/D), then y axis direction (N/S), then x axis direction(E/W). That is, NE rather than EN, DN rather than ND, and UW rather than WU (the same does not apply to a tertiary compass point, where the direction is dependent on the order of the letters).
- A tertiary compass point is 3 letters, which is interpreted as a primary compass point (1 letter) followed by a secondary compass point (2 letters), denoting the direction half way between them.
- The modifying primary compass point is either one of the 2 directions in the secondary compass point, or perpendicular to both. For example:
- NW can be modified by N or W, to give NNW or WNW, or by U or D (perpendicular to both N and W), to give UNW or DNW.
- NW cannot be modified by E or S (this would give additional names to already named directions). So ENW and SNW are not valid (ENW is exactly equivalent to the valid NNE and SNW is exactly equivalent to the valid WSW).
- The modifying primary compass point is either one of the 2 directions in the secondary compass point, or perpendicular to both. For example:
Direction for each compass point
TODO: list of each compass point and its normalised direction vector
Input
- The input will be 3 integer coordinates in the order x, y, z.
- You may choose to take these coordinates in any format that does not already provide part of the solution.
- Each of x, y, and z will be in the range -127 to 127 (both inclusive).
- The input will never be (0, 0, 0).
Output
- A string containing 1, 2, or 3 uppercase letters as described above.
- If more than 1 compass point is nearest to the direction of the input from the origin, any of them is a valid output, but you must output only 1 of them.
- The output must be one of the 66 valid compass points defined above. Each one uniquely defines a direction - there are no 2 valid compass points that define the same direction. The complete list follows:
- 6 primary compass points: E, W, N, S, U, D.
- 12 secondary compass points: UN, US, UE, UW, DN, DS, DE, DW, NE, NW, SE, SW.
- 48 tertiary compass points: UUN, NUN, EUN, WUN, UUS, SUS, EUS, WUS, UUE, EUE, NUE, SUE, UUW, WUW, NUW, SUW, DDN, NDN, EDN, WDN, DDS, SDS, EDS, WDS, DDE, EDE, NDE, SDE, DDW, WDW, NDW, SDW, NNE, ENE, UNE, DNE, NNW, WNW, UNW, DNW, SSE, ESE, USE, DSE, SSW, WSW, USW, DSW.
- In short, one of:
- 1 letter.
- 2 perpendicular letters in the correct order.
- 3 letters that contain no two opposing letters (never containing both E and W, or both N and S, or both U and D) and end in a valid 2 letter combination.
Test cases
Test cases are in the format x, y, z : "valid", "outputs"
Note that where there is more than 1 valid output, you must choose only 1 of them.
-2, -2, -2 : "WDS", "SDW", "DSW"
-2, -2, -1 : "WDS", "SDW"
-2, -2, 0 : "SW"
-2, -2, 1 : "WUS", "SUW"
-2, -2, 2 : "WUS", "SUW", "USW"
-2, -1, -2 : "WDS", "DSW"
-2, -1, -1 : "WDS"
-2, -1, 0 : "WSW"
-2, -1, 1 : "WUS"
-2, -1, 2 : "WUS", "USW"
-2, 0, -2 : "DW"
-2, 0, -1 : "WDW"
-2, 0, 0 : "W"
-2, 0, 1 : "WUW"
-2, 0, 2 : "UW"
-2, 1, -2 : "WDN", "DNW"
-2, 1, -1 : "WDN"
-2, 1, 0 : "WNW"
-2, 1, 1 : "WUN"
-2, 1, 2 : "WUN", "UNW"
-2, 2, -2 : "WDN", "NDW", "DNW"
-2, 2, -1 : "WDN", "NDW"
-2, 2, 0 : "NW"
-2, 2, 1 : "WUN", "NUW"
-2, 2, 2 : "WUN", "NUW", "UNW"
-1, -2, -2 : "SDW", "DSW"
-1, -2, -1 : "SDW"
-1, -2, 0 : "SSW"
-1, -2, 1 : "SUW"
-1, -2, 2 : "SUW", "USW"
-1, -1, -2 : "DSW"
-1, -1, -1 : "WDS", "SDW", "DSW"
-1, -1, 0 : "SW"
-1, -1, 1 : "WUS", "SUW", "USW"
-1, -1, 2 : "USW"
-1, 0, -2 : "DDW"
-1, 0, -1 : "DW"
-1, 0, 0 : "W"
-1, 0, 1 : "UW"
-1, 0, 2 : "UUW"
-1, 1, -2 : "DNW"
-1, 1, -1 : "WDN", "NDW", "DNW"
-1, 1, 0 : "NW"
-1, 1, 1 : "WUN", "NUW", "UNW"
-1, 1, 2 : "UNW"
-1, 2, -2 : "NDW", "DNW"
-1, 2, -1 : "NDW"
-1, 2, 0 : "NNW"
-1, 2, 1 : "NUW"
-1, 2, 2 : "NUW", "UNW"
0, -2, -2 : "DS"
0, -2, -1 : "SDS"
0, -2, 0 : "S"
0, -2, 1 : "SUS"
0, -2, 2 : "US"
0, -1, -2 : "DDS"
0, -1, -1 : "DS"
0, -1, 0 : "S"
0, -1, 1 : "US"
0, -1, 2 : "UUS"
0, 0, -2 : "D"
0, 0, -1 : "D"
0, 0, 1 : "U"
0, 0, 2 : "U"
0, 1, -2 : "DDN"
0, 1, -1 : "DN"
0, 1, 0 : "N"
0, 1, 1 : "UN"
0, 1, 2 : "UUN"
0, 2, -2 : "DN"
0, 2, -1 : "NDN"
0, 2, 0 : "N"
0, 2, 1 : "NUN"
0, 2, 2 : "UN"
1, -2, -2 : "SDE", "DSE"
1, -2, -1 : "SDE"
1, -2, 0 : "SSE"
1, -2, 1 : "SUE"
1, -2, 2 : "SUE", "USE"
1, -1, -2 : "DSE"
1, -1, -1 : "EDS", "SDE", "DSE"
1, -1, 0 : "SE"
1, -1, 1 : "EUS", "SUE", "USE"
1, -1, 2 : "USE"
1, 0, -2 : "DDE"
1, 0, -1 : "DE"
1, 0, 0 : "E"
1, 0, 1 : "UE"
1, 0, 2 : "UUE"
1, 1, -2 : "DNE"
1, 1, -1 : "EDN", "NDE", "DNE"
1, 1, 0 : "NE"
1, 1, 1 : "EUN", "NUE", "UNE"
1, 1, 2 : "UNE"
1, 2, -2 : "NDE", "DNE"
1, 2, -1 : "NDE"
1, 2, 0 : "NNE"
1, 2, 1 : "NUE"
1, 2, 2 : "NUE", "UNE"
2, -2, -2 : "EDS", "SDE", "DSE"
2, -2, -1 : "EDS", "SDE"
2, -2, 0 : "SE"
2, -2, 1 : "EUS", "SUE"
2, -2, 2 : "EUS", "SUE", "USE"
2, -1, -2 : "EDS", "DSE"
2, -1, -1 : "EDS"
2, -1, 0 : "ESE"
2, -1, 1 : "EUS"
2, -1, 2 : "EUS", "USE"
2, 0, -2 : "DE"
2, 0, -1 : "EDE"
2, 0, 0 : "E"
2, 0, 1 : "EUE"
2, 0, 2 : "UE"
2, 1, -2 : "EDN", "DNE"
2, 1, -1 : "EDN"
2, 1, 0 : "ENE"
2, 1, 1 : "EUN"
2, 1, 2 : "EUN", "UNE"
2, 2, -2 : "EDN", "NDE", "DNE"
2, 2, -1 : "EDN", "NDE"
2, 2, 0 : "NE"
2, 2, 1 : "EUN", "NUE"
2, 2, 2 : "EUN", "NUE", "UNE"
Explanations are optional, but I'm more likely to upvote answers that have one.
Sandbox questions
- Is it more useful to include or omit parentheses in the test case format?
- Are there any edge cases that should be included in the test cases?
TO DO BEFORE POSTING
- ADD DIAGRAMS SHOWING THE PRIMARY, SECONDARY, AND TERTIARY COMPASS POINTS. MAYBE ONE FOR PRIMARY, ONE FOR SECONDARY, ONE FOR TERTIARY, AND ONE SHOWING THEM ALL TOGETHER. MAYBE COMMENT ON WHETHER THEY ARE EQUALLY SPACED OVER THE SPHERE. CONSIDER A VORONOI MAP ON THE SURFACE OF THE UNIT SPHERE, COLOURING REGIONS THAT ALL MAP TO THE SAME COMPASS POINT
- INCLUDE TEST CASES VERY CLOSE TO THOSE POINTS THAT HAVE MORE THAN 1 VALID OUTPUT - INCLUDE CASES CLOSE TO EQUIDISTANT FROM 2 DIRECTIONS (A CASE FROM EACH SIDE) AND CASES CLOSE TO EQUIDISTANT FROM 3 DIRECTIONS (A CASE FROM ALL 3 SIDES, POTENTIALLY 6 TO COVER BOTH OPTIONS FOR SECOND CLOSEST TOO)
2 comment threads