public void SolveTenBlockPuzzle(out FiveBlocks bottomLayerOfSolution, out FiveBlocks topLayerOfSolution) { // get the blocks needed for the 10 piece wooden puzzle BlockFactory blockFactory = new BlockFactory(); TenBlocks tenBlocks = blockFactory.GetPuzzleWithTenBlocks(); // get a collection of all 5 block variations including all possible flipped blocks. // each of these FiveBlocks objects forms the bottom of a potential solution, until disproved HashSet <FiveBlocks> listsOfFiveBlocks = CalculateAllFiveBlockVariationsIncludingReversals(tenBlocks); CalculateLayerOfSolution(out bottomLayerOfSolution, out topLayerOfSolution, tenBlocks, listsOfFiveBlocks); }
public TenBlocks GetPuzzleWithTenBlocks() { List <Block> blocks = new List <Block>(); // creating blocks from real blocks. turning the blocks so that the more "interesting" stuff is on the left, just to make recognising blocks easier. blocks.Add( CreateBlock( 1, CreateBlockSlotArray1())); blocks.Add( CreateBlock( 2, CreateBlockSlotArray2())); blocks.Add( CreateBlock( 3, CreateBlockSlotArray3())); blocks.Add( CreateBlock( 4, CreateBlockSlotArray4())); blocks.Add( CreateBlock( 5, CreateBlockSlotArray5())); blocks.Add( CreateBlock( 6, CreateBlockSlotArray6())); blocks.Add( CreateBlock( 7, CreateBlockSlotArray7())); blocks.Add( CreateBlock( 8, CreateBlockSlotArray8())); blocks.Add( CreateBlock( 9, CreateBlockSlotArray9())); blocks.Add( CreateBlock( 10, CreateBlockSlotArray10())); TenBlocks tenBlocks = new TenBlocks(blocks); return(tenBlocks); }
private void CalculateLayerOfSolution(out FiveBlocks bottomLayerOfSolution, out FiveBlocks topLayerOfSolution, TenBlocks tenBlocks, HashSet <FiveBlocks> listsOfFiveBlocks) { bottomLayerOfSolution = null; topLayerOfSolution = null; foreach (var bottomFiveBlocks in listsOfFiveBlocks) { // now get the remaining five blocks FiveBlocks topFiveBlocks = new FiveBlocks(tenBlocks.Where(b => !bottomFiveBlocks.Contains(b)).ToList()); Dictionary <Block, int> blockToIndexMaping = GetTopLayerBlockMappingToBottomLayerIndex(bottomFiveBlocks, topFiveBlocks); if (blockToIndexMaping.Count == 5) { // this means we've matched all 5! we're done! // assign the layers bottomLayerOfSolution = bottomFiveBlocks; topLayerOfSolution = new FiveBlocks(blockToIndexMaping.Keys.ToList()); break; } } }
private HashSet <FiveBlocks> CalculateAllFiveBlockVariationsIncludingReversals(TenBlocks tenBlocks) { // all variations of true and false: // - true = not reversed block // - false = reversed block Variations <bool> flagVariations = CalculateAndPrintFlagVariations(); var blockVariations = new Variations <Block>(tenBlocks, 5); HashSet <FiveBlocks> listsOfFiveBlocks = new HashSet <FiveBlocks>(); foreach (var variation in blockVariations) { // now we have an ordered list of 5 blocks. // for each permutation, there 2 ^ 5 = 32 ways to flip the pieces foreach (List <bool> flagVariation in flagVariations) { List <Block> finalFixedList = new List <Block>(); for (int i = 0; i < flagVariation.Count; i++) { // use the flag to choose reversed block or not // TODO: memoization can easily be used here to not keep reversing the blocks finalFixedList.Add(flagVariation[i] ? variation[i] : new Block(variation[i])); } // final list for the bottom is built listsOfFiveBlocks.Add(new FiveBlocks(finalFixedList)); } } return(listsOfFiveBlocks); }