rubiks-cube-solver
Version:
Outputs a solution using the Fridrich Method for a given cube state.
269 lines (222 loc) • 8.62 kB
JavaScript
import { RubiksCube } from '../../../models/RubiksCube';
import { F2LCaseBaseSolver } from './F2LCaseBaseSolver';
import {
getFaceOfMove, getFaceFromDirection, getRotationFromTo, getMoveOfFace,
getDirectionFromFaces
} from '../../../utils';
const R = (moves) => RubiksCube.reverseMoves(moves);
/**
* Top level case 1:
* Both corner and edge are on the DOWN face.
*/
class Case1Solver extends F2LCaseBaseSolver {
/**
* 10 Cases:
* 1) Pair is matched.
* 2) Pair is separated.
*
* ---- Group 1: Corner's white color is on DOWN face ----
* 3) Corner and edge share a face and colors on that face are equal.
* 4) Corner and edge share a face and colors on that face are not equal.
* 5) Corner and edge do not share a face.
*
* ---- Group 2: Corner's "other" color matches edge's "primary" color ----
* 6) Corner shares a face with edge.
* 7) Corner does not share a face with edge.
*
* ---- Group 3: Corner's "other" color doesn't match edge's "primary" color ----
* 8) Edge shares a face with corner's cross color's face.
* 9) Edge shares a face with corner's other color's face.
* 10) Corner does not share a face with edge.
*
* TODO: refactor
*/
_getCaseNumber({ corner, edge }) {
if (this.isPairMatched({ corner, edge })) {
return 1;
}
if (this.isPairSeparated({ corner, edge })) {
return 2;
}
let sharedFace;
edge.faces().forEach(face => {
if (corner.faces().includes(face) && face !== 'down') {
sharedFace = face;
}
});
let otherColor = corner.colors().find(color => {
return color !== 'u' && color !== corner.getColorOfFace('down');
});
let primaryColor = edge.colors().find(c => edge.getFaceOfColor(c) !== 'down');
// Group 1
if (corner.getFaceOfColor('u') === 'down') {
if (sharedFace) {
if (corner.getColorOfFace(sharedFace) === edge.getColorOfFace(sharedFace)) {
return 3;
} else {
return 4;
}
} else {
return 5;
}
}
// Group 2
if (otherColor === primaryColor) {
if (sharedFace) {
return 6;
} else {
return 7;
}
}
// Group 3
if (sharedFace) {
if (sharedFace === corner.getFaceOfColor('u')) {
return 8;
} else {
return 9;
}
} else {
return 10;
}
}
_solveCase1({ corner, edge }) {
return this.solveMatchedPair({ corner, edge });
}
_solveCase2({ corner, edge }) {
return this.solveSeparatedPair({ corner, edge });
}
_solveCase3({ corner, edge }) {
// calculate which side the corner is on, the position, etc.
let currentFace = edge.faces().find(face => face !== 'down');
let targetFace = getFaceOfMove(edge.getColorOfFace('down'));
let prepFace = getFaceFromDirection(targetFace, 'back', { up: 'down' });
let otherFace = corner.getFaceOfColor(edge.getColorOfFace('down'));
let isLeft = getFaceFromDirection(currentFace, otherFace, { up: 'down' }) === 'left';
// the moves
let prep = getRotationFromTo('down', currentFace, prepFace);
let moveFace = getFaceOfMove(edge.getColorOfFace(currentFace));
let dir = isLeft ? 'D' : 'DPrime';
moveFace = isLeft ? moveFace : R(moveFace);
let solveMoves = `${prep} ${moveFace} ${moveFace} D D `;
solveMoves += `${moveFace} ${dir} ${R(moveFace)} ${dir} ${moveFace} ${moveFace}`;
this.move(solveMoves, { upperCase: true });
}
_solveCase4({ corner, edge }) {
// calculate which side the corner is on, the position, etc.
let currentFace = edge.faces().find(face => face !== 'down');
let targetFace = getFaceOfMove(edge.getColorOfFace(currentFace));
let otherFace = corner.faces().find(face => !edge.faces().includes(face));
let isLeft = getFaceFromDirection(otherFace, currentFace, { up: 'down' }) === 'left';
// the moves
let prep = getRotationFromTo('down', currentFace, targetFace);
let moveFace = getMoveOfFace(targetFace);
moveFace = isLeft ? R(moveFace) : moveFace;
this.move(`${prep} ${moveFace} D D ${R(moveFace)}`, { upperCase: true });
this.solveSeparatedPair({ corner, edge });
}
_solveCase5({ corner, edge }) {
let primary = edge.colors().find(color => edge.getFaceOfColor(color) !== 'down');
let secondary = edge.colors().find(color => edge.getFaceOfColor(color) === 'down');
let isLeft = getFaceFromDirection(
getFaceOfMove(primary),
getFaceOfMove(secondary),
{ up: 'down' }
) === 'right';
let edgeCurrent = edge.getFaceOfColor(primary);
let edgeTarget = getFaceOfMove(primary);
// do the prep move now. need to calculate things after this move is done
let edgePrep = getRotationFromTo('down', edgeCurrent, edgeTarget);
this.move(edgePrep, { upperCase: true });
// calculate corner stuff
let cornerCurrent = corner.getFaceOfColor(primary);
let cornerTarget = edgeTarget;
// the moves
let cornerPrep = getRotationFromTo('down', cornerCurrent, cornerTarget);
let open = isLeft ? R(edgeTarget) : edgeTarget;
this.move(`${open} ${cornerPrep} ${R(open)}`, { upperCase: true });
this.solveMatchedPair({ corner, edge });
}
_solveCase6({ corner, edge }) {
let primary = edge.colors().find(color => edge.getFaceOfColor(color) !== 'down');
let currentFace = edge.getFaceOfColor(primary);
let targetFace = getFaceOfMove(edge.getColorOfFace('down'));
let isLeft = getDirectionFromFaces(
currentFace,
corner.getFaceOfColor(primary),
{ up: 'down' }
) === 'left';
let prep = getRotationFromTo('down', currentFace, targetFace);
let moveFace = isLeft ? targetFace : R(targetFace);
let dir = isLeft ? 'DPrime' : 'D';
this.move(`${prep} ${moveFace} ${dir} ${R(moveFace)}`, { upperCase: true });
this.solveSeparatedPair({ corner, edge});
}
_solveCase7({ corner, edge }) {
let primary = edge.colors().find(c => edge.getFaceOfColor(c) !== 'down');
let cornerCurrent = corner.getFaceOfColor('u');
let cornerTarget = getFaceOfMove(primary);
let isLeft = getDirectionFromFaces(
corner.getFaceOfColor(primary),
corner.getFaceOfColor('u'),
{ up: 'down' }
) === 'left';
let cornerPrep = getRotationFromTo('down', cornerCurrent, cornerTarget);
this.move(cornerPrep, { upperCase: true });
let edgeCurrent = edge.getFaceOfColor(primary);
let edgeTarget = corner.getFaceOfColor(primary);
let open = isLeft ? corner.getFaceOfColor('u') : R(corner.getFaceOfColor('u'));
let edgeMatch = getRotationFromTo('down', edgeCurrent, edgeTarget);
this.move(`${open} ${edgeMatch} ${R(open)}`, { upperCase: true });
this.solveMatchedPair({ corner, edge });
}
_solveCase8({ corner, edge }) {
let primary = edge.colors().find(c => edge.getFaceOfColor(c) !== 'down');
let secondary = edge.colors().find(c => edge.getFaceOfColor(c) === 'down');
let currentFace = corner.getFaceOfColor(secondary);
let targetFace = getFaceOfMove(primary);
let isLeft = getDirectionFromFaces(
currentFace,
corner.getFaceOfColor('u'),
{ up: 'down' }
) === 'left';
let prep = getRotationFromTo('down', currentFace, targetFace);
let open = isLeft ? R(targetFace) : targetFace;
let dir = isLeft ? 'D' : 'DPrime';
this.move(`${prep} ${open} ${dir} ${R(open)}`, { upperCase: true });
this.solveSeparatedPair({ corner, edge });
}
_solveCase9({ corner, edge }) {
let otherColor = edge.colors().find(c => edge.getFaceOfColor(c) === 'down');
let currentFace = corner.getFaceOfColor('u');
let targetFace = getFaceOfMove(otherColor);
let isLeft = getDirectionFromFaces(
corner.getFaceOfColor(otherColor),
currentFace,
{ up: 'down' }
) === 'left';
let prep = getRotationFromTo('down', currentFace, targetFace);
let moveFace = isLeft ? targetFace : R(targetFace);
this.move(`${prep} ${moveFace} D D ${R(moveFace)}`, { upperCase: true });
this.solveSeparatedPair({ corner, edge });
}
_solveCase10({ corner, edge }) {
let primary = edge.colors().find(c => edge.getFaceOfColor(c) !== 'down');
let secondary = edge.colors().find(c => edge.getFaceOfColor(c) === 'down');
let cornerCurrent = corner.getFaceOfColor('u');
let cornerTarget = getFaceOfMove(secondary);
let isLeft = getDirectionFromFaces(
corner.getFaceOfColor(secondary),
corner.getFaceOfColor('u'),
{ up: 'down' }
) === 'left';
let cornerPrep = getRotationFromTo('down', cornerCurrent, cornerTarget);
this.move(cornerPrep, { upperCase: true });
let edgeCurrent = edge.getFaceOfColor(primary);
let edgeTarget = getFaceOfMove(primary);
let open = isLeft ? cornerTarget : R(cornerTarget);
let edgePrep = getRotationFromTo('down', edgeCurrent, edgeTarget);
this.move(`${open} ${edgePrep} ${R(open)}`, { upperCase: true });
this.solveSeparatedPair({ corner, edge });
}
}
export { Case1Solver };