Revision 94ce8e53
Added by Leszek Koltunski 10 months ago
| src/main/java/org/distorted/dialogs/RubikDialogSolverView.java | ||
|---|---|---|
| 9 | 9 |
|
| 10 | 10 |
package org.distorted.dialogs; |
| 11 | 11 |
|
| 12 |
import android.content.res.Resources; |
|
| 13 | 12 |
import android.util.TypedValue; |
| 14 | 13 |
import android.view.View; |
| 15 | 14 |
import android.widget.Button; |
| ... | ... | |
| 19 | 18 |
import org.distorted.main.R; |
| 20 | 19 |
import org.distorted.objectlib.helpers.OperatingSystemInterface; |
| 21 | 20 |
import org.distorted.objectlib.main.TwistyObject; |
| 22 |
import org.distorted.solvers.SolvingList; |
|
| 23 |
import org.distorted.solvers.SolvingThread; |
|
| 21 |
import org.distorted.objectlib.solvers.verifiers.SolverAbstract; |
|
| 22 |
import org.distorted.objectlib.solvers.verifiers.SolvingList; |
|
| 23 |
import org.distorted.solverui.ScreenList; |
|
| 24 |
import org.distorted.solverui.ScreenSolver; |
|
| 24 | 25 |
import org.distorted.solverui.SolverActivity; |
| 25 | 26 |
|
| 26 | 27 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| ... | ... | |
| 56 | 57 |
dialog.dismiss(); |
| 57 | 58 |
SolvingList list = SolvingList.getSolver(solverOrdinal); |
| 58 | 59 |
OperatingSystemInterface os = act.getInterface(); |
| 59 |
Resources res = act.getResources(); |
|
| 60 | 60 |
TwistyObject object = act.getObject(); |
| 61 |
SolvingThread solver = new SolvingThread( os,res,object,list ); |
|
| 62 |
solver.start(); |
|
| 61 |
SolverAbstract solver = list.create(os,object); |
|
| 62 |
ScreenSolver screen = (ScreenSolver)ScreenList.SVER.getScreenClass(); |
|
| 63 |
|
|
| 64 |
if( solver!=null ) |
|
| 65 |
{
|
|
| 66 |
int[] result = solver.validatePosition(object); |
|
| 67 |
if( result[0]>=0 ) solver.solve(screen,result); |
|
| 68 |
else screen.displayImpossibleDialog(result,solver.getFaceColors()); |
|
| 69 |
} |
|
| 70 |
else screen.displayErrorDialog(act.getString(R.string.solver_generic_not_implemented)); |
|
| 63 | 71 |
} |
| 64 | 72 |
}); |
| 65 | 73 |
|
| src/main/java/org/distorted/dialogs/RubikDialogSolvers.java | ||
|---|---|---|
| 23 | 23 |
import org.distorted.main.R; |
| 24 | 24 |
import org.distorted.objectlib.metadata.ListObjects; |
| 25 | 25 |
import org.distorted.solverui.SolverActivity; |
| 26 |
import org.distorted.solvers.SolvingList;
|
|
| 26 |
import org.distorted.objectlib.solvers.verifiers.SolvingList;
|
|
| 27 | 27 |
|
| 28 | 28 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 29 | 29 |
|
| src/main/java/org/distorted/objects/RubikObject.java | ||
|---|---|---|
| 27 | 27 |
import org.distorted.objectlib.metadata.ListObjects; |
| 28 | 28 |
import org.distorted.objectlib.metadata.Metadata; |
| 29 | 29 |
import org.distorted.objectlib.patterns.RubikPatternList; |
| 30 |
import org.distorted.solvers.SolvingList;
|
|
| 30 |
import org.distorted.objectlib.solvers.verifiers.SolvingList;
|
|
| 31 | 31 |
|
| 32 | 32 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
| 33 | 33 |
|
| src/main/java/org/distorted/solvers/SolverAlgorithmic.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2024 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Magic Cube. // |
|
| 5 |
// // |
|
| 6 |
// Magic Cube is proprietary software licensed under an EULA which you should have received // |
|
| 7 |
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html // |
|
| 8 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 9 |
|
|
| 10 |
package org.distorted.solvers; |
|
| 11 |
|
|
| 12 |
import android.content.res.Resources; |
|
| 13 |
|
|
| 14 |
import org.distorted.objectlib.algsolvers.SolutionListener; |
|
| 15 |
import org.distorted.objectlib.algsolvers.SolvedObject; |
|
| 16 |
import org.distorted.objectlib.algsolvers.implemented.PhasedSolver3x3Beginner; |
|
| 17 |
import org.distorted.objectlib.algsolvers.implemented.PhasedSolverAbstract; |
|
| 18 |
import org.distorted.objectlib.helpers.OperatingSystemInterface; |
|
| 19 |
import org.distorted.objectlib.main.TwistyObject; |
|
| 20 |
import org.distorted.solverui.ScreenList; |
|
| 21 |
import org.distorted.solverui.ScreenPhasedSolution; |
|
| 22 |
import org.distorted.solverui.ScreenSolver; |
|
| 23 |
|
|
| 24 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 25 |
|
|
| 26 |
public abstract class SolverAlgorithmic implements SolvingInterface, SolutionListener |
|
| 27 |
{
|
|
| 28 |
private final SolvedObject mSolvedObject; |
|
| 29 |
private final PhasedSolverAbstract mSolver; |
|
| 30 |
private final OperatingSystemInterface mOS; |
|
| 31 |
private final Resources mRes; |
|
| 32 |
private final TwistyObject mObject; |
|
| 33 |
private long mTime; |
|
| 34 |
private ScreenSolver mScreen; |
|
| 35 |
|
|
| 36 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 37 |
// PUBLIC API |
|
| 38 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 39 |
|
|
| 40 |
public SolverAlgorithmic(OperatingSystemInterface os, Resources res, TwistyObject object) |
|
| 41 |
{
|
|
| 42 |
mOS = os; |
|
| 43 |
mRes = res; |
|
| 44 |
mObject = object; |
|
| 45 |
mSolver = new PhasedSolver3x3Beginner(); |
|
| 46 |
mSolvedObject = mSolver.getObject(); |
|
| 47 |
} |
|
| 48 |
|
|
| 49 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 50 |
|
|
| 51 |
abstract int[] validatePosition(TwistyObject object); |
|
| 52 |
abstract String getError(Resources res); |
|
| 53 |
|
|
| 54 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 55 |
|
|
| 56 |
public void solve(ScreenSolver screen) |
|
| 57 |
{
|
|
| 58 |
mScreen = screen; |
|
| 59 |
int[] quats = validatePosition(mObject); |
|
| 60 |
|
|
| 61 |
if( quats!=null ) |
|
| 62 |
{
|
|
| 63 |
int numPhases = mSolver.getNumPhases(); |
|
| 64 |
String[] names = new String[numPhases]; |
|
| 65 |
for(int p=0; p<numPhases; p++) names[p] = mSolver.getPhaseName(p); |
|
| 66 |
ScreenPhasedSolution solScreen = (ScreenPhasedSolution) ScreenList.PHAS.getScreenClass(); |
|
| 67 |
solScreen.updateNames(names); |
|
| 68 |
mTime = System.currentTimeMillis(); |
|
| 69 |
mSolver.solution(this,quats); |
|
| 70 |
} |
|
| 71 |
else |
|
| 72 |
{
|
|
| 73 |
String error = getError(mRes); |
|
| 74 |
screen.displayImpossibleDialog(error); |
|
| 75 |
} |
|
| 76 |
} |
|
| 77 |
|
|
| 78 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 79 |
|
|
| 80 |
public void receiveSolution(int[] solution, int phaseNumber) |
|
| 81 |
{
|
|
| 82 |
if( solution==null ) |
|
| 83 |
{
|
|
| 84 |
String message = "Phase "+phaseNumber+": FAIL"; |
|
| 85 |
System.out.println(message); |
|
| 86 |
} |
|
| 87 |
else |
|
| 88 |
{
|
|
| 89 |
int numMoves = solution[0]; |
|
| 90 |
int[][] moves = new int[numMoves][]; |
|
| 91 |
int index = 0; |
|
| 92 |
|
|
| 93 |
for(int m=1; m<=numMoves; m++) |
|
| 94 |
moves[index++] = mSolvedObject.findMove(solution[m]); |
|
| 95 |
|
|
| 96 |
int[][] subphases = mSolver.getSubPhases(phaseNumber); |
|
| 97 |
mScreen.setSolved(moves,phaseNumber,subphases); |
|
| 98 |
} |
|
| 99 |
|
|
| 100 |
long time = System.currentTimeMillis(); |
|
| 101 |
long diff = time - mTime; |
|
| 102 |
mTime = time; |
|
| 103 |
|
|
| 104 |
System.out.println("Phase "+phaseNumber+" solved in "+diff+"ms. Moves: "+(solution==null ? 0:solution[0]));
|
|
| 105 |
} |
|
| 106 |
} |
|
| 107 |
|
|
| src/main/java/org/distorted/solvers/SolverAlgorithmicCUBE3.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2024 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Magic Cube. // |
|
| 5 |
// // |
|
| 6 |
// Magic Cube is proprietary software licensed under an EULA which you should have received // |
|
| 7 |
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html // |
|
| 8 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 9 |
|
|
| 10 |
package org.distorted.solvers; |
|
| 11 |
|
|
| 12 |
import android.content.res.Resources; |
|
| 13 |
|
|
| 14 |
import org.distorted.objectlib.helpers.OperatingSystemInterface; |
|
| 15 |
import org.distorted.objectlib.main.TwistyObject; |
|
| 16 |
import org.distorted.solverui.SolverActivity; |
|
| 17 |
|
|
| 18 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 19 |
|
|
| 20 |
public class SolverAlgorithmicCUBE3 extends SolverAlgorithmic |
|
| 21 |
{
|
|
| 22 |
public SolverAlgorithmicCUBE3(OperatingSystemInterface os, Resources res, TwistyObject object) |
|
| 23 |
{
|
|
| 24 |
super(os,res,object); |
|
| 25 |
} |
|
| 26 |
|
|
| 27 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 28 |
|
|
| 29 |
int[] validatePosition(TwistyObject object) |
|
| 30 |
{
|
|
| 31 |
int numCubits = object.getNumCubits(); |
|
| 32 |
int[] ret = new int[numCubits]; // mockup |
|
| 33 |
return ret; |
|
| 34 |
} |
|
| 35 |
|
|
| 36 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 37 |
|
|
| 38 |
String getError(Resources res) |
|
| 39 |
{
|
|
| 40 |
return null; |
|
| 41 |
} |
|
| 42 |
} |
|
| 43 |
|
|
| src/main/java/org/distorted/solvers/SolverKociembaCUBE3.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2023 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Magic Cube. // |
|
| 5 |
// // |
|
| 6 |
// Magic Cube is proprietary software licensed under an EULA which you should have received // |
|
| 7 |
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html // |
|
| 8 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 9 |
|
|
| 10 |
package org.distorted.solvers; |
|
| 11 |
|
|
| 12 |
import android.content.res.Resources; |
|
| 13 |
|
|
| 14 |
import org.distorted.main.R; |
|
| 15 |
import org.distorted.objectlib.helpers.OperatingSystemInterface; |
|
| 16 |
import org.distorted.solverui.ScreenSolver; |
|
| 17 |
import org.distorted.objectlib.main.TwistyObject; |
|
| 18 |
import org.distorted.objectlib.kociemba.SolverSearch; |
|
| 19 |
|
|
| 20 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 21 |
|
|
| 22 |
public class SolverKociembaCUBE3 implements SolvingInterface |
|
| 23 |
{
|
|
| 24 |
private final Resources mRes; |
|
| 25 |
private final OperatingSystemInterface mOS; |
|
| 26 |
private final TwistyObject mObject; |
|
| 27 |
private int mColorID; |
|
| 28 |
|
|
| 29 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 30 |
|
|
| 31 |
private int mapCubitToFace(int cubit, int face) |
|
| 32 |
{
|
|
| 33 |
if( cubit<8 ) |
|
| 34 |
{
|
|
| 35 |
switch(face) |
|
| 36 |
{
|
|
| 37 |
case 0: return 1; |
|
| 38 |
case 1: if( cubit==2 ) return 5; |
|
| 39 |
if( cubit==1 ) return 3; |
|
| 40 |
return 1; |
|
| 41 |
case 2: return cubit==7 ? 5 : 3; |
|
| 42 |
case 3: if( cubit==1 ) return 1; |
|
| 43 |
return cubit==4 ? 5 : 3; |
|
| 44 |
case 4: return cubit==7 ? 3 : 5; |
|
| 45 |
case 5: if( cubit==2 ) return 1; |
|
| 46 |
if( cubit==4 ) return 3; |
|
| 47 |
return 5; |
|
| 48 |
} |
|
| 49 |
} |
|
| 50 |
|
|
| 51 |
if( cubit>19 ) return 4; |
|
| 52 |
|
|
| 53 |
switch(face) |
|
| 54 |
{
|
|
| 55 |
case 0: return cubit==15 || cubit==18 ? 3 : 5; |
|
| 56 |
case 1: return cubit==13 || cubit==16 ? 3 : 5; |
|
| 57 |
case 2: return cubit==10 ? 5 : 3; |
|
| 58 |
case 3: return cubit== 8 ? 3 : 5; |
|
| 59 |
case 4: return cubit== 9 ? 3 : 5; |
|
| 60 |
case 5: return cubit== 8 ? 5 : 3; |
|
| 61 |
} |
|
| 62 |
|
|
| 63 |
return -1; |
|
| 64 |
} |
|
| 65 |
|
|
| 66 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 67 |
|
|
| 68 |
private int checkPosition(String position) |
|
| 69 |
{
|
|
| 70 |
int[] numColors = new int[6]; |
|
| 71 |
int len = position.length(); |
|
| 72 |
|
|
| 73 |
for(int i=0; i<len; i++) |
|
| 74 |
{
|
|
| 75 |
char ch = position.charAt(i); |
|
| 76 |
|
|
| 77 |
switch(ch) |
|
| 78 |
{
|
|
| 79 |
case 'R': numColors[0]++; break; |
|
| 80 |
case 'L': numColors[1]++; break; |
|
| 81 |
case 'U': numColors[2]++; break; |
|
| 82 |
case 'D': numColors[3]++; break; |
|
| 83 |
case 'F': numColors[4]++; break; |
|
| 84 |
case 'B': numColors[5]++; break; |
|
| 85 |
} |
|
| 86 |
} |
|
| 87 |
|
|
| 88 |
if( numColors[0]<9 ) { mColorID = R.string.color_yellow1; return numColors[0]; }
|
|
| 89 |
if( numColors[1]<9 ) { mColorID = R.string.color_white1 ; return numColors[1]; }
|
|
| 90 |
if( numColors[2]<9 ) { mColorID = R.string.color_blue1 ; return numColors[2]; }
|
|
| 91 |
if( numColors[3]<9 ) { mColorID = R.string.color_green1 ; return numColors[3]; }
|
|
| 92 |
if( numColors[4]<9 ) { mColorID = R.string.color_red1 ; return numColors[4]; }
|
|
| 93 |
if( numColors[5]<9 ) { mColorID = R.string.color_orange1; return numColors[5]; }
|
|
| 94 |
|
|
| 95 |
return -1; |
|
| 96 |
} |
|
| 97 |
|
|
| 98 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 99 |
// order: Up --> Right --> Front --> Down --> Left --> Back |
|
| 100 |
// (because the first implemented Solver - the two-phase Cube3 one - expects such order) |
|
| 101 |
// |
|
| 102 |
// Solved 3x3x3 Cube maps to "UUUUUUUUURRRRRRRRRFFFFFFFFFDDDDDDDDDLLLLLLLLLBBBBBBBBB" |
|
| 103 |
|
|
| 104 |
private String preparePosition() |
|
| 105 |
{
|
|
| 106 |
StringBuilder objectString = new StringBuilder(); |
|
| 107 |
|
|
| 108 |
final int R = 0; |
|
| 109 |
final int L = 1; |
|
| 110 |
final int U = 2; |
|
| 111 |
final int D = 3; |
|
| 112 |
final int F = 4; |
|
| 113 |
final int B = 5; |
|
| 114 |
|
|
| 115 |
// 'I' - interior, theoretically can happen |
|
| 116 |
final char[] FACE_NAMES = { 'R', 'L', 'U', 'D', 'F', 'B', 'I'};
|
|
| 117 |
|
|
| 118 |
final int[] U_INDEX = { 2,10, 6,17,22,19, 3,11, 7};
|
|
| 119 |
final int[] R_INDEX = { 7,19, 6,15,20,14, 5,18, 4};
|
|
| 120 |
final int[] F_INDEX = { 3,11, 7,13,24,15, 1, 9, 5};
|
|
| 121 |
final int[] D_INDEX = { 1, 9, 5,16,23,18, 0, 8, 4};
|
|
| 122 |
final int[] L_INDEX = { 2,17, 3,12,21,13, 0,16, 1};
|
|
| 123 |
final int[] B_INDEX = { 6,10, 2,14,25,12, 4, 8, 0};
|
|
| 124 |
|
|
| 125 |
for(int i=0; i<9; i++) |
|
| 126 |
{
|
|
| 127 |
int face = mapCubitToFace(U_INDEX[i],U); |
|
| 128 |
int color = mObject.getCubitFaceStickerIndex(U_INDEX[i], face); |
|
| 129 |
objectString.append(FACE_NAMES[color]); |
|
| 130 |
} |
|
| 131 |
for(int i=0; i<9; i++) |
|
| 132 |
{
|
|
| 133 |
int face = mapCubitToFace(R_INDEX[i],R); |
|
| 134 |
int color = mObject.getCubitFaceStickerIndex(R_INDEX[i], face); |
|
| 135 |
objectString.append(FACE_NAMES[color]); |
|
| 136 |
} |
|
| 137 |
for(int i=0; i<9; i++) |
|
| 138 |
{
|
|
| 139 |
int face = mapCubitToFace(F_INDEX[i],F); |
|
| 140 |
int color = mObject.getCubitFaceStickerIndex(F_INDEX[i], face); |
|
| 141 |
objectString.append(FACE_NAMES[color]); |
|
| 142 |
} |
|
| 143 |
for(int i=0; i<9; i++) |
|
| 144 |
{
|
|
| 145 |
int face = mapCubitToFace(D_INDEX[i],D); |
|
| 146 |
int color = mObject.getCubitFaceStickerIndex(D_INDEX[i], face); |
|
| 147 |
objectString.append(FACE_NAMES[color]); |
|
| 148 |
} |
|
| 149 |
for(int i=0; i<9; i++) |
|
| 150 |
{
|
|
| 151 |
int face = mapCubitToFace(L_INDEX[i],L); |
|
| 152 |
int color = mObject.getCubitFaceStickerIndex(L_INDEX[i], face); |
|
| 153 |
objectString.append(FACE_NAMES[color]); |
|
| 154 |
} |
|
| 155 |
for(int i=0; i<9; i++) |
|
| 156 |
{
|
|
| 157 |
int face = mapCubitToFace(B_INDEX[i],B); |
|
| 158 |
int color = mObject.getCubitFaceStickerIndex(B_INDEX[i], face); |
|
| 159 |
objectString.append(FACE_NAMES[color]); |
|
| 160 |
} |
|
| 161 |
|
|
| 162 |
return objectString.toString(); |
|
| 163 |
} |
|
| 164 |
|
|
| 165 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 166 |
// PUBLIC API |
|
| 167 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 168 |
|
|
| 169 |
public SolverKociembaCUBE3(OperatingSystemInterface os, Resources res, TwistyObject object) |
|
| 170 |
{
|
|
| 171 |
mRes = res; |
|
| 172 |
mOS = os; |
|
| 173 |
mObject= object; |
|
| 174 |
} |
|
| 175 |
|
|
| 176 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 177 |
|
|
| 178 |
public void solve(ScreenSolver solver) |
|
| 179 |
{
|
|
| 180 |
String result; |
|
| 181 |
|
|
| 182 |
SolverSearch.prepare(mOS); |
|
| 183 |
String objectPosition = preparePosition(); |
|
| 184 |
int check = checkPosition(objectPosition); |
|
| 185 |
|
|
| 186 |
if( check<0 ) |
|
| 187 |
{
|
|
| 188 |
result = SolverSearch.solution(objectPosition, 24, 20); |
|
| 189 |
|
|
| 190 |
if( result.contains("Error") )
|
|
| 191 |
{
|
|
| 192 |
switch( result.charAt(result.length()-1) ) |
|
| 193 |
{
|
|
| 194 |
case '1': result = mRes.getString(R.string.solver_cube3_error1); break; |
|
| 195 |
case '2': result = mRes.getString(R.string.solver_cube3_error2); break; |
|
| 196 |
case '3': result = mRes.getString(R.string.solver_generic_edge_twist); break; |
|
| 197 |
case '4': result = mRes.getString(R.string.solver_cube3_error4); break; |
|
| 198 |
case '5': result = mRes.getString(R.string.solver_generic_corner_twist); break; |
|
| 199 |
case '6': result = mRes.getString(R.string.solver_cube3_error6); break; |
|
| 200 |
case '7': result = mRes.getString(R.string.solver_cube3_error7); break; |
|
| 201 |
case '8': result = mRes.getString(R.string.solver_cube3_error8); break; |
|
| 202 |
case '9': result = mRes.getString(R.string.solver_cube3_error9); break; |
|
| 203 |
} |
|
| 204 |
|
|
| 205 |
solver.displayImpossibleDialog(result); |
|
| 206 |
} |
|
| 207 |
else |
|
| 208 |
{
|
|
| 209 |
solver.setSolved(result); |
|
| 210 |
} |
|
| 211 |
} |
|
| 212 |
else |
|
| 213 |
{
|
|
| 214 |
String color = mRes.getString(mColorID); |
|
| 215 |
result = mRes.getString(R.string.solver_cube3_error1,check,color); |
|
| 216 |
solver.displayImpossibleDialog(result); |
|
| 217 |
} |
|
| 218 |
} |
|
| 219 |
} |
|
| 220 |
|
|
| src/main/java/org/distorted/solvers/SolverTablebase.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2023 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Magic Cube. // |
|
| 5 |
// // |
|
| 6 |
// Magic Cube is proprietary software licensed under an EULA which you should have received // |
|
| 7 |
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html // |
|
| 8 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 9 |
|
|
| 10 |
package org.distorted.solvers; |
|
| 11 |
|
|
| 12 |
import android.content.res.Resources; |
|
| 13 |
|
|
| 14 |
import org.distorted.main.R; |
|
| 15 |
import org.distorted.objectlib.helpers.OperatingSystemInterface; |
|
| 16 |
import org.distorted.objectlib.main.TwistyObject; |
|
| 17 |
import org.distorted.objectlib.tablebases.ImplementedTablebasesList; |
|
| 18 |
import org.distorted.objectlib.tablebases.TablebasesAbstract; |
|
| 19 |
import org.distorted.solverui.ScreenSolver; |
|
| 20 |
|
|
| 21 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 22 |
|
|
| 23 |
public abstract class SolverTablebase implements SolvingInterface |
|
| 24 |
{
|
|
| 25 |
private static final int[][] colorsHex = |
|
| 26 |
{
|
|
| 27 |
{R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
|
|
| 28 |
{R.string.color_white1 ,R.string.color_white2 ,R.string.color_white3 ,R.string.color_white4 ,R.string.color_white5 ,R.string.color_white6 ,R.string.color_white7 },
|
|
| 29 |
{R.string.color_blue1 ,R.string.color_blue2 ,R.string.color_blue3 ,R.string.color_blue4 ,R.string.color_blue5 ,R.string.color_blue6 ,R.string.color_blue7 },
|
|
| 30 |
{R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7 },
|
|
| 31 |
{R.string.color_red1 ,R.string.color_red2 ,R.string.color_red3 ,R.string.color_red4 ,R.string.color_red5 ,R.string.color_red6 ,R.string.color_red7 },
|
|
| 32 |
{R.string.color_orange1,R.string.color_orange2,R.string.color_orange3,R.string.color_orange4,R.string.color_orange5,R.string.color_orange6,R.string.color_orange7 },
|
|
| 33 |
}; |
|
| 34 |
private static final int[][] colorsTet = |
|
| 35 |
{
|
|
| 36 |
{R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7 },
|
|
| 37 |
{R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
|
|
| 38 |
{R.string.color_blue1 ,R.string.color_blue2 ,R.string.color_blue3 ,R.string.color_blue4 ,R.string.color_blue5 ,R.string.color_blue6 ,R.string.color_blue7 },
|
|
| 39 |
{R.string.color_red1 ,R.string.color_red2 ,R.string.color_red3 ,R.string.color_red4 ,R.string.color_red5 ,R.string.color_red6 ,R.string.color_red7 },
|
|
| 40 |
}; |
|
| 41 |
private static final int[][] colorsOct = |
|
| 42 |
{
|
|
| 43 |
{R.string.color_violet1,R.string.color_violet2,R.string.color_violet3,R.string.color_violet4,R.string.color_violet5,R.string.color_violet6,R.string.color_violet7 },
|
|
| 44 |
{R.string.color_grey1 ,R.string.color_grey2 ,R.string.color_grey3 ,R.string.color_grey4 ,R.string.color_grey5 ,R.string.color_grey6 ,R.string.color_grey7 },
|
|
| 45 |
{R.string.color_blue1 ,R.string.color_blue2 ,R.string.color_blue3 ,R.string.color_blue4 ,R.string.color_blue5 ,R.string.color_blue6 ,R.string.color_blue7 },
|
|
| 46 |
{R.string.color_red1 ,R.string.color_red2 ,R.string.color_red3 ,R.string.color_red4 ,R.string.color_red5 ,R.string.color_red6 ,R.string.color_red7 },
|
|
| 47 |
{R.string.color_orange1,R.string.color_orange2,R.string.color_orange3,R.string.color_orange4,R.string.color_orange5,R.string.color_orange6,R.string.color_orange7 },
|
|
| 48 |
{R.string.color_green1 ,R.string.color_green2 ,R.string.color_green3 ,R.string.color_green4 ,R.string.color_green5 ,R.string.color_green6 ,R.string.color_green7 },
|
|
| 49 |
{R.string.color_white1 ,R.string.color_white2 ,R.string.color_white3 ,R.string.color_white4 ,R.string.color_white5 ,R.string.color_white6 ,R.string.color_white7 },
|
|
| 50 |
{R.string.color_yellow1,R.string.color_yellow2,R.string.color_yellow3,R.string.color_yellow4,R.string.color_yellow5,R.string.color_yellow6,R.string.color_yellow7 },
|
|
| 51 |
}; |
|
| 52 |
|
|
| 53 |
private final OperatingSystemInterface mOS; |
|
| 54 |
private final Resources mRes; |
|
| 55 |
private final TwistyObject mObject; |
|
| 56 |
private TablebasesAbstract mSolver; |
|
| 57 |
|
|
| 58 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 59 |
|
|
| 60 |
public abstract int tablebaseIndex(TwistyObject object); |
|
| 61 |
public abstract String error(int index, Resources res); |
|
| 62 |
|
|
| 63 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 64 |
// PUBLIC API |
|
| 65 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 66 |
|
|
| 67 |
public SolverTablebase(OperatingSystemInterface os, Resources res, TwistyObject object) |
|
| 68 |
{
|
|
| 69 |
mOS = os; |
|
| 70 |
mRes = res; |
|
| 71 |
mObject= object; |
|
| 72 |
} |
|
| 73 |
|
|
| 74 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 75 |
|
|
| 76 |
int getHexColor(int color,int variant) { return colorsHex[color][variant]; }
|
|
| 77 |
int getTetColor(int color,int variant) { return colorsTet[color][variant]; }
|
|
| 78 |
int getOctColor(int color,int variant) { return colorsOct[color][variant]; }
|
|
| 79 |
int[] getExtra() { return null; }
|
|
| 80 |
|
|
| 81 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 82 |
|
|
| 83 |
public void solve(ScreenSolver screen) |
|
| 84 |
{
|
|
| 85 |
int index = tablebaseIndex(mObject); |
|
| 86 |
|
|
| 87 |
if( index>=0 ) |
|
| 88 |
{
|
|
| 89 |
if( mSolver==null ) |
|
| 90 |
{
|
|
| 91 |
mSolver = ImplementedTablebasesList.createPacked(mOS, mObject.getShortName() ); |
|
| 92 |
} |
|
| 93 |
|
|
| 94 |
mSolver.initialize(); |
|
| 95 |
int[][] moves = mSolver!=null ? mSolver.solution(index,getExtra(),mOS) : null; |
|
| 96 |
screen.setSolved(moves); |
|
| 97 |
} |
|
| 98 |
else |
|
| 99 |
{
|
|
| 100 |
String error = error(index,mRes); |
|
| 101 |
screen.displayImpossibleDialog(error); |
|
| 102 |
} |
|
| 103 |
} |
|
| 104 |
} |
|
| 105 |
|
|
| src/main/java/org/distorted/solvers/SolverTablebaseCU232.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2023 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Magic Cube. // |
|
| 5 |
// // |
|
| 6 |
// Magic Cube is proprietary software licensed under an EULA which you should have received // |
|
| 7 |
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html // |
|
| 8 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 9 |
|
|
| 10 |
package org.distorted.solvers; |
|
| 11 |
|
|
| 12 |
import android.content.res.Resources; |
|
| 13 |
|
|
| 14 |
import org.distorted.main.R; |
|
| 15 |
import org.distorted.objectlib.helpers.OperatingSystemInterface; |
|
| 16 |
import org.distorted.objectlib.main.TwistyObject; |
|
| 17 |
import org.distorted.objectlib.tablebases.TablebaseHelpers; |
|
| 18 |
|
|
| 19 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 20 |
|
|
| 21 |
public class SolverTablebaseCU232 extends SolverTablebase |
|
| 22 |
{
|
|
| 23 |
private static final int ERROR_CORNER_MISSING = -1; |
|
| 24 |
private static final int ERROR_EDGE_MISSING = -2; |
|
| 25 |
private static final int ERROR_CORNERS_CANNOT = -3; |
|
| 26 |
private static final int ERROR_EDGE_TWISTED = -4; |
|
| 27 |
private static final int ERROR_CORNER_TWISTED = -5; |
|
| 28 |
|
|
| 29 |
private final int[] mFaceColors; |
|
| 30 |
private int mErrColor1, mErrColor2, mErrColor3; |
|
| 31 |
|
|
| 32 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 33 |
|
|
| 34 |
private int edgeIs(int[] edge, int i0, int i1) |
|
| 35 |
{
|
|
| 36 |
int c0 = mFaceColors[i0]; |
|
| 37 |
int c1 = mFaceColors[i1]; |
|
| 38 |
|
|
| 39 |
if( edge[0]==c0 && edge[1]==c1 ) return 0; |
|
| 40 |
if( edge[0]==c1 && edge[1]==c0 ) return 1; |
|
| 41 |
return 2; |
|
| 42 |
} |
|
| 43 |
|
|
| 44 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 45 |
|
|
| 46 |
private int retEdgePermutation(int[] output, int[][] edges) |
|
| 47 |
{
|
|
| 48 |
for(int i=0; i<4; i++) output[i] = -1; |
|
| 49 |
|
|
| 50 |
for(int i=0; i<4; i++) |
|
| 51 |
{
|
|
| 52 |
int edge0 = edgeIs(edges[i],1,5); |
|
| 53 |
if( edge0==0 ) output[0]=i; |
|
| 54 |
else if( edge0==1 ) return ERROR_EDGE_TWISTED; |
|
| 55 |
|
|
| 56 |
int edge1 = edgeIs(edges[i],1,4); |
|
| 57 |
if( edge1==0 ) output[1]=i; |
|
| 58 |
else if( edge1==1 ) return ERROR_EDGE_TWISTED; |
|
| 59 |
|
|
| 60 |
int edge2 = edgeIs(edges[i],0,5); |
|
| 61 |
if( edge2==0 ) output[2]=i; |
|
| 62 |
else if( edge2==1 ) return ERROR_EDGE_TWISTED; |
|
| 63 |
|
|
| 64 |
int edge3 = edgeIs(edges[i],0,4); |
|
| 65 |
if( edge3==0 ) output[3]=i; |
|
| 66 |
else if( edge3==1 ) return ERROR_EDGE_TWISTED; |
|
| 67 |
} |
|
| 68 |
|
|
| 69 |
if( output[0]==-1 ) { mErrColor1=1; mErrColor2=5; return ERROR_EDGE_MISSING; }
|
|
| 70 |
if( output[1]==-1 ) { mErrColor1=1; mErrColor2=4; return ERROR_EDGE_MISSING; }
|
|
| 71 |
if( output[2]==-1 ) { mErrColor1=0; mErrColor2=5; return ERROR_EDGE_MISSING; }
|
|
| 72 |
if( output[3]==-1 ) { mErrColor1=0; mErrColor2=4; return ERROR_EDGE_MISSING; }
|
|
| 73 |
|
|
| 74 |
return 0; |
|
| 75 |
} |
|
| 76 |
|
|
| 77 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 78 |
|
|
| 79 |
private int cornerIs(int[] corner, int i0, int i1, int i2) |
|
| 80 |
{
|
|
| 81 |
int c0 = mFaceColors[i0]; |
|
| 82 |
int c1 = mFaceColors[i1]; |
|
| 83 |
int c2 = mFaceColors[i2]; |
|
| 84 |
|
|
| 85 |
if( corner[0]==c0 && corner[1]==c1 && corner[2]==c2 ) return 0; |
|
| 86 |
|
|
| 87 |
if( corner[0]==c0 && corner[1]==c2 && corner[2]==c1 || |
|
| 88 |
corner[0]==c1 && corner[1]==c0 && corner[2]==c2 || |
|
| 89 |
corner[0]==c1 && corner[1]==c2 && corner[2]==c0 || |
|
| 90 |
corner[0]==c2 && corner[1]==c0 && corner[2]==c1 || |
|
| 91 |
corner[0]==c2 && corner[1]==c1 && corner[2]==c0 ) return 1; |
|
| 92 |
|
|
| 93 |
return 2; |
|
| 94 |
} |
|
| 95 |
|
|
| 96 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 97 |
|
|
| 98 |
private int retCornerPermutation(int[] output, int[][] corners) |
|
| 99 |
{
|
|
| 100 |
for(int i=0; i<8; i++) output[i] = -1; |
|
| 101 |
|
|
| 102 |
for(int i=0; i<8; i++) |
|
| 103 |
{
|
|
| 104 |
int corner7 = cornerIs(corners[i],2,4,0); |
|
| 105 |
if( corner7==0 ) output[7]=i; |
|
| 106 |
else if( corner7==1 ) return ERROR_CORNER_TWISTED; |
|
| 107 |
|
|
| 108 |
int corner6 = cornerIs(corners[i],2,0,5); |
|
| 109 |
if( corner6==0 ) output[6]=i; |
|
| 110 |
else if( corner6==1 ) return ERROR_CORNER_TWISTED; |
|
| 111 |
|
|
| 112 |
int corner5 = cornerIs(corners[i],3,0,4); |
|
| 113 |
if( corner5==0 ) output[5]=i; |
|
| 114 |
else if( corner5==1 ) return ERROR_CORNER_TWISTED; |
|
| 115 |
|
|
| 116 |
int corner4 = cornerIs(corners[i],3,5,0); |
|
| 117 |
if( corner4==0 ) output[4]=i; |
|
| 118 |
else if( corner4==1 ) return ERROR_CORNER_TWISTED; |
|
| 119 |
|
|
| 120 |
int corner3 = cornerIs(corners[i],2,1,4); |
|
| 121 |
if( corner3==0 ) output[3]=i; |
|
| 122 |
else if( corner3==1 ) return ERROR_CORNER_TWISTED; |
|
| 123 |
|
|
| 124 |
int corner2 = cornerIs(corners[i],2,5,1); |
|
| 125 |
if( corner2==0 ) output[2]=i; |
|
| 126 |
else if( corner2==1 ) return ERROR_CORNER_TWISTED; |
|
| 127 |
|
|
| 128 |
int corner1 = cornerIs(corners[i],3,4,1); |
|
| 129 |
if( corner1==0 ) output[1]=i; |
|
| 130 |
else if( corner1==1 ) return ERROR_CORNER_TWISTED; |
|
| 131 |
|
|
| 132 |
int corner0 = cornerIs(corners[i],3,1,5); |
|
| 133 |
if( corner0==0 ) output[0]=i; |
|
| 134 |
else if( corner0==1 ) return ERROR_CORNER_TWISTED; |
|
| 135 |
} |
|
| 136 |
|
|
| 137 |
if( output[0]==-1 ) { mErrColor1=1; mErrColor2=3; mErrColor3=5; return ERROR_CORNER_MISSING; }
|
|
| 138 |
if( output[1]==-1 ) { mErrColor1=1; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
|
|
| 139 |
if( output[2]==-1 ) { mErrColor1=1; mErrColor2=2; mErrColor3=5; return ERROR_CORNER_MISSING; }
|
|
| 140 |
if( output[3]==-1 ) { mErrColor1=1; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
|
|
| 141 |
if( output[4]==-1 ) { mErrColor1=0; mErrColor2=3; mErrColor3=5; return ERROR_CORNER_MISSING; }
|
|
| 142 |
if( output[5]==-1 ) { mErrColor1=0; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
|
|
| 143 |
if( output[6]==-1 ) { mErrColor1=0; mErrColor2=2; mErrColor3=5; return ERROR_CORNER_MISSING; }
|
|
| 144 |
if( output[7]==-1 ) { mErrColor1=0; mErrColor2=2; mErrColor3=4; return ERROR_CORNER_MISSING; }
|
|
| 145 |
|
|
| 146 |
return 0; |
|
| 147 |
} |
|
| 148 |
|
|
| 149 |
//////////////////////////////////////////////////////////////////////////////////////// |
|
| 150 |
|
|
| 151 |
private int computeFaceColors(int[][] corners, int[][] edges) |
|
| 152 |
{
|
|
| 153 |
mFaceColors[1] = edges[1][0]; |
|
| 154 |
mFaceColors[4] = edges[1][1]; |
|
| 155 |
|
|
| 156 |
if( edges[0][0]==mFaceColors[1] ) mFaceColors[5] = edges[0][1]; |
|
| 157 |
else if( edges[2][0]==mFaceColors[1] ) mFaceColors[5] = edges[2][1]; |
|
| 158 |
else if( edges[3][0]==mFaceColors[1] ) mFaceColors[5] = edges[3][1]; |
|
| 159 |
else return ERROR_EDGE_TWISTED; |
|
| 160 |
|
|
| 161 |
if( edges[0][1]==mFaceColors[4] ) mFaceColors[0] = edges[0][0]; |
|
| 162 |
else if( edges[2][1]==mFaceColors[4] ) mFaceColors[0] = edges[2][0]; |
|
| 163 |
else if( edges[3][1]==mFaceColors[4] ) mFaceColors[0] = edges[3][0]; |
|
| 164 |
else return ERROR_EDGE_TWISTED; |
|
| 165 |
|
|
| 166 |
boolean found2 = false; |
|
| 167 |
boolean found3 = false; |
|
| 168 |
|
|
| 169 |
for(int c=0; c<8; c++) |
|
| 170 |
{
|
|
| 171 |
if( !found3 && corners[c][1]==mFaceColors[4] && corners[c][2]==mFaceColors[1] ) |
|
| 172 |
{
|
|
| 173 |
found3=true; |
|
| 174 |
mFaceColors[3] = corners[c][0]; |
|
| 175 |
} |
|
| 176 |
if( !found2 && corners[c][1]==mFaceColors[1] && corners[c][2]==mFaceColors[4] ) |
|
| 177 |
{
|
|
| 178 |
found2=true; |
|
| 179 |
mFaceColors[2] = corners[c][0]; |
|
| 180 |
} |
|
| 181 |
} |
|
| 182 |
|
|
| 183 |
if( !found2 || !found3 ) return ERROR_CORNERS_CANNOT; |
|
| 184 |
|
|
| 185 |
for(int i=0; i<6; i++) |
|
| 186 |
for(int j=i+1; j<6; j++) |
|
| 187 |
if( mFaceColors[i]==mFaceColors[j] ) return ERROR_CORNERS_CANNOT; |
|
| 188 |
|
|
| 189 |
return 0; |
|
| 190 |
} |
|
| 191 |
|
|
| 192 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 193 |
|
|
| 194 |
private int[] correctEdgePerm(int[] perm) |
|
| 195 |
{
|
|
| 196 |
int[] ret = new int[3]; |
|
| 197 |
|
|
| 198 |
ret[0] = perm[0]; |
|
| 199 |
ret[1] = perm[2]; |
|
| 200 |
ret[2] = perm[3]; |
|
| 201 |
|
|
| 202 |
if( ret[0]>1 ) ret[0]--; |
|
| 203 |
if( ret[1]>1 ) ret[1]--; |
|
| 204 |
if( ret[2]>1 ) ret[2]--; |
|
| 205 |
|
|
| 206 |
return ret; |
|
| 207 |
} |
|
| 208 |
|
|
| 209 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 210 |
|
|
| 211 |
public SolverTablebaseCU232(OperatingSystemInterface os, Resources res, TwistyObject object) |
|
| 212 |
{
|
|
| 213 |
super(os,res,object); |
|
| 214 |
mFaceColors = new int[6]; |
|
| 215 |
} |
|
| 216 |
|
|
| 217 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 218 |
|
|
| 219 |
public int tablebaseIndex(TwistyObject object) |
|
| 220 |
{
|
|
| 221 |
int[][] corners= new int[8][3]; |
|
| 222 |
int[][] edges = new int[4][2]; |
|
| 223 |
|
|
| 224 |
corners[0][0] = object.getCubitFaceStickerIndex(0,3); |
|
| 225 |
corners[0][1] = object.getCubitFaceStickerIndex(0,1); |
|
| 226 |
corners[0][2] = object.getCubitFaceStickerIndex(0,5); |
|
| 227 |
|
|
| 228 |
corners[1][0] = object.getCubitFaceStickerIndex(1,1); |
|
| 229 |
corners[1][1] = object.getCubitFaceStickerIndex(1,5); |
|
| 230 |
corners[1][2] = object.getCubitFaceStickerIndex(1,3); |
|
| 231 |
|
|
| 232 |
corners[2][0] = object.getCubitFaceStickerIndex(2,3); |
|
| 233 |
corners[2][1] = object.getCubitFaceStickerIndex(2,1); |
|
| 234 |
corners[2][2] = object.getCubitFaceStickerIndex(2,5); |
|
| 235 |
|
|
| 236 |
corners[3][0] = object.getCubitFaceStickerIndex(3,3); |
|
| 237 |
corners[3][1] = object.getCubitFaceStickerIndex(3,1); |
|
| 238 |
corners[3][2] = object.getCubitFaceStickerIndex(3,5); |
|
| 239 |
|
|
| 240 |
corners[4][0] = object.getCubitFaceStickerIndex(4,5); |
|
| 241 |
corners[4][1] = object.getCubitFaceStickerIndex(4,3); |
|
| 242 |
corners[4][2] = object.getCubitFaceStickerIndex(4,1); |
|
| 243 |
|
|
| 244 |
corners[5][0] = object.getCubitFaceStickerIndex(5,3); |
|
| 245 |
corners[5][1] = object.getCubitFaceStickerIndex(5,1); |
|
| 246 |
corners[5][2] = object.getCubitFaceStickerIndex(5,5); |
|
| 247 |
|
|
| 248 |
corners[6][0] = object.getCubitFaceStickerIndex(6,3); |
|
| 249 |
corners[6][1] = object.getCubitFaceStickerIndex(6,1); |
|
| 250 |
corners[6][2] = object.getCubitFaceStickerIndex(6,5); |
|
| 251 |
|
|
| 252 |
corners[7][0] = object.getCubitFaceStickerIndex(7,5); |
|
| 253 |
corners[7][1] = object.getCubitFaceStickerIndex(7,3); |
|
| 254 |
corners[7][2] = object.getCubitFaceStickerIndex(7,1); |
|
| 255 |
|
|
| 256 |
edges[0][0] = object.getCubitFaceStickerIndex(8,5); |
|
| 257 |
edges[0][1] = object.getCubitFaceStickerIndex(8,3); |
|
| 258 |
edges[1][0] = object.getCubitFaceStickerIndex(9,3); |
|
| 259 |
edges[1][1] = object.getCubitFaceStickerIndex(9,5); |
|
| 260 |
edges[2][0] = object.getCubitFaceStickerIndex(10,5); |
|
| 261 |
edges[2][1] = object.getCubitFaceStickerIndex(10,3); |
|
| 262 |
edges[3][0] = object.getCubitFaceStickerIndex(11,3); |
|
| 263 |
edges[3][1] = object.getCubitFaceStickerIndex(11,5); |
|
| 264 |
|
|
| 265 |
int result0 = computeFaceColors(corners, edges); |
|
| 266 |
if( result0<0 ) return result0; |
|
| 267 |
|
|
| 268 |
int[] corner_perm = new int[8]; |
|
| 269 |
int result1 = retCornerPermutation(corner_perm,corners); |
|
| 270 |
if( result1<0 ) return result1; |
|
| 271 |
|
|
| 272 |
int[] edge_perm = new int[4]; |
|
| 273 |
int result2 = retEdgePermutation(edge_perm,edges); |
|
| 274 |
if( result2<0 ) return result2; |
|
| 275 |
|
|
| 276 |
int[] edge_perm2 = correctEdgePerm(edge_perm); // edge1 is fixed! |
|
| 277 |
|
|
| 278 |
int corner_perm_num = TablebaseHelpers.computePermutationNum(corner_perm); |
|
| 279 |
int edge_perm_num = TablebaseHelpers.computePermutationNum(edge_perm2); |
|
| 280 |
|
|
| 281 |
return edge_perm_num + 6*corner_perm_num; |
|
| 282 |
} |
|
| 283 |
|
|
| 284 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 285 |
|
|
| 286 |
private String edgeError(Resources res, int face0, int face1) |
|
| 287 |
{
|
|
| 288 |
int j0 = getHexColor(face0,3); |
|
| 289 |
int j1 = getHexColor(face1,6); |
|
| 290 |
|
|
| 291 |
String c0 = res.getString(j0); |
|
| 292 |
String c1 = res.getString(j1); |
|
| 293 |
|
|
| 294 |
return res.getString(R.string.solver_generic_missing_edge,c0,c1); |
|
| 295 |
} |
|
| 296 |
|
|
| 297 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 298 |
|
|
| 299 |
private String cornerError(Resources res, int face0, int face1, int face2) |
|
| 300 |
{
|
|
| 301 |
int j0 = getHexColor(face0,3); |
|
| 302 |
int j1 = getHexColor(face1,3); |
|
| 303 |
int j2 = getHexColor(face2,4); |
|
| 304 |
|
|
| 305 |
String c0 = res.getString(j0); |
|
| 306 |
String c1 = res.getString(j1); |
|
| 307 |
String c2 = res.getString(j2); |
|
| 308 |
|
|
| 309 |
return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2); |
|
| 310 |
} |
|
| 311 |
|
|
| 312 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 313 |
|
|
| 314 |
public String error(int index, Resources res) |
|
| 315 |
{
|
|
| 316 |
switch(index) |
|
| 317 |
{
|
|
| 318 |
case ERROR_CORNER_MISSING: return cornerError(res,mErrColor1,mErrColor2,mErrColor3); |
|
| 319 |
case ERROR_EDGE_MISSING : return edgeError(res,mErrColor1,mErrColor2); |
|
| 320 |
case ERROR_CORNERS_CANNOT: return res.getString(R.string.solver_generic_corners_cannot); |
|
| 321 |
case ERROR_EDGE_TWISTED : return res.getString(R.string.solver_generic_edge_twist); |
|
| 322 |
case ERROR_CORNER_TWISTED: return res.getString(R.string.solver_generic_corner_twist); |
|
| 323 |
} |
|
| 324 |
|
|
| 325 |
return null; |
|
| 326 |
} |
|
| 327 |
} |
|
| 328 |
|
|
| src/main/java/org/distorted/solvers/SolverTablebaseCU323.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2023 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Magic Cube. // |
|
| 5 |
// // |
|
| 6 |
// Magic Cube is proprietary software licensed under an EULA which you should have received // |
|
| 7 |
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html // |
|
| 8 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 9 |
|
|
| 10 |
package org.distorted.solvers; |
|
| 11 |
|
|
| 12 |
import android.content.res.Resources; |
|
| 13 |
|
|
| 14 |
import org.distorted.main.R; |
|
| 15 |
import org.distorted.objectlib.helpers.OperatingSystemInterface; |
|
| 16 |
import org.distorted.objectlib.main.TwistyObject; |
|
| 17 |
import org.distorted.objectlib.tablebases.TBCuboid323; |
|
| 18 |
import org.distorted.objectlib.tablebases.TablebaseHelpers; |
|
| 19 |
|
|
| 20 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 21 |
// a few cu_323 max (depth 18) indices: 1180633, 1180642, 1182044, 1190482, 128151851, 128190028 |
|
| 22 |
|
|
| 23 |
public class SolverTablebaseCU323 extends SolverTablebase |
|
| 24 |
{
|
|
| 25 |
private static final int ERROR_CORNER_MISSING = -1; |
|
| 26 |
private static final int ERROR_EDGE_MISSING = -2; |
|
| 27 |
private static final int ERROR_CORNERS_CANNOT = -3; |
|
| 28 |
private static final int ERROR_EDGE_TWISTED = -4; |
|
| 29 |
private static final int ERROR_CORNER_TWISTED = -5; |
|
| 30 |
|
|
| 31 |
private final int[] mFaceColors; |
|
| 32 |
private int mErrColor1, mErrColor2, mErrColor3; |
|
| 33 |
|
|
| 34 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 35 |
|
|
| 36 |
public SolverTablebaseCU323(OperatingSystemInterface os, Resources res, TwistyObject object) |
|
| 37 |
{
|
|
| 38 |
super(os,res,object); |
|
| 39 |
mFaceColors = new int[6]; |
|
| 40 |
} |
|
| 41 |
|
|
| 42 |
//////////////////////////////////////////////////////////////////////////////////////// |
|
| 43 |
|
|
| 44 |
private int findCorner(int[][] corners, int c1, int c2) |
|
| 45 |
{
|
|
| 46 |
for(int i=0; i<8; i++) |
|
| 47 |
{
|
|
| 48 |
int[] c = corners[i]; |
|
| 49 |
|
|
| 50 |
if( c[0]==c1 && c[1]==c2 ) return c[2]; |
|
| 51 |
if( c[1]==c1 && c[2]==c2 ) return c[0]; |
|
| 52 |
if( c[2]==c1 && c[0]==c2 ) return c[1]; |
|
| 53 |
} |
|
| 54 |
|
|
| 55 |
return ERROR_CORNERS_CANNOT; |
|
| 56 |
} |
|
| 57 |
|
|
| 58 |
//////////////////////////////////////////////////////////////////////////////////////// |
|
| 59 |
|
|
| 60 |
private int missingColor() |
|
| 61 |
{
|
|
| 62 |
boolean[] present = new boolean[6]; |
|
| 63 |
for(int i=0; i<5; i++) present[mFaceColors[i]] = true; |
|
| 64 |
|
|
| 65 |
int indexFalse = -1; |
|
| 66 |
|
|
| 67 |
for(int i=0; i<6; i++) |
|
| 68 |
if( !present[i] ) |
|
| 69 |
{
|
|
| 70 |
if( indexFalse<0 ) indexFalse=i; |
|
| 71 |
else return ERROR_CORNERS_CANNOT; |
|
| 72 |
} |
|
| 73 |
|
|
| 74 |
return indexFalse; |
|
| 75 |
} |
|
| 76 |
|
|
| 77 |
//////////////////////////////////////////////////////////////////////////////////////// |
|
| 78 |
|
|
| 79 |
private int edgePresent(int[][] edges, int f0, int f1) |
|
| 80 |
{
|
|
| 81 |
int c0 = mFaceColors[f0]; |
|
| 82 |
int c1 = mFaceColors[f1]; |
|
| 83 |
|
|
| 84 |
for(int i=0; i<8; i++ ) |
|
| 85 |
{
|
|
| 86 |
int[] edge = edges[i]; |
|
| 87 |
|
|
| 88 |
if( edge[0]==c0 && edge[1]==c1 ) return i; |
|
| 89 |
if( edge[0]==c1 && edge[1]==c0 ) |
|
| 90 |
{
|
|
| 91 |
mErrColor1 = c0; |
|
| 92 |
mErrColor2 = c1; |
|
| 93 |
return ERROR_EDGE_TWISTED; |
|
| 94 |
} |
|
| 95 |
} |
|
| 96 |
|
|
| 97 |
mErrColor1 = c0; |
|
| 98 |
mErrColor2 = c1; |
|
| 99 |
return ERROR_EDGE_MISSING; |
|
| 100 |
} |
|
| 101 |
|
|
| 102 |
//////////////////////////////////////////////////////////////////////////////////////// |
|
| 103 |
|
|
| 104 |
private int cornerPresent(int[][] corners, int f0, int f1, int f2) |
|
| 105 |
{
|
|
| 106 |
int c0 = mFaceColors[f0]; |
|
| 107 |
int c1 = mFaceColors[f1]; |
|
| 108 |
int c2 = mFaceColors[f2]; |
|
| 109 |
|
|
| 110 |
for(int i=0; i<8; i++) |
|
| 111 |
{
|
|
| 112 |
int[] corner = corners[i]; |
|
| 113 |
|
|
| 114 |
if( corner[0]==c0 && corner[1]==c1 && corner[2]==c2 ) return i; |
|
| 115 |
if( (corner[0]==c1 && corner[1]==c2 && corner[2]==c0 ) || |
|
| 116 |
(corner[0]==c2 && corner[1]==c0 && corner[2]==c1 ) ) |
|
| 117 |
{
|
|
| 118 |
mErrColor1 = c0; |
|
| 119 |
mErrColor2 = c1; |
|
| 120 |
mErrColor3 = c2; |
|
| 121 |
return ERROR_CORNER_TWISTED; |
|
| 122 |
} |
|
| 123 |
} |
|
| 124 |
|
|
| 125 |
mErrColor1 = c0; |
|
| 126 |
mErrColor2 = c1; |
|
| 127 |
mErrColor3 = c2; |
|
| 128 |
return ERROR_CORNER_MISSING; |
|
| 129 |
} |
|
| 130 |
|
|
| 131 |
//////////////////////////////////////////////////////////////////////////////////////// |
|
| 132 |
|
|
| 133 |
private int retEdgePermutation(int[] output, int[][] edges) |
|
| 134 |
{
|
|
| 135 |
int[][] e = { {5,3}, {4,3}, {5,2}, {4,2}, {1,3}, {1,2}, {0,3}, {0,2} };
|
|
| 136 |
|
|
| 137 |
for(int i=0; i<8; i++) |
|
| 138 |
{
|
|
| 139 |
int[] ee = e[i]; |
|
| 140 |
output[i] = edgePresent(edges,ee[0],ee[1]); |
|
| 141 |
if( output[i]<0 ) return output[i]; |
|
| 142 |
} |
|
| 143 |
|
|
| 144 |
return 0; |
|
| 145 |
} |
|
| 146 |
|
|
| 147 |
//////////////////////////////////////////////////////////////////////////////////////// |
|
| 148 |
|
|
| 149 |
private int retCornerPermutation(int[] output, int[][] corners) |
|
| 150 |
{
|
|
| 151 |
int[][] c = { {5,1,3}, {1,4,3}, {1,5,2}, {4,1,2}, {0,5,3}, {4,0,3}, {5,0,2}, {0,4,2} };
|
|
| 152 |
|
|
| 153 |
for(int i=0; i<8; i++) |
|
| 154 |
{
|
|
| 155 |
int[] cc = c[i]; |
|
| 156 |
output[i] = cornerPresent(corners,cc[0],cc[1],cc[2]); |
|
| 157 |
if( output[i]<0 ) return output[i]; |
|
| 158 |
} |
|
| 159 |
|
|
| 160 |
return 0; |
|
| 161 |
} |
|
| 162 |
|
|
| 163 |
//////////////////////////////////////////////////////////////////////////////////////// |
|
| 164 |
|
|
| 165 |
private int computeFaceColors(int[][] corners, int[][] edges, int[] centers) |
|
| 166 |
{
|
|
| 167 |
mFaceColors[4] = edges[1][0]; |
|
| 168 |
mFaceColors[3] = edges[1][1]; |
|
| 169 |
|
|
| 170 |
if( centers[0]!=mFaceColors[3] ) mFaceColors[2] = centers[0]; |
|
| 171 |
else if( centers[1]!=mFaceColors[3] ) mFaceColors[2] = centers[1]; |
|
| 172 |
else return ERROR_CORNERS_CANNOT; |
|
| 173 |
|
|
| 174 |
mFaceColors[0] = findCorner(corners,mFaceColors[4],mFaceColors[2]); |
|
| 175 |
if( mFaceColors[0]<0 ) return mFaceColors[0]; |
|
| 176 |
|
|
| 177 |
mFaceColors[1] = findCorner(corners,mFaceColors[2],mFaceColors[4]); |
|
| 178 |
if( mFaceColors[1]<0 ) return mFaceColors[1]; |
|
| 179 |
|
|
| 180 |
mFaceColors[5] = missingColor(); |
|
| 181 |
if( mFaceColors[5]<0 ) return mFaceColors[5]; |
|
| 182 |
|
|
| 183 |
return 0; |
|
| 184 |
} |
|
| 185 |
|
|
| 186 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 187 |
|
|
| 188 |
private void getCorners(TwistyObject object, int[][] corners) |
|
| 189 |
{
|
|
| 190 |
corners[0][0] = object.getCubitFaceStickerIndex(0,5); |
|
| 191 |
corners[0][1] = object.getCubitFaceStickerIndex(0,1); |
|
| 192 |
corners[0][2] = object.getCubitFaceStickerIndex(0,3); |
|
| 193 |
|
|
| 194 |
corners[1][0] = object.getCubitFaceStickerIndex(1,3); |
|
| 195 |
corners[1][1] = object.getCubitFaceStickerIndex(1,5); |
|
| 196 |
corners[1][2] = object.getCubitFaceStickerIndex(1,1); |
|
| 197 |
|
|
| 198 |
corners[2][0] = object.getCubitFaceStickerIndex(2,5); |
|
| 199 |
corners[2][1] = object.getCubitFaceStickerIndex(2,1); |
|
| 200 |
corners[2][2] = object.getCubitFaceStickerIndex(2,3); |
|
| 201 |
|
|
| 202 |
corners[3][0] = object.getCubitFaceStickerIndex(3,5); |
|
| 203 |
corners[3][1] = object.getCubitFaceStickerIndex(3,1); |
|
| 204 |
corners[3][2] = object.getCubitFaceStickerIndex(3,3); |
|
| 205 |
|
|
| 206 |
corners[4][0] = object.getCubitFaceStickerIndex(4,1); |
|
| 207 |
corners[4][1] = object.getCubitFaceStickerIndex(4,3); |
|
| 208 |
corners[4][2] = object.getCubitFaceStickerIndex(4,5); |
|
| 209 |
|
|
| 210 |
corners[5][0] = object.getCubitFaceStickerIndex(5,5); |
|
| 211 |
corners[5][1] = object.getCubitFaceStickerIndex(5,1); |
|
| 212 |
corners[5][2] = object.getCubitFaceStickerIndex(5,3); |
|
| 213 |
|
|
| 214 |
corners[6][0] = object.getCubitFaceStickerIndex(6,5); |
|
| 215 |
corners[6][1] = object.getCubitFaceStickerIndex(6,1); |
|
| 216 |
corners[6][2] = object.getCubitFaceStickerIndex(6,3); |
|
| 217 |
|
|
| 218 |
corners[7][0] = object.getCubitFaceStickerIndex(7,1); |
|
| 219 |
corners[7][1] = object.getCubitFaceStickerIndex(7,3); |
|
| 220 |
corners[7][2] = object.getCubitFaceStickerIndex(7,5); |
|
| 221 |
} |
|
| 222 |
|
|
| 223 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 224 |
|
|
| 225 |
private void getEdges(TwistyObject object, int[][] edges) |
|
| 226 |
{
|
|
| 227 |
edges[0][0] = object.getCubitFaceStickerIndex(8,5); |
|
| 228 |
edges[0][1] = object.getCubitFaceStickerIndex(8,3); |
|
| 229 |
edges[1][0] = object.getCubitFaceStickerIndex(9,3); |
|
| 230 |
edges[1][1] = object.getCubitFaceStickerIndex(9,5); |
|
| 231 |
edges[2][0] = object.getCubitFaceStickerIndex(10,3); |
|
| 232 |
edges[2][1] = object.getCubitFaceStickerIndex(10,5); |
|
| 233 |
edges[3][0] = object.getCubitFaceStickerIndex(11,5); |
|
| 234 |
edges[3][1] = object.getCubitFaceStickerIndex(11,3); |
|
| 235 |
edges[4][0] = object.getCubitFaceStickerIndex(12,3); |
|
| 236 |
edges[4][1] = object.getCubitFaceStickerIndex(12,5); |
|
| 237 |
edges[5][0] = object.getCubitFaceStickerIndex(13,5); |
|
| 238 |
edges[5][1] = object.getCubitFaceStickerIndex(13,3); |
|
| 239 |
edges[6][0] = object.getCubitFaceStickerIndex(14,3); |
|
| 240 |
edges[6][1] = object.getCubitFaceStickerIndex(14,5); |
|
| 241 |
edges[7][0] = object.getCubitFaceStickerIndex(15,5); |
|
| 242 |
edges[7][1] = object.getCubitFaceStickerIndex(15,3); |
|
| 243 |
} |
|
| 244 |
|
|
| 245 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 246 |
|
|
| 247 |
private void getCenters(TwistyObject object, int[] centers) |
|
| 248 |
{
|
|
| 249 |
centers[0] = object.getCubitFaceStickerIndex(16,4); |
|
| 250 |
centers[1] = object.getCubitFaceStickerIndex(17,4); |
|
| 251 |
} |
|
| 252 |
|
|
| 253 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 254 |
|
|
| 255 |
public int tablebaseIndex(TwistyObject object) |
|
| 256 |
{
|
|
| 257 |
int[][] corners= new int[8][3]; |
|
| 258 |
int[][] edges = new int[8][2]; |
|
| 259 |
int[] centers = new int[2]; |
|
| 260 |
|
|
| 261 |
getCorners(object,corners); |
|
| 262 |
getEdges(object,edges); |
|
| 263 |
getCenters(object,centers); |
|
| 264 |
|
|
| 265 |
//for(int i=0; i<8; i++) android.util.Log.e("D", "corner: "+i+" : "+corners[i][0]+" "+corners[i][1]+" "+corners[i][2]);
|
|
| 266 |
//for(int i=0; i<8; i++) android.util.Log.e("D", "edge: "+i+" : "+edges[i][0]+" "+edges[i][1]);
|
|
| 267 |
|
|
| 268 |
int result0 = computeFaceColors(corners, edges, centers); |
|
| 269 |
if( result0<0 ) return result0; |
|
| 270 |
|
|
| 271 |
int[] corner_perm = new int[8]; |
|
| 272 |
int result1 = retCornerPermutation(corner_perm,corners); |
|
| 273 |
if( result1<0 ) return result1; |
|
| 274 |
|
|
| 275 |
//android.util.Log.e("D", "upper: "+mUpper);
|
|
| 276 |
//for(int i=0; i<6; i++) android.util.Log.e("D", "face color: "+mFaceColors[i]);
|
|
| 277 |
|
|
| 278 |
int[] edge_perm8 = new int[8]; |
|
| 279 |
int result2 = retEdgePermutation(edge_perm8,edges); |
|
| 280 |
if( result2<0 ) return result2; |
|
| 281 |
|
|
| 282 |
int[] edge_perm7 = TBCuboid323.edgePermTo7(edge_perm8); |
|
| 283 |
/* |
|
| 284 |
TablebaseHelpers.displayTable(corner_perm, "CORNER PERM"); |
|
| 285 |
TablebaseHelpers.displayTable(edge_perm8, "EDGE PERM8"); |
|
| 286 |
TablebaseHelpers.displayTable(edge_perm7, "EDGE PERM7"); |
|
| 287 |
*/ |
|
| 288 |
int corner_perm_num = TablebaseHelpers.computePermutationNum(corner_perm); |
|
| 289 |
int edge_perm_num = TablebaseHelpers.computePermutationNum(edge_perm7); |
|
| 290 |
int centersInPlace = (centers[0]==mFaceColors[2]) ? 0 : 1; |
|
| 291 |
|
|
| 292 |
//android.util.Log.e("D", "corner_perm_num: "+corner_perm_num+" edge_perm_num: "+edge_perm_num+" inPlace: "+centersInPlace);
|
|
| 293 |
//android.util.Log.e("D", "index="+(corner_perm_num + 40320*( centersInPlace + 2*edge_perm_num)));
|
|
| 294 |
|
|
| 295 |
return corner_perm_num + 40320*( centersInPlace + 2*edge_perm_num); |
|
| 296 |
} |
|
| 297 |
|
|
| 298 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 299 |
|
|
| 300 |
private String edgeTwistedError(Resources res, int color0, int color1) |
|
| 301 |
{
|
|
| 302 |
int j0 = getHexColor(color0,3); |
|
| 303 |
int j1 = getHexColor(color1,6); |
|
| 304 |
|
|
| 305 |
String c0 = res.getString(j0); |
|
| 306 |
String c1 = res.getString(j1); |
|
| 307 |
|
|
| 308 |
return res.getString(R.string.solver_generic_twisted_edge,c0,c1); |
|
| 309 |
} |
|
| 310 |
|
|
| 311 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 312 |
|
|
| 313 |
private String cornerTwistedError(Resources res, int color0, int color1, int color2) |
|
| 314 |
{
|
|
| 315 |
int j0 = getHexColor(color0,3); |
|
| 316 |
int j1 = getHexColor(color1,3); |
|
| 317 |
int j2 = getHexColor(color2,5); |
|
| 318 |
|
|
| 319 |
String c0 = res.getString(j0); |
|
| 320 |
String c1 = res.getString(j1); |
|
| 321 |
String c2 = res.getString(j2); |
|
| 322 |
|
|
| 323 |
return res.getString(R.string.solver_generic_twisted_corner,c0,c1,c2); |
|
| 324 |
} |
|
| 325 |
|
|
| 326 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 327 |
|
|
| 328 |
private String edgeMissingError(Resources res, int color0, int color1) |
|
| 329 |
{
|
|
| 330 |
int j0 = getHexColor(color0,3); |
|
| 331 |
int j1 = getHexColor(color1,6); |
|
| 332 |
|
|
| 333 |
String c0 = res.getString(j0); |
|
| 334 |
String c1 = res.getString(j1); |
|
| 335 |
|
|
| 336 |
return res.getString(R.string.solver_generic_missing_edge,c0,c1); |
|
| 337 |
} |
|
| 338 |
|
|
| 339 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 340 |
|
|
| 341 |
private String cornerMissingError(Resources res, int color0, int color1, int color2) |
|
| 342 |
{
|
|
| 343 |
int j0 = getHexColor(color0,3); |
|
| 344 |
int j1 = getHexColor(color1,3); |
|
| 345 |
int j2 = getHexColor(color2,4); |
|
| 346 |
|
|
| 347 |
String c0 = res.getString(j0); |
|
| 348 |
String c1 = res.getString(j1); |
|
| 349 |
String c2 = res.getString(j2); |
|
| 350 |
|
|
| 351 |
return res.getString(R.string.solver_generic_missing_corner,c0,c1,c2); |
|
| 352 |
} |
|
| 353 |
|
|
| 354 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 355 |
|
|
| 356 |
public String error(int index, Resources res) |
|
| 357 |
{
|
|
| 358 |
switch(index) |
|
| 359 |
{
|
|
| 360 |
case ERROR_CORNER_MISSING : return cornerMissingError(res,mErrColor1,mErrColor2,mErrColor3); |
|
| 361 |
case ERROR_EDGE_MISSING : return edgeMissingError(res,mErrColor1,mErrColor2); |
|
| 362 |
case ERROR_CORNERS_CANNOT : return res.getString(R.string.solver_generic_corners_cannot); |
|
| 363 |
case ERROR_EDGE_TWISTED : return edgeTwistedError(res,mErrColor1,mErrColor2); |
|
| 364 |
case ERROR_CORNER_TWISTED : return cornerTwistedError(res,mErrColor1,mErrColor2,mErrColor3); |
|
| 365 |
} |
|
| 366 |
|
|
| 367 |
return null; |
|
| 368 |
} |
|
| 369 |
} |
|
| 370 |
|
|
| src/main/java/org/distorted/solvers/SolverTablebaseCUBE2.java | ||
|---|---|---|
| 1 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 2 |
// Copyright 2023 Leszek Koltunski // |
|
| 3 |
// // |
|
| 4 |
// This file is part of Magic Cube. // |
|
| 5 |
// // |
|
| 6 |
// Magic Cube is proprietary software licensed under an EULA which you should have received // |
|
| 7 |
// along with the code. If not, check https://distorted.org/magic/License-Magic-Cube.html // |
|
| 8 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 9 |
|
|
| 10 |
package org.distorted.solvers; |
|
| 11 |
|
|
| 12 |
import android.content.res.Resources; |
|
| 13 |
|
|
| 14 |
import org.distorted.main.R; |
|
| 15 |
import org.distorted.objectlib.helpers.OperatingSystemInterface; |
|
| 16 |
import org.distorted.objectlib.main.TwistyObject; |
|
| 17 |
import org.distorted.objectlib.tablebases.TablebaseHelpers; |
|
| 18 |
import org.distorted.objectlib.tablebases.TBCube2; |
|
| 19 |
|
|
| 20 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 21 |
|
|
| 22 |
public class SolverTablebaseCUBE2 extends SolverTablebase |
|
| 23 |
{
|
|
| 24 |
private static final int ERROR_CORNER_MISSING = -1; |
|
| 25 |
private static final int ERROR_CORNERS_CANNOT = -2; |
|
| 26 |
private static final int ERROR_CORNER_TWISTED = -3; |
|
| 27 |
|
|
| 28 |
private final int[] mFaceColors; |
|
| 29 |
private int mErrColor1, mErrColor2, mErrColor3; |
|
| 30 |
|
|
| 31 |
//////////////////////////////////////////////////////////////////////////////////////// |
|
| 32 |
|
|
| 33 |
private void fillCornerTwists(int[] output, int[][] corners, int[] perm) |
|
| 34 |
{
|
|
| 35 |
for(int i=0; i<8; i++) |
|
| 36 |
{
|
|
| 37 |
int[] c = corners[perm[i]]; |
|
| 38 |
|
|
| 39 |
if( c[0]==mFaceColors[0] || c[0]==mFaceColors[1] ) output[i] = 0; |
|
| 40 |
else if( c[1]==mFaceColors[0] || c[1]==mFaceColors[1] ) output[i] = 1; |
|
| 41 |
else output[i] = 2; |
|
| 42 |
} |
|
| 43 |
} |
|
| 44 |
|
|
| 45 |
//////////////////////////////////////////////////////////////////////////////////////// |
|
| 46 |
|
|
| 47 |
private int cornerIndex(int[][] corners, int i1, int i2, int i3) |
|
| 48 |
{
|
|
| 49 |
int c1 = mFaceColors[i1]; |
|
| 50 |
int c2 = mFaceColors[i2]; |
|
| 51 |
int c3 = mFaceColors[i3]; |
|
| 52 |
|
|
| 53 |
for(int i=0; i<8; i++) |
|
| 54 |
{
|
|
| 55 |
int[] cor = corners[i]; |
|
| 56 |
|
|
| 57 |
if( (cor[0]==c1 && cor[1]==c2 && cor[2]==c3) || |
|
| 58 |
(cor[0]==c2 && cor[1]==c3 && cor[2]==c1) || |
|
| 59 |
(cor[0]==c3 && cor[1]==c1 && cor[2]==c2) ) return i; |
|
| 60 |
} |
|
| 61 |
|
|
| 62 |
return -1; |
|
| 63 |
} |
|
| 64 |
|
|
| 65 |
//////////////////////////////////////////////////////////////////////////////////////// |
|
| 66 |
|
|
| 67 |
private int retCornerPermutation(int[] output, int[][] corners) |
|
| 68 |
{
|
|
| 69 |
for(int i=0; i<8; i++) output[i] = -1; |
|
| 70 |
|
|
| 71 |
output[0] = cornerIndex(corners, 1,2,5); |
|
| 72 |
output[1] = cornerIndex(corners, 1,4,2); |
|
| 73 |
output[2] = cornerIndex(corners, 1,5,3); |
|
| 74 |
output[3] = cornerIndex(corners, 1,3,4); |
|
| 75 |
output[4] = cornerIndex(corners, 0,5,2); |
|
| 76 |
output[5] = cornerIndex(corners, 0,2,4); |
|
| 77 |
output[6] = cornerIndex(corners, 0,3,5); |
|
| 78 |
output[7] = cornerIndex(corners, 0,4,3); |
|
| 79 |
|
|
| 80 |
if( output[0]==-1 ) { mErrColor1=1; mErrColor2=2; mErrColor3=5; return ERROR_CORNER_MISSING; }
|
|
| 81 |
if( output[1]==-1 ) { mErrColor1=1; mErrColor2=4; mErrColor3=2; return ERROR_CORNER_MISSING; }
|
|
| 82 |
if( output[2]==-1 ) { mErrColor1=1; mErrColor2=5; mErrColor3=3; return ERROR_CORNER_MISSING; }
|
|
| 83 |
if( output[3]==-1 ) { mErrColor1=1; mErrColor2=3; mErrColor3=4; return ERROR_CORNER_MISSING; }
|
|
| 84 |
if( output[4]==-1 ) { mErrColor1=0; mErrColor2=5; mErrColor3=2; return ERROR_CORNER_MISSING; }
|
|
| 85 |
if( output[5]==-1 ) { mErrColor1=0; mErrColor2=2; mErrColor3=4; return ERROR_CORNER_MISSING; }
|
|
| 86 |
if( output[6]==-1 ) { mErrColor1=0; mErrColor2=3; mErrColor3=5; return ERROR_CORNER_MISSING; }
|
|
| 87 |
if( output[7]==-1 ) { mErrColor1=0; mErrColor2=4; mErrColor3=3; return ERROR_CORNER_MISSING; }
|
|
| 88 |
|
|
| 89 |
return 0; |
|
| 90 |
} |
|
| 91 |
|
|
| 92 |
//////////////////////////////////////////////////////////////////////////////////////// |
|
| 93 |
|
|
| 94 |
private int findColor(int[][] corners, int c1, int c2) |
|
| 95 |
{
|
|
| 96 |
for(int i=0; i<8; i++) |
|
| 97 |
{
|
|
| 98 |
int[] cor = corners[i]; |
|
| 99 |
|
|
| 100 |
if( cor[0]==c1 && cor[1]==c2 ) return cor[2]; |
|
| 101 |
if( cor[1]==c1 && cor[2]==c2 ) return cor[0]; |
|
| 102 |
if( cor[2]==c1 && cor[0]==c2 ) return cor[1]; |
|
| 103 |
} |
|
| 104 |
|
|
| 105 |
return -1; |
|
| 106 |
} |
|
| 107 |
|
|
| 108 |
//////////////////////////////////////////////////////////////////////////////////////// |
|
| 109 |
|
|
| 110 |
private int computeFaceColors(int[][] corners) |
|
| 111 |
{
|
|
| 112 |
mFaceColors[1] = corners[1][0]; |
|
| 113 |
mFaceColors[2] = corners[1][2]; |
|
| 114 |
mFaceColors[4] = corners[1][1]; |
|
| 115 |
|
|
| 116 |
mFaceColors[0] = findColor(corners,mFaceColors[2],mFaceColors[4]); |
|
| 117 |
mFaceColors[3] = findColor(corners,mFaceColors[4],mFaceColors[1]); |
|
| 118 |
mFaceColors[5] = findColor(corners,mFaceColors[1],mFaceColors[2]); |
|
| 119 |
|
|
| 120 |
for(int i=0; i<6; i++) |
|
| 121 |
{
|
|
| 122 |
int color = mFaceColors[i]; |
|
| 123 |
if( color<0 ) return ERROR_CORNERS_CANNOT; |
|
| 124 |
|
|
| 125 |
for(int j=i+1; j<6; j++) |
|
| 126 |
if( mFaceColors[j]==color ) return ERROR_CORNERS_CANNOT; |
|
| 127 |
} |
|
| 128 |
|
|
| 129 |
return 0; |
|
| 130 |
} |
|
| 131 |
|
|
| 132 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 133 |
|
|
| 134 |
public SolverTablebaseCUBE2(OperatingSystemInterface os, Resources res, TwistyObject object) |
|
| 135 |
{
|
|
| 136 |
super(os,res,object); |
|
| 137 |
mFaceColors = new int[6]; |
|
| 138 |
} |
|
| 139 |
|
|
| 140 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 141 |
|
|
| 142 |
private void getCorners(TwistyObject object, int[][] corners) |
|
| 143 |
{
|
|
| 144 |
corners[0][0] = object.getCubitFaceStickerIndex(0,1); |
|
| 145 |
corners[0][1] = object.getCubitFaceStickerIndex(0,3); |
|
| 146 |
corners[0][2] = object.getCubitFaceStickerIndex(0,5); |
|
| 147 |
|
|
| 148 |
corners[1][0] = object.getCubitFaceStickerIndex(1,3); |
|
| 149 |
corners[1][1] = object.getCubitFaceStickerIndex(1,5); |
|
| 150 |
corners[1][2] = object.getCubitFaceStickerIndex(1,1); |
|
| 151 |
|
|
| 152 |
corners[2][0] = object.getCubitFaceStickerIndex(2,5); |
|
| 153 |
corners[2][1] = object.getCubitFaceStickerIndex(2,1); |
|
| 154 |
corners[2][2] = object.getCubitFaceStickerIndex(2,3); |
|
| 155 |
|
|
| 156 |
corners[3][0] = object.getCubitFaceStickerIndex(3,1); |
|
| 157 |
corners[3][1] = object.getCubitFaceStickerIndex(3,3); |
|
| 158 |
corners[3][2] = object.getCubitFaceStickerIndex(3,5); |
|
| 159 |
|
|
| 160 |
corners[4][0] = object.getCubitFaceStickerIndex(4,1); |
|
| 161 |
corners[4][1] = object.getCubitFaceStickerIndex(4,3); |
|
| 162 |
corners[4][2] = object.getCubitFaceStickerIndex(4,5); |
|
| 163 |
|
|
| 164 |
corners[5][0] = object.getCubitFaceStickerIndex(5,1); |
|
| 165 |
corners[5][1] = object.getCubitFaceStickerIndex(5,3); |
|
| 166 |
corners[5][2] = object.getCubitFaceStickerIndex(5,5); |
|
| 167 |
|
|
| 168 |
corners[6][0] = object.getCubitFaceStickerIndex(6,1); |
|
| 169 |
corners[6][1] = object.getCubitFaceStickerIndex(6,3); |
|
| 170 |
corners[6][2] = object.getCubitFaceStickerIndex(6,5); |
|
| 171 |
|
|
| 172 |
corners[7][0] = object.getCubitFaceStickerIndex(7,1); |
|
| 173 |
corners[7][1] = object.getCubitFaceStickerIndex(7,3); |
|
| 174 |
corners[7][2] = object.getCubitFaceStickerIndex(7,5); |
|
| 175 |
} |
|
| 176 |
|
|
| 177 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 178 |
|
|
| 179 |
public int tablebaseIndex(TwistyObject object) |
|
| 180 |
{
|
|
| 181 |
int[][] corners= new int[8][3]; |
|
| 182 |
getCorners(object,corners); |
|
| 183 |
|
|
| 184 |
int result0 = computeFaceColors(corners); |
|
| 185 |
if( result0<0 ) return result0; |
|
| 186 |
|
|
| 187 |
int[] perm = new int[8]; |
|
| 188 |
int result1 = retCornerPermutation(perm,corners); |
|
| 189 |
if( result1<0 ) return result1; |
|
| 190 |
|
|
| 191 |
int[] perm7 = TBCube2.shrinkPerm(perm); |
|
| 192 |
int permNum = TablebaseHelpers.computePermutationNum(perm7); |
|
| 193 |
int[] twist = new int[8]; |
|
| 194 |
fillCornerTwists(twist,corners,perm); |
|
| 195 |
|
|
| 196 |
int totalTwist = 0; |
|
| 197 |
for(int i=0; i<8; i++) totalTwist += twist[i]; |
|
| 198 |
if( ((totalTwist)%3) != 0 ) return ERROR_CORNER_TWISTED; |
|
| 199 |
|
|
| 200 |
int twistNum = twist[0] + 3*(twist[2] + 3*(twist[3] + 3*(twist[4] + 3*(twist[5] + 3*twist[6])))); |
|
| 201 |
|
|
| 202 |
return twistNum + 729*permNum; |
|
| 203 |
} |
|
| 204 |
|
|
| 205 |
/////////////////////////////////////////////////////////////////////////////////////////////////// |
|
| 206 |
|
|
| 207 |
private String cornerError(Resources res, int face0, int face1, int face2) |
|
| 208 |
{
|
|
Also available in: Unified diff
Properly define and separate the interface between the App and the 'solver' part of the objectlib. Move the 'position verifiers' to the objectlib.