Saturday, October 9, 2021

Rubik's Cube Instructions in JavaScript


Can Rubik's Cubes fit in Computer Science or Math? 

I say YES! Read on to find out why.

This past summer, I learned how to solve several versions of the Rubik's Cube. It is almost always advisable to start with the standard 3x3 cube. Most of the other versions (4x4, 5x5, Windmill, Mirror, etc.) are based on moves in the basic 3x3 instructions.


So I started with the 3x3. As I watched YouTube videos and wrote detailed instructions to prepare myself to teach this to my High School students, I couldn't help but think in terms of: 

  • Loops
  • Functions
  • Functions within Functions
  • Conditionals, and
  • APIs

Function / API:

In the above video and steps, you'll see a very frequently used set of moves, which this video calls 
"Right Hand":
JavaScript shown in block style
    1. Turn the right side clockwise
    2. Turn the top layer clockwise
    3. Turn the right side counter-clockwise
    4. Turn the top layer counter-clockwise 
The exact opposite, slightly less frequently used, set of moves, is called 
"Left Hand":
    1. Turn the left side counter-clockwise
    2. Turn the top layer counter-clockwise
    3. Turn the left side clockwise
    4. Turn the top layer clockwise


In the rest of the video/instructions,  "Right Hand" and "Left Hand" are referred to over and over without having to list the 4 steps that make them up every time.

From a Computer Science perspective, we have just added a Function to the API.

API:

Before this, a "cube-student" needs to learn the basic "commands", like:
R =  Turn the right side clockwise
R' = Turn the right side counter-clockwise
L = Turn the left side clockwise
L' = Turn the left side counter-clockwise
U and U' = The same pattern, with the top layer
F and F' = The same pattern, with the front face
D and D' = The same pattern, with the bottom layer
B and B' = The same pattern, with the back face

Conditionals:

As you go through the instructions, you'll get to a point where you need to do "Right Hand" UNTIL a certain condition is met (putting a corner that's on the top layer directly down to the bottom layer). 

Loops:

At a later part of the instructions, you'll need to do "Right Hand" THREE TIMES, turn the entire cube, then "Left Hand" THREE TIMES.






When you get to the very last step/phase, you'll do 
"Right Hand" ONCE
"Left Hand" ONCE
"Right Hand" 5x
"Left Hand" 5x


I used Code.org's App Lap to write a JavaScript version of the instructions & video mentioned earlier.
  • I made some Functions.
  • I made some For Loops to repeat a set of steps.
  • I needed to include more Comments where I had to stick with human-readable instructions. These were primarily for parts that were more intuitive, as opposed to an algorithm.
  • Math: I assumed that something like the following would be sufficient to evaluate whether one side of a piece did NOT match the desired color:  ((BottomOfCornerPiece != Yellow))

Parts of the "block" version of the code are shown above.

Here is the complete JavaScript project, shown in Text version:


//Define Basic Moves
//Right is often refered to as R
function Right() {
  TurnRightSideCLOCKWISE
}
//RightInv is often refered to as R'
function RightInv() {
  TurnRightSideCOUNTERCLOCKWISE
}
//Left is often refered to as L
function Left() {
  TurnLeftSideCLOCKWISE
}
//LeftInv is often refered to as L'
function LeftInv() {
  TurnLeftSideCOUNTERCLOCKWISE
}
//Up is often refered to as U
function Up() {
  TurnTopLayerCLOCKWISE
}
//UpInv is often refered to as U'
function UpInv() {
  TurnTopLayerCOUNTERCLOCKWISE
}
//Front is often refered to as F
function Front() {
  TurnFrontFaceCLOCKWISE
}
// FrontInv is often refered to as F'
function FrontInv() {
  TurnFrontFaceCOUNTERCLOCKWISE
}

//Define "RightHand" and "LeftHand"
function RightHand() {
  Right();
  Up();
  RightInv();
  UpInv();
}
function LeftHand() {
  LeftInv();
  UpInv();
  Left();
  Up();
}

function Bottom2Layers() {
  TurnBottomTwoLayersEitherDirection
}
function TurnCubeLeft() {
  TurnEntireCubeToTheLeft
}
function TurnCubeRight() {
  TurnEntireCubeToTheRight
}
function OrientCube(color) {
  OrientCubeSoThisColorIsOnTop
}

//WHITE CROSS
//Make "Daisy"(yellow center w/ white edges); Then continue:
//This "for" loop repeats its contents 4x
for (var i = 0; i < 4; i++) {
if (FrontFaceTopEdge_matches_FrontFaceCenter) {
  Right();
  Right();
  RotateCubeLeft
} else {
  Bottom2Layers();
}
//Goal is to have all white edges' other color to match centers.
}


//WHITE CORNERS in place
OrientCube(yellow);
while (LessThanFourWhiteCornersInPlace) {
  RotateTop: CornerWithWhite=AboveFinalPlace
while (WhiteSquareNotInPlace) {
  RightHand();
}
//If a white square is on the bottom, but in the wrong place, 
//Do these steps to move it to the top, then
//Repeat these steps to put it where it goes.
}

//COMPLETE MIDDLE LAYER (EDGES)
while ((TopEdgePiecesWithYellow < 4)) {
  // Turn U so Top Edge piece WITHOUT yellow faces you 
  while ((TopEdgePiece != FrontFaceCenter)) {
    Bottom2Layers();
  }
  //Top Edge piece should now match front face's center
  if (TopEdgePieceTopColor == RightFaceCenter) {
    Up();
    RightHand();
    TurnCubeLeft();
    LeftHand();
  } else {
    //Top Edge Piece's top color should match LEFT face center
    UpInv();
    LeftHand();
    TurnCubeRight();
    RightHand();
  }
}

//Orient Cube so Yellow is on bottom
OrientCube(white);

//YELLOW CROSS
while (NoYellowCrossYet) {
if (HorizontalYellowLine) {
  //Position yellows to the left and right
  //(NOT up and down)
  Front();
  RightHand();
  FrontInv();
} else if (NineOClockPattern) {
  //Position yellows in top and left
  Front();
  RightHand();
  FrontInv();
} else {
  //Only yellow center
  Front();
  RightHand();
  FrontInv();
}
}

//POSITION Yellow Corners
//These "for" loops repeats their contents 3x
OrientCube(yellow);
//Up until 2 adjacent corners are in proper position
//Put these 2 correct corners to the left
//These steps will swap the right two corners
for (var i = 0; i < 3; i++) {
  RightHand();
}
RotateCubeLeft();
for (var i = 0; i < 3; i++) {
  LeftHand();
}

//ORIENT Yellow Corners
OrientCube(white);
while ((NumberOfYellowCornersFacingDown < 4)) {
  while ((BottomOfCornerPiece != Yellow)) {
    //This should position the bottom-right piece so that
    //yellow is NOT on the bottom, but on one of the sides
    Bottom();
  }
  while ((BottomOfCornerPiece != Yellow)) {
    RightHand();
  }
}


//LAST STEP - position top edges
//This will rotate top edge pieces
while (CubeNotSolved) {
RightHand();
LeftHand();
//These "for" loops repeat their contents 5x
for (var i = 0; i < 5; i++) {
  RightHand();
}
for (var i = 0; i < 5; i++) {
  LeftHand();
}
}


Rubik's Cube Instructions in JavaScript

Can Rubik's Cubes fit in Computer Science or Math?  I say YES! Read on to find out why. This past summer, I learned how to solve several...