Output a Face on a Numbered Cube Assign the numbers 0 through 7 to the 8 vertices of a cube in any way you want. Exactly one number must be assigned to each vertex.
For example, your vertices might be assigned like this:
  3-----1
 /|    /|
4-----2 |
| |   | |
| 5---|-0
|/    |/
6-----7

Write a program that takes in an integer from 0 to 5. Each of these 6 numbers is associated with exactly one face of your cube in any way you like. When one of these numbers is input, the 4 vertex numbers of the associated face must be printed to stdout in a 2×2 square of digits. The face is to be viewed straight on from outside the cube. All 4 face rotations are valid.
For example, if 0 is associated with the front face of the example cube above, then this would be a valid output for input 0:
42
67

The face may be viewed at any 90° rotation, so these are also valid:
27
46
76
24
64
72
This output (and its rotations) are not valid, as they are viewed from the wrong side of the face:
24
76

The same idea applies to all other faces. e.g. if 1 is associated with the back face, then input 1 might produce output 13[newline]05 (and 31[newline]50 would be invalid).
So the real challenge is choosing your vertex numbers and rotations such that translating the input into its 4 vertex numbers is easy and short.
The shortest code in bytes wins. Tiebreaker is earlier post. (Handy byte counter.)
Notes

You may write a function instead of a program. It should take an integer from 0 to 5 and print or return the 2×2 digit grid string.
Take input from stdin, command line, or function arg. You may assume input is  valid.
The output may optionally have a trailing newline.
Be sure to tell us the vertex and face numbers you chose.
CJam, 23 16 bytes

There's probably an elegant mathematical solution to this problem. But I have no clue how to find one, so super compressed hard coding it is!

I found one! Well, it's not a classically elegant mathematical solution as it uses bitwise operations, but it is entirely formulaic.

li_o1^_p_6|o3+6%


Try it online.

Cube layout

  4-----7          4-----7          3-----2
 /|    /|         /  0  /|         /  3  /|
1-----0 |        1-----0 |        6-----5 |
| |   | |        |     |2|        |     |4|
| 5---|-2        |  1  | 2        |  5  | 7
|/    |/         |     |/         |     |/ 
6-----3          6-----3          1-----4  


Explanation

My old answer already laid out the cube such that each face can be described with its first (top-left) vertex number equal to the face number. But I wanted to be able to calculate more vertex numbers using the face number. At some point, I came up with the idea that got my foot in the door, to calculate the second (top-left) vertex number as the face number XOR 1. And after a while of trial and error, I managed to come up with the layout shown above and the formulas below that allow me to to calculate every vertex number for a face n quite succinctly:


Top-left: n
Top-right: n^1
Bottom-left: (n^1)|6
Bottom-right: ((n^1)+3)%6


For reference, I'll reproduce the output for each face in the desired layout here:

Face:      0     1     2     3     4     5

Vertices:  01    10    23    32    45    54
           74    63    70    65    72    61


So the whole program just comes down to reading the input face number and producing these values in order, albeit with slightly different printing logic for different vertices. Note that, because every vertex after the first starts with a base of n^1, I only need to calculate that once, which compacts the logic even further.



For posterity's sake, and because I think it was still a pretty good approach, here's my old answer.

CJam, 23 bytes

There's probably an elegant mathematical solution to this problem. But I have no clue how to find one, so super compressed hard coding it is!

"pÜ×ñè¨"487b8b3/ri_o=~p


Try it online.

Cube layout

  0-----7          0-----7          3-----6
 /|    /|         /  0  /|         /  3  /|
1-----2 |        1-----2 |        4-----5 |
| |   | |        |     |2|        |     |5|
| 5---|-6        |  1  | 6        |  4  | 7
|/    |/         |     |/         |     |/ 
4-----3          4-----3          1-----0  


Explanation

The basic approach employed is to hard code the vertices for each face in as little space as possible. Similarly to Optimizer's base conversion solution, this treats the vertex list as an octal number packed as ASCII character data. But that's about where the similarities end to make way for further optimizations!

Here are the three key optimizations I made to the "naive" solution:


Lay out the cube such that each face can be described with its face number as the first vertex number. Looking at my cube layout as presented above, one can see that the top-left vertex number of each face is equal to the face number. This allows me to encode six fewer vertices at the cost of having to print the input back, which turns out to save a byte.
Pack the vertex data into a string for which each "character" has a maximum larger than 256. As this maximum increases past 256, the length of the string slowly decreases, but it becomes increasingly likely that any one "character" exceeds 256 and is thus no longer part of the 1-byte ASCII character set. So I wrote a program that tries encoding the vertex data in every base from 256 to 1000, with which I found about 10 bases that save one byte of character data compared to base 256. I chose 487, as that also has the nice property that the resulting string consists entirely of printable ASCII.
Mixed with the first optimization, produce the output asymetrically. The usual approach in CJam would be to format the vertex data as a 2-element list of 2-element lists, insert a newline in the middle, and let the output be implicitly printed. But I instead print the first vertex (equal to the input face number) with an operator that doesn't add a newline, retrieve the 3-element list of the other vertices, grab the next vertex and print it with an operator that does add a newline, and let the other two vertices be implicitly printed. This saves a byte.