Example #1
0
            public CubeSolver()
            {
                // first piece will not be rotated
                this.KnownPermutations[0] = new KnownPiece[1] {
                    KNOWN_PIECES[0]
                };

                // create permutations (except for the first piece)
                for (int i = 1; i < KNOWN_PIECES.Length; i++)
                {
                    this.KnownPermutations[i] = GeneratePiecePermutations(KNOWN_PIECES[i]).ToArray();
                }

                // create all placements (ulong) for every permutation of every piece there is
                for (int pieceIndex = 0; pieceIndex < KNOWN_PIECES.Length; pieceIndex++)
                {
                    this.KnownPlacements[pieceIndex] = new Tuple <ulong, byte[, , ]> [this.KnownPermutations[pieceIndex].Length][];
                    for (int permutationIndex = 0; permutationIndex < this.KnownPermutations[pieceIndex].Length; permutationIndex++)
                    {
                        KnownPiece currentPermutation = this.KnownPermutations[pieceIndex][permutationIndex];
                        int        xSteps             = CUBE_X - currentPermutation.DimX + 1;
                        int        ySteps             = CUBE_Y - currentPermutation.DimY + 1;
                        int        zSteps             = CUBE_Z - currentPermutation.DimZ + 1;
                        int        placementCount     = xSteps * ySteps * zSteps;
                        this.KnownPlacements[pieceIndex][permutationIndex] = new Tuple <ulong, byte[, , ]> [placementCount];
                        int count = 0;
                        // loop through all dimensions
                        for (byte z = 0; z <= (CUBE_Z - currentPermutation.DimZ); z++)
                        {
                            for (byte y = 0; y <= (CUBE_Y - currentPermutation.DimY); y++)
                            {
                                for (byte x = 0; x <= (CUBE_X - currentPermutation.DimX); x++)
                                {
                                    byte[,,] trialCube = new byte[CUBE_X, CUBE_Y, CUBE_Z];
                                    PlacePiece(trialCube, x, y, z, currentPermutation);
                                    this.KnownPlacements[pieceIndex][permutationIndex][count] = CalculatePlacementTuple(trialCube);
                                    count++;
                                }
                            }
                        }
                    }
                }
            }
Example #2
0
            private void Worker_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
            {
                BackgroundWorker worker = sender as BackgroundWorker;

                this.backgroundWorkers.Remove(worker);

                HashSet <PossibleSolution>[] allSteps = e.Result as HashSet <PossibleSolution>[];
                foreach (PossibleSolution possibleSolution in allSteps[KNOWN_PIECES.Length - 1])
                {
                    this.solutions.Add(possibleSolution);
                }

                if (this.backgroundWorkers.Count > 0)
                {
                    // not done yet
                    return;
                }

                PossibleSolution solutionSteps = this.solutions.First();

                Console.WriteLine("Expected: " + ((ulong)Math.Pow(2, CUBE_X * CUBE_Y * CUBE_Z - 1) + ((ulong)Math.Pow(2, CUBE_X * CUBE_Y * CUBE_Z - 1) - 1)));
                Console.WriteLine("Solution: " + solutionSteps.CubeStatus);
                byte[,,] solutionCube = new byte[CUBE_X, CUBE_Y, CUBE_Z];
                ulong check = 0;

                for (int pieceIndex = 0; pieceIndex < KNOWN_PIECES.Length; pieceIndex++)
                {
                    Tuple <int, int> permAndPlace = solutionSteps.PiecePermutationAndPlacement[pieceIndex];
                    Console.WriteLine("Piece:" + (pieceIndex + 1) + " Permutation:" + permAndPlace.Item1 + " Placement:" + permAndPlace.Item2);
                    byte[,,] pieceSolution = this.KnownPlacements[pieceIndex][permAndPlace.Item1][permAndPlace.Item2].Item2;
                    check ^= this.KnownPlacements[pieceIndex][permAndPlace.Item1][permAndPlace.Item2].Item1;
                    for (int z = 0; z < CUBE_Z; z++)
                    {
                        for (int y = 0; y < CUBE_Y; y++)
                        {
                            for (int x = 0; x < CUBE_X; x++)
                            {
                                if (pieceSolution[x, y, z] != 0)
                                {
                                    solutionCube[x, y, z] = pieceSolution[x, y, z];
                                }
                            }
                        }
                    }
                }
                OutputCube(solutionCube, CUBE_X, CUBE_Y, CUBE_Z);

                byte[] solutionBytes = new byte[CUBE_X * CUBE_Y * CUBE_Z];
                for (int z = 0; z < CUBE_Z; z++)
                {
                    for (int y = 0; y < CUBE_Y; y++)
                    {
                        for (int x = 0; x < CUBE_X; x++)
                        {
                            solutionBytes[x + y * CUBE_X + z * CUBE_X * CUBE_Y] = solutionCube[x, y, z];
                        }
                    }
                }

                KnownPiece        solutionPiece     = new KnownPiece(0, CUBE_X, CUBE_Y, CUBE_Z, solutionBytes);
                List <KnownPiece> solutionRotations = GeneratePiecePermutations(solutionPiece);
                List <BigInteger> solutionSums      = new List <BigInteger>();

                foreach (KnownPiece rotation in solutionRotations)
                {
                    StringBuilder digitsXYZ = new StringBuilder(new string('_', CUBE_X * CUBE_Y * CUBE_Z));
                    for (int z = 0; z < CUBE_Z; z++)
                    {
                        for (int y = 0; y < CUBE_Y; y++)
                        {
                            for (int x = 0; x < CUBE_X; x++)
                            {
                                digitsXYZ[x + y * CUBE_X + z * CUBE_X * CUBE_Y] = Convert.ToChar(rotation.Blocks[x, y, z].ToString());
                            }
                        }
                    }
                    solutionSums.Add(BigInteger.Parse(String.Join("", digitsXYZ.ToString().Reverse())));
                }

                solutionSums.Sort();
                BigInteger hackerSum = BigInteger.Zero;

                foreach (BigInteger pieceSum in solutionSums)
                {
                    hackerSum += pieceSum;
                    Console.WriteLine(pieceSum);
                }

                Console.WriteLine("Hacker Solution: " + hackerSum);
            }
