Our first goal is to actually represent a Rubik's Cube in F# at all!

As mentioned previously, the Rubik's Cube is composed of 12 Edges and 8 Corners.

Each of these edges can be in one of 12 places, and each one of the corners can be in one of 8 places, naturally.

Further, each edge can be in one of two orientations (flipped, or not flipped). Finally, each corner can be in one of three orientations (flipped, twisted clockwise, twisted counter-clockwise)

Below, I will represent the idea of a Rubik's Cube in F#, and then explain a bit.

``````// Edges:   UF UR UB UL DF DR DB DL FR FL BR BL
// Corners: UFR URB UBL ULF DRF DFL DLB DBR

// Universal decision!
// A CubeState (or a transformation represented by said data structure)
//   should represent the state of the puzzle AFTER the operation has been complete
//   (as opposed to what it was BEFORE the operation)

type CubeState =
{ EdgePositions   : int array
EdgeFlips       : int array
CornerPositions : int array
CornerTwists    : int array }
``````

Each of these arrays hold small bits of information about the state of a Rubik's Cube.

A solved Rubik's Cube is essentially an identity of itself. Every cubie's pieces are correctly oriented (aren't twisted in place) and are correctly permutated (aren't in the wrong location on the cube).

As such, the edge at position 0 is at position 0, and we can declare a solved Rubik's Cube to be such:

``````let solvedCube : CubeState =
{ EdgePositions   = [| 0 .. 11 |];
EdgeFlips       = Array.create 12 0;
CornerPositions = [| 0 .. 7 |]
CornerTwists    = Array.create 8 0 }
``````

Throughout our process, we will be representing some basic moves on the Rubik's Cube with this very same data structure (a bunch of int arrays). We'll need to label these and encapsulate the transformation they should include, so we might as well declare a helper type in this file.

``````type CubeTransformation =
{ Label  : string list
Transformation : CubeState }
``````

Relevant Tests:

``````[<Fact>]
let ``Solved cube has 12 edges`` () =
solvedCube.EdgePositions.Length |> should equal 12
solvedCube.EdgeFlips.Length     |> should equal 12

[<Fact>]
let ``Solved cube has 8 corners`` () =
solvedCube.CornerPositions.Length |> should equal 8
solvedCube.CornerTwists.Length    |> should equal 8
``````