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.