Example #3
0
 private byte[,,] PlacePiece(byte[,,] currentCube, byte posX, byte posY, byte posZ, KnownPiece piece)
 {
     // place piece
     for (int pieceZ = 0; pieceZ < piece.DimZ; pieceZ++)
     {
         for (int pieceY = 0; pieceY < piece.DimY; pieceY++)
         {
             for (int pieceX = 0; pieceX < piece.DimX; pieceX++)
             {
                 // voxel in new piece
                 if (piece.Blocks[pieceX, pieceY, pieceZ] != 0)
                 {
                     currentCube[posX + pieceX, posY + pieceY, posZ + pieceZ] = piece.Blocks[pieceX, pieceY, pieceZ];
                 }
             }
         }
     }
     return(currentCube);
 }
Example #4
0
        //// trial 3x3 puzzle
        //private static readonly KnownPiece[] KNOWN_PIECES = {
        //    new KnownPiece(1, 3, 3, 3, new byte[] { 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 1 }),
        //    new KnownPiece(2, 2, 2, 2, new byte[] { 2, 2, 2, 0, 2, 0, 0, 0 }),
        //    new KnownPiece(3, 3, 3, 3, new byte[] { 3, 3, 3, 3, 3, 3, 3, 3, 0, 3, 3, 3, 3, 0, 0, 3, 0, 0, 3, 3, 0, 3, 0, 0, 0, 0, 0 })
        //};

        //// another 3x3 trial
        //private static readonly KnownPiece[] KNOWN_PIECES = {
        //    new KnownPiece(1, 2, 3, 1, new byte[] { 1, 1, 0, 1, 0, 1 }),
        //    new KnownPiece(2, 2, 3, 1, new byte[] { 2, 2, 0, 2, 0, 2 }),
        //    new KnownPiece(3, 2, 3, 1, new byte[] { 3, 3, 0, 3, 0, 3 }),
        //    new KnownPiece(4, 2, 3, 1, new byte[] { 4, 4, 0, 4, 0, 4 }),
        //    new KnownPiece(5, 2, 2, 1, new byte[] { 5, 5, 0, 5 }),
        //    new KnownPiece(6, 2, 3, 1, new byte[] { 0, 6, 6, 6, 6, 0}),
        //    new KnownPiece(7, 2, 3, 1, new byte[] { 0, 7, 7, 7, 0, 7 })
        //};

        //// another 3x3 trial
        //private static readonly KnownPiece[] KNOWN_PIECES = {
        //    new KnownPiece(1, 2, 2, 2, new byte[] { 0, 0, 1, 0, 1, 0, 1, 1 }),
        //    new KnownPiece(2, 2, 2, 2, new byte[] { 0, 2, 2, 2, 0, 0, 2, 0 }),
        //    new KnownPiece(3, 2, 3, 1, new byte[] { 0, 3, 3, 3, 3, 0 }),
        //    new KnownPiece(4, 2, 2, 2, new byte[] { 0, 0, 4, 0, 0, 4, 4, 4 }),
        //    new KnownPiece(5, 2, 2, 1, new byte[] { 0, 5, 5, 5 }),
        //    new KnownPiece(6, 3, 2, 1, new byte[] { 0, 6, 0, 6, 6, 7 }),
        //    new KnownPiece(7, 3, 2, 1, new byte[] { 0, 0, 7, 7, 7, 7 })
        //};

        //// trivial 3x3 example
        //private static readonly KnownPiece[] KNOWN_PIECES = {
        //    new KnownPiece(1, 3, 1, 1, new byte[] { 1, 1, 1 }),
        //    new KnownPiece(2, 3, 1, 1, new byte[] { 1, 1, 1 }),
        //    new KnownPiece(3, 3, 1, 1, new byte[] { 1, 1, 1 }),
        //    new KnownPiece(4, 3, 1, 1, new byte[] { 1, 1, 1 }),
        //    new KnownPiece(5, 3, 1, 1, new byte[] { 1, 1, 1 }),
        //    new KnownPiece(6, 3, 1, 1, new byte[] { 1, 1, 1 }),
        //    new KnownPiece(7, 3, 1, 1, new byte[] { 1, 1, 1 }),
        //    new KnownPiece(8, 3, 1, 1, new byte[] { 1, 1, 1 }),
        //    new KnownPiece(9, 3, 1, 1, new byte[] { 1, 1, 1 })
        //};

        /// <summary>
        /// For all of the 6 sides (imagine a cube) we rotate the piece through the 4 orientation.
        /// This gives us, at most, 24 different ways of looking at the piece. Duplicates are eliminated.
        /// </summary>
        private static List <KnownPiece> GeneratePiecePermutations(KnownPiece piece)
        {
            List <KnownPiece> retVal = new List <KnownPiece>();
            // original #1 [front]
            KnownPiece zRotate1 = new KnownPiece(piece.PieceId, piece.DimX, piece.DimY, piece.DimZ);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        zRotate1.Blocks[x, y, z] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(zRotate1);
            // original #1 + 180 y
            KnownPiece zRotate2 = new KnownPiece(piece.PieceId, piece.DimX, piece.DimY, piece.DimZ);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        zRotate2.Blocks[piece.DimX - 1 - x, y, piece.DimZ - 1 - z] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(zRotate2);
            // original #1 + 180 x
            KnownPiece zRotate3 = new KnownPiece(piece.PieceId, piece.DimX, piece.DimY, piece.DimZ);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        zRotate3.Blocks[x, piece.DimY - 1 - y, piece.DimZ - 1 - z] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(zRotate3);
            // original #1 + 180 z
            KnownPiece zRotate4 = new KnownPiece(piece.PieceId, piece.DimX, piece.DimY, piece.DimZ);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        zRotate4.Blocks[piece.DimX - 1 - x, piece.DimY - 1 - y, z] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(zRotate4);
            // original #2 [front turned right]
            KnownPiece zRotate5 = new KnownPiece(piece.PieceId, piece.DimY, piece.DimX, piece.DimZ);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        zRotate5.Blocks[piece.DimY - 1 - y, x, z] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(zRotate5);
            // original #2 + 180 z
            KnownPiece zRotate6 = new KnownPiece(piece.PieceId, piece.DimY, piece.DimX, piece.DimZ);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        zRotate6.Blocks[y, piece.DimX - 1 - x, z] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(zRotate6);
            // original #2 + 180 y
            KnownPiece zRotate7 = new KnownPiece(piece.PieceId, piece.DimY, piece.DimX, piece.DimZ);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        zRotate7.Blocks[y, x, piece.DimZ - 1 - z] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(zRotate7);
            // original #2 + 180 x
            KnownPiece zRotate8 = new KnownPiece(piece.PieceId, piece.DimY, piece.DimX, piece.DimZ);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        zRotate8.Blocks[piece.DimY - 1 - y, piece.DimX - 1 - x, piece.DimZ - 1 - z] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(zRotate8);
            // original #3 [left]
            KnownPiece xRotate1 = new KnownPiece(piece.PieceId, piece.DimZ, piece.DimY, piece.DimX);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        xRotate1.Blocks[piece.DimZ - 1 - z, y, x] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(xRotate1);
            // original #3 +180 y
            KnownPiece xRotate2 = new KnownPiece(piece.PieceId, piece.DimZ, piece.DimY, piece.DimX);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        xRotate2.Blocks[z, y, piece.DimX - 1 - x] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(xRotate2);
            // original #3 + 180 z
            KnownPiece xRotate3 = new KnownPiece(piece.PieceId, piece.DimZ, piece.DimY, piece.DimX);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        xRotate3.Blocks[z, piece.DimY - 1 - y, x] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(xRotate3);
            // original #3 + 180 x
            KnownPiece xRotate4 = new KnownPiece(piece.PieceId, piece.DimZ, piece.DimY, piece.DimX);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        xRotate4.Blocks[piece.DimZ - 1 - z, piece.DimY - 1 - y, piece.DimX - 1 - x] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(xRotate4);
            // original #4 [left turned left]
            KnownPiece xRotate5 = new KnownPiece(piece.PieceId, piece.DimY, piece.DimZ, piece.DimX);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        xRotate5.Blocks[y, z, x] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(xRotate5);
            // original #4 + 180 x
            KnownPiece xRotate6 = new KnownPiece(piece.PieceId, piece.DimY, piece.DimZ, piece.DimX);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        xRotate6.Blocks[y, piece.DimZ - 1 - z, piece.DimX - 1 - x] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(xRotate6);
            // original #4 + 180 y
            KnownPiece xRotate7 = new KnownPiece(piece.PieceId, piece.DimY, piece.DimZ, piece.DimX);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        xRotate7.Blocks[piece.DimY - 1 - y, z, piece.DimX - 1 - x] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(xRotate7);
            // original #4 + 180 z
            KnownPiece xRotate8 = new KnownPiece(piece.PieceId, piece.DimY, piece.DimZ, piece.DimX);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        xRotate8.Blocks[piece.DimY - 1 - y, piece.DimZ - 1 - z, x] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(xRotate8);
            // original #5 [bottom]
            KnownPiece yRotate1 = new KnownPiece(piece.PieceId, piece.DimX, piece.DimZ, piece.DimY);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        yRotate1.Blocks[x, z, piece.DimY - 1 - y] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(yRotate1);
            // original #5 + 180 x
            KnownPiece yRotate2 = new KnownPiece(piece.PieceId, piece.DimX, piece.DimZ, piece.DimY);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        yRotate2.Blocks[x, piece.DimZ - 1 - z, y] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(yRotate2);
            // original #5 + 180 z
            KnownPiece yRotate3 = new KnownPiece(piece.PieceId, piece.DimX, piece.DimZ, piece.DimY);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        yRotate3.Blocks[piece.DimX - 1 - x, piece.DimZ - 1 - z, piece.DimY - 1 - y] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(yRotate3);
            // original #5 + 180 y
            KnownPiece yRotate4 = new KnownPiece(piece.PieceId, piece.DimX, piece.DimZ, piece.DimY);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        yRotate4.Blocks[piece.DimX - 1 - x, z, piece.DimY - 1 - y] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(yRotate4);
            // original #6 [top turned right]
            KnownPiece yRotate5 = new KnownPiece(piece.PieceId, piece.DimZ, piece.DimX, piece.DimY);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        yRotate5.Blocks[z, x, y] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(yRotate5);
            // original #6 + 180 y
            KnownPiece yRotate6 = new KnownPiece(piece.PieceId, piece.DimZ, piece.DimX, piece.DimY);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        yRotate6.Blocks[piece.DimZ - 1 - z, x, piece.DimY - 1 - y] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(yRotate6);
            // original #6 + 180 x
            KnownPiece yRotate7 = new KnownPiece(piece.PieceId, piece.DimZ, piece.DimX, piece.DimY);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        yRotate7.Blocks[z, piece.DimX - 1 - x, piece.DimY - 1 - y] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(yRotate7);
            // original #6 + 180 z
            KnownPiece yRotate8 = new KnownPiece(piece.PieceId, piece.DimZ, piece.DimX, piece.DimY);

            for (int z = 0; z < piece.DimZ; z++)
            {
                for (int y = 0; y < piece.DimY; y++)
                {
                    for (int x = 0; x < piece.DimX; x++)
                    {
                        yRotate8.Blocks[piece.DimZ - 1 - z, piece.DimX - 1 - x, y] = piece.Blocks[x, y, z];
                    }
                }
            }
            retVal.Add(yRotate8);

            // make rotations unique
            retVal = retVal.GroupBy(pieceRotation => pieceRotation.Footprint).Select(group => group.First()).ToList();

            return(retVal);
        }