Esempio n. 1
0
        /**
         * Generate a random pyraminx position.
         * @param r         random int generator
         */

        public PyraminxSolverState RandomState(Random r)
        {
            var state = new PyraminxSolverState();

            do
            {
                state.EdgePerm = r.Next(NEdgePerm);
            } while (PrunPerm[state.EdgePerm] == -1); // incorrect permutation (bad parity)
            state.EdgeOrient   = r.Next(NEdgeOrient);
            state.CornerOrient = r.Next(NCornerOrient);
            state.Tips         = r.Next(NTips);
            return(state);
        }
Esempio n. 2
0
        private static string Solve(PyraminxSolverState state, int desiredLength, bool exactLength, bool inverse,
                                    bool includingTips)
        {
            var r             = new Random();
            var solution      = new int[MaxLength];
            var foundSolution = false;

            // If we count the tips in the desired length, we have to subtract the number of unsolved tips from the length of the main puzzle search.
            if (includingTips)
            {
                desiredLength -= state.UnsolvedTips();
            }
            var length = exactLength ? desiredLength : 0;

            while (length <= desiredLength)
            {
                if (Search(state.EdgePerm, state.EdgeOrient, state.CornerOrient, 0, length, 42, solution, r))
                {
                    foundSolution = true;
                    break;
                }
                length++;
            }

            if (!foundSolution)
            {
                return(null);
            }

            var scramble = new StringBuilder((MaxLength + 4) * 3);

            if (inverse)
            {
                for (var i = length - 1; i >= 0; i--)
                {
                    scramble.Append(" ").Append(InverseMoveToString[solution[i]]);
                }
            }
            else
            {
                for (var i = 0; i < length; i++)
                {
                    scramble.Append(" ").Append(MoveToString[solution[i]]);
                }
            }

            // Scramble the tips
            var arrayTips = new int[4];

            UnpackCornerOrient(state.Tips, arrayTips);
            for (var tip = 0; tip < 4; tip++)
            {
                var dir = arrayTips[tip];
                if (dir > 0)
                {
                    scramble.Append(" ")
                    .Append(inverse ? TipToString[tip * 2 + dir - 1] : InverseTipToString[tip * 2 + dir - 1]);
                }
            }

            return(scramble.ToString().Trim());
        }
Esempio n. 3
0
        /**
         * Return a generator of a given position in exactly length number of turns or not at all.
         * Returns either the solution or the generator (inverse solution)
         * @param state         state
         * @param length        length of the desired solution
         * @param includingTips do we want to include tips in the solution lenght ?
         * @return              a string representing the solution or the scramble of a random position
         */

        public string GenerateExactly(PyraminxSolverState state, int length, bool includingTips)
        {
            return(Solve(state, length, true, true, includingTips));
        }
Esempio n. 4
0
        /**
         * Solve a given position in less than or equal to length number of turns.
         * Returns either the solution or the generator (inverse solution)
         * @param state         state
         * @param length        length of the desired solution
         * @param includingTips do we want to include tips in the solution lenght ?
         * @return              a string representing the solution or the scramble of a random position
         */

        public string SolveIn(PyraminxSolverState state, int length, bool includingTips)
        {
            return(Solve(state, length, false, false, includingTips));
        }
