private static void recurSolverStarter(BlockPuzzle blockPuzzle) { List <Point> startingPoints = new List <Point>() { new Point(0, 0, 0), new Point(0, 1, 0), new Point(1, 0, 0), new Point(1, 1, 0), //new Point(0,0,1), //new Point(0,1,1), new Point(1, 0, 1), new Point(1, 1, 1), }; foreach (Point startingPoint in startingPoints) { BlockLine startingBlock = new BlockLine(BlockOrder[0] + 1, BlockLine.Orientation.Back); startingBlock.startPoint = startingPoint; startingBlock.endPoint = new Point(startingPoint.xPos, startingPoint.yPos + 2, startingPoint.zPos); blockPuzzle.AddBlockLineDirectly(startingBlock); StackSolver(blockPuzzle, BlockLine.Orientation.Left); StackSolver(blockPuzzle, BlockLine.Orientation.Right); StackSolver(blockPuzzle, BlockLine.Orientation.Up); StackSolver(blockPuzzle, BlockLine.Orientation.Down); StackSolver(blockPuzzle, BlockLine.Orientation.Front); StackSolver(blockPuzzle, BlockLine.Orientation.Back); blockPuzzle.RemoveLastBlockLine(); Console.WriteLine("Just finished up the pass for starting point {0}, {1}, {2} : {3}", startingPoint.xPos, startingPoint.yPos, startingPoint.zPos, System.DateTime.Now.ToLongTimeString()); } }
static void Main(string[] args) { System.Console.WriteLine("Starting at {0}.", System.DateTime.Now.ToLongTimeString()); BlockPuzzle FourByFour = new BlockPuzzle(BlockOrder); recurSolverStarter(FourByFour); System.Console.WriteLine("Ending at {0}.", System.DateTime.Now.ToLongTimeString()); }
public static void Main(string[] args) { // Start time System.Console.WriteLine("Program starting at {0}.", System.DateTime.Now.ToLongTimeString()); // Set up the puzzle BlockPuzzle FourByFourbyFour = new BlockPuzzle(BlockOrder); // Solve it! BlockPuzzle.Solve(FourByFourbyFour); // End time System.Console.WriteLine("Program ending at {0}.", System.DateTime.Now.ToLongTimeString()); System.Console.WriteLine("{0} total positions considered!", FourByFourbyFour.PositionCount); System.Console.ReadLine(); }
private static void StackSolver(BlockPuzzle blockPuzzle, BlockLine.Orientation nextOrientation) { if (!blockPuzzle.isFinished) { if (blockPuzzle.AddBlockLine(nextOrientation)) { StackSolver(blockPuzzle, BlockLine.Orientation.Left); StackSolver(blockPuzzle, BlockLine.Orientation.Right); StackSolver(blockPuzzle, BlockLine.Orientation.Up); StackSolver(blockPuzzle, BlockLine.Orientation.Down); StackSolver(blockPuzzle, BlockLine.Orientation.Front); StackSolver(blockPuzzle, BlockLine.Orientation.Back); blockPuzzle.RemoveLastBlockLine(); } } }
public static void Main(string[] args) { // Start the timer Stopwatch stopwatch = Stopwatch.StartNew(); // Go! Console.WriteLine("Program starting at {0}.", DateTime.Now.ToLongTimeString()); // Solve it! BlockPuzzle.Solve(BlockOrder); // End time stopwatch.Stop(); Console.WriteLine("Program ending at {0}.", DateTime.Now.ToLongTimeString()); Console.WriteLine("Total program time was {0:hh\\:mm\\:ss}", stopwatch.Elapsed); Console.WriteLine("Press Enter to exit."); Console.ReadLine(); }
// This part does the work and is called link by link private static void PuzzleSolverInnerLoop(BlockPuzzle blockPuzzle, BlockLine.BlockLineOrientation nextOrientation) { // If you're not done, keep working! if (!blockPuzzle.IsFinished) { // Try to add the requested orientation if (blockPuzzle.AddBlockLine(nextOrientation)) { // If adding the requested block succeeds, try to add another block in each direction! PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Left); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Right); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Up); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Down); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Front); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Back); // Once all directions have been tried, unroll the block you just placed from the master list blockPuzzle.RemovePreviousBlockLine(); } } }
// Start off by enumerating all the starting positions and adding them to the list private static void PuzzleSolver(BlockPuzzle blockPuzzle) { // These are the unique starting points, based on the first block size List <Point> startingPoints = new List <Point>() { new Point(0, 0, 0), new Point(0, 1, 0), new Point(1, 0, 0), new Point(1, 1, 0), new Point(1, 0, 1), new Point(1, 1, 1), }; // for each starting point, kick off the inner solver foreach (Point startingPoint in startingPoints) { // Start by going any direction, back chosen at random BlockLine startingBlock = new BlockLine(BlockOrder[0] + 1, BlockLine.BlockLineOrientation.Back); startingBlock.StartPoint = startingPoint; startingBlock.EndPoint = new Point(startingPoint.XPos, startingPoint.YPos + BlockOrder[0], startingPoint.ZPos); // Add the first block to the stack blockPuzzle.AddBlockLineDirectly(startingBlock); // Throw each next direction onto the depth-first queue PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Left); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Right); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Up); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Down); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Front); PuzzleSolverInnerLoop(blockPuzzle, BlockLine.BlockLineOrientation.Back); // Remove the first block to trigger the end of the routine blockPuzzle.RemovePreviousBlockLine(); Console.WriteLine("Just finished up the pass for starting point {0}, {1}, {2} : {3}", startingPoint.XPos, startingPoint.YPos, startingPoint.ZPos, System.DateTime.Now.ToLongTimeString()); } }
private BlockPuzzle Puzzle; // keep a ref to the master puzzle public BlockLine(int numBlocks, int blockIndex, BlockPuzzle puzzle) { this.NumBlocks = numBlocks; this.BlockIndex = blockIndex; this.Puzzle = puzzle; }
// Start off by enumerating all the starting positions and adding them to the list public static void Solve(BlockPuzzle blockPuzzle) { bool blockAdded = false; bool solutionFound = false; uint solutionCount = 0; // These are the unique starting points // all other starting points are equivalent by symmetry in a 4x4x4 cube // TODO: Build up a general model for unique starting points for cube size n // NOTE: This will spit out some solutions that are mirrors of each other. Although they're still "unique", // future work would be to prune out the mirrors. // (Ex: "start in the corner (0,0,0) and move left" is rotationally symmetric to "start in the corner (0,0,0) and move right") // (Ex: "start at 0,1,0, move up, then left" is vertically symmetric to "start at 0,1,0, move up, then right" List <Point> startingPoints = new List <Point>() { new Point(0, 0, 0), new Point(0, 1, 0), new Point(1, 1, 0), new Point(1, 1, 1), }; // for each starting point, kick off the inner solver foreach (Point startingPoint in startingPoints) { // Start time System.Console.WriteLine("Beginning pass with start point {0}, {1}, {2} at {3}. ====================", startingPoint.XPos, startingPoint.YPos, startingPoint.ZPos, System.DateTime.Now.ToLongTimeString()); // Update the starting point for the puzzle and the first block line blockPuzzle.StartingPoint = startingPoint; blockPuzzle.BlockLineList[0].StartPoint = startingPoint; // Since that's the starting point and we *know* that a block will be there, set that block in the grid blockPuzzle.TheGrid[blockPuzzle.StartingPoint.XPos, blockPuzzle.StartingPoint.YPos, blockPuzzle.StartingPoint.ZPos] = true; // Reset the starting link and orientation blockPuzzle.BlockLineIndex = 0; blockPuzzle.BlockLineList[blockPuzzle.BlockLineIndex].ZeroOrientation(); // no prior orientation // This is the main loop! while (blockPuzzle.BlockLineIndex >= 0) { // Try the next link and orientation. Does it fit? If so, add it in! blockAdded = blockPuzzle.AddBlockLine(blockPuzzle.BlockLineIndex); if (blockAdded) { // increment the link index blockPuzzle.BlockLineIndex++; // Are we done? Is that the last block? IS THAT A SOLUTION??? solutionFound = blockPuzzle.BlockLineIndex >= blockPuzzle.BlockLineList.Count; if (solutionFound) { Console.WriteLine("Solution #" + (solutionCount++ + 1) + " ================================================================"); // Add one to start with "Solution 1" blockPuzzle.PrintPuzzle(); // special last block line case, take the index back down to the last block blockPuzzle.BlockLineIndex--; } // if not, reset the new link's start pos and orientation in light of the last link's orientation else { blockPuzzle.BlockLineList[blockPuzzle.BlockLineIndex].StartPoint = blockPuzzle.BlockLineList[blockPuzzle.BlockLineIndex - 1].EndPoint; blockPuzzle.BlockLineList[blockPuzzle.BlockLineIndex].LastLineOrientation = blockPuzzle.BlockLineList[blockPuzzle.BlockLineIndex - 1].Orientation; blockPuzzle.BlockLineList[blockPuzzle.BlockLineIndex].ZeroOrientation(); } } // if the blockline couldn't be added OR we found a solution, rotate the block line in question in prep for next attempt if (!blockAdded || solutionFound) { // rotate the link if (blockPuzzle.BlockLineList[blockPuzzle.BlockLineIndex].RotateBlockLine()) { // exit this loop, go back up to the top of the loop, and try again! } // if that was the last rotation, there are no more options for this link. back up one link and rotate else { do { // back up one --(blockPuzzle.BlockLineIndex); }while ((blockPuzzle.BlockLineIndex >= 0) && // as long as you're not past the beginning (!blockPuzzle.BlockLineList[blockPuzzle.BlockLineIndex].RotateBlockLine())); // rotate and check, until there are no more rotates } } } // Clean up the starting point that we added in the beginning blockPuzzle.TheGrid[blockPuzzle.StartingPoint.XPos, blockPuzzle.StartingPoint.YPos, blockPuzzle.StartingPoint.ZPos] = false; // End time System.Console.WriteLine("Ending pass with start point {0}, {1}, {2} at {3}. =======================", startingPoint.XPos, startingPoint.YPos, startingPoint.ZPos, System.DateTime.Now.ToLongTimeString()); } }