UNPKG

rubiks-cube-solver

Version:

Outputs a solution using the Fridrich Method for a given cube state.

145 lines (115 loc) 3.81 kB
import { RubiksCube } from '../../models/RubiksCube'; import { F2LBaseSolver } from './F2LBaseSolver'; import { Case1Solver } from './cases/case-1'; import { Case2Solver } from './cases/case-2'; import { Case3Solver } from './cases/case-3'; import { getDirectionFromFaces } from '../../utils'; const R = (moves) => RubiksCube.reverseMoves(moves); class F2LSolver extends F2LBaseSolver { constructor(...args) { super(...args); this.subCaseOptions = Object.assign(this.options, { _overrideAfterEach: true }); } solve() { this.partitions = []; let pairs = this.getAllPairs(); pairs.forEach(({ corner, edge }) => { let partition = this._solve({ corner, edge }); this.partitions.push(partition); }); return this.partitions; } isSolved() { let pairs = this.getAllPairs(); for (let pair of pairs) { if (!this.isPairSolved(pair)) { return false; } } return true; } getAllPairs() { let corners = this.cube.corners().filter(corner => { return corner.hasColor('u'); }); let edges = this.cube.edges().filter(edge => { return !edge.hasColor('u') && !edge.hasColor('d'); }); let pairs = []; for (let edge of edges) { let corner = corners.find(corner => { let colors = edge.colors(); return corner.hasColor(colors[0]) && corner.hasColor(colors[1]); }); pairs.push({ edge, corner }); } return pairs; } /** * 4 top level cases: (cross face is UP) * * 1) Corner and edge are both on the DOWN face. * 2) Corner is on the DOWN face and edge is not on DOWN face. * 3) Corner is on UP face and edge is on DOWN face. * 4) Corner is on UP face and edge is not on DOWN face. */ _getCaseNumber({ corner, edge }) { if (corner.faces().includes('down')) { if (edge.faces().includes('down')) { return 1; } if (!edge.faces().includes('down') && !edge.faces().includes('up')) { return 2; } } if (corner.faces().includes('up')) { if (edge.faces().includes('down')) { return 3; } if (!edge.faces().includes('down') && !edge.faces().includes('up')) { return 4; } } throw new Error('Could not find a top level F2L case'); } _solveCase1({ corner, edge }) { let solver = new Case1Solver(this.cube, this.subCaseOptions); let partition = solver.solve({ corner, edge }); this.totalMoves = partition.moves; this.partition.caseNumber = [this.partition.caseNumber, partition.caseNumber]; } _solveCase2({ corner, edge }) { let solver = new Case2Solver(this.cube, this.subCaseOptions); let partition = solver.solve({ corner, edge }); this.totalMoves = partition.moves; this.partition.caseNumber = [this.partition.caseNumber, partition.caseNumber]; } _solveCase3({ corner, edge }) { let solver = new Case3Solver(this.cube, this.subCaseOptions); let partition = solver.solve({ corner, edge }); this.totalMoves = partition.moves; this.partition.caseNumber = [this.partition.caseNumber, partition.caseNumber]; } _solveCase4({ corner, edge }) { if (this.isPairSolved({ corner, edge })) { return; } let solver; if (corner.faces().includes(edge.faces()[0]) && corner.faces().includes(edge.faces()[1])) { solver = new Case1Solver(this.cube, this.subCaseOptions); } else { solver = new Case2Solver(this.cube, this.subCaseOptions); } let faces = corner.faces().filter(face => face !== 'up'); let dir = getDirectionFromFaces(faces[0], faces[1], { up: 'down' }); let cornerRightFace = dir === 'right' ? faces[1] : faces[0]; this.move(`${cornerRightFace} D ${R(cornerRightFace)}`, { upperCase: true }); let partition = solver.solve({ corner, edge }); this.partition.caseNumber = [this.partition.caseNumber, partition.caseNumber]; this.totalMoves = [...this.totalMoves, ...partition.moves]; } } export { F2LSolver };