Esempio n. 5
0
            public PyraminxSolverState ToPyraminxSolverState()
            {
                var state = new PyraminxSolverState();

                /** Each face color is assigned a value so that the sum of the color (minus 1) of each edge gives a unique integer.
                 * These edge values match the edge numbering in the PyraminxSolver class, making the following code simpler.
                 *                                    U
                 *              ____  ____  ____              ____  ____  ____
                 *             \    /\    /\    /     /\     \    /\    /\    /
                 *              \  /  \5 /  \  /     /  \     \  /  \5 /  \  /
                 *               \/____\/____\/     /____\     \/____\/____\/
                 *                \    /\    /     /\    /\     \    /\    /
                 *        face +2  \2 /  \1 /     /1 \  /3 \     \3 /  \4 / face +4
                 *                  \/____\/     /____\/____\     \/____\/
                 *                   \    /     /\    /\    /\     \    /
                 *                    \  /     /  \  /0 \  /  \     \  /
                 *                     \/     /____\/____\/____\     \/
                 *                                  face +0
                 *                        L    ____  ____  ____    R
                 *                            \    /\    /\    /
                 *                             \  /  \0 /  \  /
                 *                              \/____\/____\/
                 *                               \    /\    /
                 *                                \2 /  \4 /
                 *                         face +1 \/____\/
                 *                                  \    /
                 *                                   \  /
                 *                                    \/
                 *
                 *                                    B
                 */
                int[][] stickersToEdges =
                {
                    new[] { _image[0][5], _image[1][2] },
                    new[] { _image[0][8], _image[2][5] },
                    new[] { _image[1][8], _image[2][8] },
                    new[] { _image[0][2], _image[3][8] },
                    new[] { _image[1][5], _image[3][5] },
                    new[] { _image[2][2], _image[3][2] }
                };

                int[] colorToValue = { 0, 1, 2, 4 };

                var edges = new int[6];

                for (var i = 0; i < edges.Length; i++)
                {
                    edges[i] = colorToValue[stickersToEdges[i][0]] + colorToValue[stickersToEdges[i][1]] - 1;
                    // In the PyraminxSolver class, the primary facelet of each edge correspond to the lowest face number.
                    if (stickersToEdges[i][0] > stickersToEdges[i][1])
                    {
                        edges[i] += 8;
                    }
                }

                state.EdgePerm   = PyraminxSolver.PackEdgePerm(edges);
                state.EdgeOrient = PyraminxSolver.PackEdgeOrient(edges);

                int[][] stickersToCorners =
                {
                    new[] { _image[0][1], _image[2][4], _image[3][1] },
                    new[] { _image[0][7], _image[1][1], _image[2][7] },
                    new[] { _image[0][4], _image[3][7], _image[1][4] },
                    new[] { _image[1][7], _image[3][4], _image[2][1] }
                };

                /* The corners are supposed to be fixed, so we are also checking if they are in the right place.
                 * We can use the sum trick, but here, no need for transition table :) */

                var corners = new int[4];

                for (var i = 0; i < corners.Length; i++)
                {
                    //azzertEquals(stickersToCorners[i][0] + stickersToCorners[i][1] + stickersToCorners[i][2], correctSum[i]);
                    // The following code is not pretty, sorry...
                    if (stickersToCorners[i][0] < stickersToCorners[i][1] &&
                        stickersToCorners[i][0] < stickersToCorners[i][2])
                    {
                        corners[i] = 0;
                    }
                    if (stickersToCorners[i][1] < stickersToCorners[i][0] &&
                        stickersToCorners[i][1] < stickersToCorners[i][2])
                    {
                        corners[i] = 1;
                    }
                    if (stickersToCorners[i][2] < stickersToCorners[i][1] &&
                        stickersToCorners[i][2] < stickersToCorners[i][0])
                    {
                        corners[i] = 2;
                    }
                }

                state.CornerOrient = PyraminxSolver.PackCornerOrient(corners);

                /* For the tips, we use the same numbering */
                int[][] stickersToTips =
                {
                    new[] { _image[0][0], _image[2][3], _image[3][0] },
                    new[] { _image[0][6], _image[1][0], _image[2][6] },
                    new[] { _image[0][3], _image[3][6], _image[1][3] },
                    new[] { _image[1][6], _image[3][3], _image[2][0] }
                };

                var tips = new int[4];

                for (var i = 0; i < tips.Length; i++)
                {
                    //int[] stickers = stickersToTips[i];
                    // We can use the same color check as for the corners.
                    //azzertEquals(stickers[0] + stickers[1] + stickers[2], correctSum[i]);

                    // For the tips, we don't have to check colors against face, but against the attached corner.
                    var cornerPrimaryColor          = stickersToCorners[i][0];
                    var clockwiseTurnsToMatchCorner = 0;
                    while (stickersToTips[i][clockwiseTurnsToMatchCorner] != cornerPrimaryColor)
                    {
                        clockwiseTurnsToMatchCorner++;
                    }
                    tips[i] = clockwiseTurnsToMatchCorner;
                }

                state.Tips = PyraminxSolver.PackCornerOrient(tips); // Same function as for corners.

                return(state);
            }