public PossibleSolution(PossibleSolution parent, int pieceIndex, int permIndex, int placeIndex, ulong status) { this.PiecePermutationAndPlacement = new Tuple <int, int> [KNOWN_PIECES.Length]; for (int i = 0; i < parent.PiecePermutationAndPlacement.Length; i++) { if (parent.PiecePermutationAndPlacement[i] != null) { this.PiecePermutationAndPlacement[i] = parent.PiecePermutationAndPlacement[i]; } } this.PiecePermutationAndPlacement[pieceIndex] = new Tuple <int, int>(permIndex, placeIndex); this.CubeStatus = status; }
private void Worker_DoWork(object sender, DoWorkEventArgs e) { PossibleSolution startingPoint = e.Argument as PossibleSolution; HashSet <PossibleSolution>[] validSolutionsPerStep = new HashSet <PossibleSolution> [KNOWN_PIECES.Length]; validSolutionsPerStep[0] = new HashSet <PossibleSolution>(); validSolutionsPerStep[0].Add(startingPoint); // piece by piece for (int pieceIndex = 1; pieceIndex < KNOWN_PIECES.Length; pieceIndex++) { validSolutionsPerStep[pieceIndex] = new HashSet <PossibleSolution>(); ulong tries = 0; // against all previous solutions foreach (PossibleSolution previousSolutionStep in validSolutionsPerStep[pieceIndex - 1]) { // try all placements (including all permutations) of the current piece for (int permutationIndex = 0; permutationIndex < this.KnownPlacements[pieceIndex].Length; permutationIndex++) { for (int placementIndex = 0; placementIndex < this.KnownPlacements[pieceIndex][permutationIndex].Length; placementIndex++) { // valid, no overlaps in bits ulong placementBits = this.KnownPlacements[pieceIndex][permutationIndex][placementIndex].Item1; if ((previousSolutionStep.CubeStatus & placementBits) == 0) { validSolutionsPerStep[pieceIndex].Add(new PossibleSolution(previousSolutionStep, pieceIndex, permutationIndex, placementIndex, previousSolutionStep.CubeStatus ^ placementBits)); } else { // nothing ?! } tries++; } } } Console.WriteLine("Number of valid solutions (piece #" + pieceIndex + "): " + validSolutionsPerStep[pieceIndex].Count + " [tries: " + tries + "]"); } // report back e.Result = validSolutionsPerStep; }
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); }