private Dictionary <UsedTileDictionaryKey, int> GetDynamicCheckedTileDictionary() { var returnDictionary = new Dictionary <UsedTileDictionaryKey, int>(); int pIndexCounter = SubmittedPuzzleTileCount; var reverseSubmittedPuzzleTiles = SubmittedPuzzleTilesIndices.OrderByDescending(c => c).ToList(); var lastInserted = 4; foreach (var pIndex in reverseSubmittedPuzzleTiles) { var leftOver = 7 - pIndexCounter; foreach (var tile in TotalRotationTileList) { var tileKey = new UsedTileDictionaryKey(pIndex, tile.TileNumber, tile.Degrees); //Ok, so this should probably be calculated soon. But i need more time. //Hold my beer! It's calculated! if (SubmittedPuzzleTileCount == pIndexCounter) { returnDictionary.Add(tileKey, 1); continue; } returnDictionary.Add(tileKey, leftOver * lastInserted); } if (SubmittedPuzzleTileCount != pIndexCounter) { lastInserted = leftOver * lastInserted * 4; } pIndexCounter--; } return(returnDictionary.OrderBy(s => s.Key.PuzzleIndex).ToDictionary(s => s.Key, s => s.Value)); }
private Dictionary <UsedTileDictionaryKey, int> GetCheckedTileDictionary() { var returnDictionary = new Dictionary <UsedTileDictionaryKey, int>(); foreach (var depthCounter in SubmittedPuzzleTilesIndices) { foreach (var tile in TotalRotationTileList) { var tileKey = new UsedTileDictionaryKey(depthCounter, tile.TileNumber, tile.Degrees); returnDictionary.Add(tileKey, 0); } } return(returnDictionary); }
public void FillCheckedTileDictionary() { foreach (var usedPIndex in UsedPuzzleTilesIndices) { foreach (var tile in Initiator.TileList) { var firstTileKey = new UsedTileDictionaryKey(usedPIndex, tile.TileNumber, 0); CheckedTileDictionary.Add(firstTileKey, 0); foreach (var tileRot in tile.TileRotationList) { var tileKey = new UsedTileDictionaryKey(usedPIndex, tile.TileNumber, tileRot.Degrees); CheckedTileDictionary.Add(tileKey, 0); } } } }
private void CheckTileCountAndUpIfNeeded(bool didBailOut) { var usedTileNumbers = UsedTileList.Select(s => s.TileNumber); var allKeys = UsedTileList.Select(s => new UsedTileDictionaryKey(s.PuzzleIndex, s.TileNumber, s.Degrees)).ToList(); //var otherTileKeys = Initiator.TotalRotationTileList.Where(s => !usedTileNumbers.Contains(s.TileNumber)); var uppedAboveTiles = false; if (AmountOfCheckedSolutions % 480 == 0) { } if (!didBailOut) { } var dynamicNotMaxedOut = DynamicCheckedTileDictionary.Where(s => s.Value < AmountOfMaximumTriesPerTile).ToList(); //var dynamicLowerThanChecked = DynamicCheckedTileDictionary.Where(a => a.Value <= CheckedTileDictionary[a.Key] && a.Value != AmountOfMaximumTriesPerTile).ToList(); //if (dynamicLowerThanChecked.Any()) //{ //} if (didBailOut) { //if (!uppedAboveTiles) { var lastTile = UsedTileList.OrderBy(s => s.PuzzleIndex).LastOrDefault(); var keysAboveCurrent = allKeys.Where(s => PuzzleIndexCounter[s.PuzzleIndex] <= lastTile.PuzzleDepthCounter).ToList(); var relevantLayer = PuzzleIndexCounter[lastTile.PuzzleIndex]; var oriDepthAmount = OriginalDepthCounter[relevantLayer]; if (keysAboveCurrent.Any()) { foreach (var keyAbove in keysAboveCurrent) { if (CheckedTileDictionary[keyAbove] + oriDepthAmount <= AmountOfMaximumTriesPerTile) { CheckedTileDictionary[keyAbove] += oriDepthAmount; } } uppedAboveTiles = true; } //var usedTileKeysBelowThisLayer = CheckedTileDictionary.Keys.Where(s => s.PuzzleIndex > key.PuzzleIndex && !usedTileNumbers.Contains(s.TileNumber)); var usedTileKeysBelowThisLayer = DynamicCheckedTileDictionary.Keys.Where(s => s.PuzzleIndex > lastTile.PuzzleIndex && !usedTileNumbers.Contains(s.TileNumber)).ToList(); var firstLayerAfterBailOut = relevantLayer + 1; foreach (var otKey in usedTileKeysBelowThisLayer) { var otKeyLayer = PuzzleIndexCounter[otKey.PuzzleIndex]; if (DynamicCheckedTileDictionary[otKey] + OriginalDepthCounter[firstLayerAfterBailOut] <= AmountOfMaximumTriesPerTile) { if (otKey.PuzzleIndex == 5 && otKey.TileNumber == 2 && otKey.Degrees == 0 && DynamicCheckedTileDictionary[otKey] >= 440) { } DynamicCheckedTileDictionary[otKey] += OriginalDepthCounter[firstLayerAfterBailOut]; } else { Debug.WriteLine(String.Format("We bailout out, but did NOT up the below layer! {0}", otKey.ToString())); //Lets fill it up towards max DynamicCheckedTileDictionary[otKey] = AmountOfMaximumTriesPerTile; } CheckedTileDictionary[otKey] += OriginalDepthCounter[firstLayerAfterBailOut]; } var keysAboveCurrentlayer = allKeys.Where(s => PuzzleIndexCounter[s.PuzzleIndex] != lastTile.PuzzleDepthCounter); var tileNumbersAboveCurrentLayer = keysAboveCurrentlayer.Select(s => s.TileNumber); var tilesInSameLayer = CheckedTileDictionary.Keys.Where(s => s.PuzzleIndex == lastTile.PuzzleIndex && !tileNumbersAboveCurrentLayer.Contains(s.TileNumber)); var key = new UsedTileDictionaryKey(lastTile.PuzzleIndex, lastTile.TileNumber, lastTile.Degrees); var allSameAmount = tilesInSameLayer.All(a => CheckedTileDictionary[a] == CheckedTileDictionary[key] && CheckedTileDictionary[a] != AmountOfMaximumTriesPerTile); if (allSameAmount) { foreach (var tsl in tilesInSameLayer) { if (DynamicCheckedTileDictionary[tsl] + oriDepthAmount <= AmountOfMaximumTriesPerTile) { DynamicCheckedTileDictionary[tsl] += oriDepthAmount; } } } foreach (var kkey in keysAboveCurrent) { var rTile = UsedTileList.FirstOrDefault(s => s.PuzzleIndex == kkey.PuzzleIndex && s.TileNumber == kkey.TileNumber && s.Degrees == kkey.Degrees); //See if one of the used keys (starting at the end) has been used too much if (Initiator.CheckedTileDictionary[kkey] >= DynamicCheckedTileDictionary[kkey]) { RemoveAndResetPuzzleTile(rTile); //break; } } //RemoveAndResetPuzzleTile(lastTile); } var dynamicLowerThanChecked = DynamicCheckedTileDictionary.Where(a => a.Value <= CheckedTileDictionary[a.Key] && a.Value != AmountOfMaximumTriesPerTile).ToList(); if (dynamicLowerThanChecked.Any()) { } return; } foreach (var key in allKeys.OrderByDescending(s => s.PuzzleIndex)) { var relevantTile = UsedTileList.FirstOrDefault(s => s.TileNumber == key.TileNumber && s.Degrees == key.Degrees); var relevantLayer = PuzzleIndexCounter[key.PuzzleIndex]; var oriDepthAmount = OriginalDepthCounter[relevantLayer]; var dynamicKeyCount = DynamicCheckedTileDictionary[key]; //else { //Only up if there is an actual checked solution if (allKeys.Count == SubmittedPuzzleTileCount) { if (CheckedTileDictionary[key] + 1 <= dynamicKeyCount) { CheckedTileDictionary[key]++; } //if (CheckedTileDictionary[key] > 0) //{ // var keysAboveCurrentlayer = allKeys.Where(s => PuzzleIndexCounter[s.PuzzleIndex] != relevantTile.PuzzleDepthCounter); // var tileNumbersAboveCurrentLayer = keysAboveCurrentlayer.Select(s => s.TileNumber); // var tilesInSameLayer = CheckedTileDictionary.Keys.Where(s => s.PuzzleIndex == key.PuzzleIndex && !tileNumbersAboveCurrentLayer.Contains(s.TileNumber)); // var allSameAmount = tilesInSameLayer.All(a => CheckedTileDictionary[a] == CheckedTileDictionary[key]); // if (allSameAmount) // { // if (DynamicCheckedTileDictionary[key] + oriDepthAmount <= AmountOfMaximumTriesPerTile) // { // foreach (var otKey in tilesInSameLayer) // { // DynamicCheckedTileDictionary[new UsedTileDictionaryKey(key.PuzzleIndex, otKey.TileNumber, otKey.Degrees)] += oriDepthAmount; // } // } // } //} //foreach (var akey in allKeys.OrderByDescending(s => s.PuzzleIndex)) //{ //var relevantTile = UsedTileList.FirstOrDefault(s => //s.TileNumber == akey.TileNumber && s.Degrees == akey.Degrees); //See if one of the used keys (starting at the end) has been used too much if (Initiator.CheckedTileDictionary[key] >= DynamicCheckedTileDictionary[key]) { //UsedPuzzleTilesIndices.Remove(key.PuzzleIndex); //UsedTileList.Remove(relevantTile); //UsedTileDictionary[key.TileNumber] = false; //var keysAboveCurrentlayer = allKeys.Where(s => PuzzleIndexCounter[s.PuzzleIndex] != relevantTile.PuzzleDepthCounter); //var tileNumbersAboveCurrentLayer = keysAboveCurrentlayer.Select(s => s.TileNumber); //var tilesInSameLayer = CheckedTileDictionary.Keys.Where(s => s.PuzzleIndex == key.PuzzleIndex && !tileNumbersAboveCurrentLayer.Contains(s.TileNumber)); //We should only += the DynamicDepthCounter in the above layers. var aboveLayer = OriginalDepthCounter.FirstOrDefault(s => s.Key > relevantTile.PuzzleDepthCounter); if (aboveLayer.Key != 0) { var usedTileNumbersAboveThisLayer = allKeys.Where(s => s.PuzzleIndex < DepthToIndex[aboveLayer.Key]).Select(a => a.TileNumber).ToList(); var relevantIndex = DepthToIndex[aboveLayer.Key]; var everyKeyExceptUsedOnes = DynamicCheckedTileDictionary.Where(s => s.Key.PuzzleIndex == relevantIndex && !usedTileNumbersAboveThisLayer.Contains(s.Key.TileNumber)).ToList(); foreach (var keyEx in everyKeyExceptUsedOnes) { //Update the count for the next round DynamicCheckedTileDictionary[keyEx.Key] += OriginalDepthCounter[aboveLayer.Key]; } } RemoveAndResetPuzzleTile(relevantTile); //relevantTile.PuzzleDepthCounter = 0; //relevantTile.PuzzleIndex = -1; } //} } } var dynamicLowerThanChecked = DynamicCheckedTileDictionary.Where(a => a.Value <= CheckedTileDictionary[a.Key] && a.Value != AmountOfMaximumTriesPerTile).ToList(); if (dynamicLowerThanChecked.Any()) { } //See if one of the used keys (starting at the end) has been used too much if (Initiator.CheckedTileDictionary[key] >= dynamicKeyCount && didBailOut) { RemoveAndResetPuzzleTile(relevantTile); break; } } }
public SolvedPuzzleViewModel SolvePuzzle(PuzzleViewModel puzzleVM) { var solvedPuzzleVM = new SolvedPuzzleViewModel(); solvedPuzzleVM.ErrorList = ValidatePuzzle(puzzleVM); if (solvedPuzzleVM.ErrorList.Any()) { return(solvedPuzzleVM); } Initiator.Initialize(puzzleVM); UsedTileList.Clear(); UsedTileDictionary = TileList.ToDictionary(s => s.TileNumber, s => false); var breakCount = 0; var tries = new List <String>(); var start = DateTime.Now; //After the first run, the DepthCounter dictionary should probably be updated to be * 2? //while (!solvedPuzzleVM.Solved && CheckedTileDictionary.Values.All(s => s == AmountOfMaximumTriesPerTile)) while (!solvedPuzzleVM.Solved && AmountOfCheckedSolutions < AmountOfTotalSolutions && breakCount <= AmountOfTotalSolutions) { breakCount++; foreach (var tile in Initiator.TotalRotationTileList) { if (solvedPuzzleVM.Solved) { break; } if (UsedTileDictionary[tile.TileNumber]) { continue; } if (!UsedTileDictionary[tile.TileNumber]) { UsedTileList.Add(tile); UsedTileDictionary[tile.TileNumber] = true; } //var puzzleFieldCount = 0; foreach (var puzzleTile in puzzleVM.TileIndexList.Where(s => !UsedPuzzleTilesIndices.Contains(s.Index))) { //There already is a tile on this puzzlefield if (UsedPuzzleTilesIndices.Contains(puzzleTile.Index)) { continue; } if (tile.PuzzleIndex >= 0) { break; } tile.PuzzleDepthCounter = PuzzleIndexCounter[puzzleTile.Index]; var tileKey = new UsedTileDictionaryKey(puzzleTile.Index, tile.TileNumber, tile.Degrees); //var usedTileNumbers = new HashSet<int>(UsedTileList.Select(a => a.TileNumber)); //var tilesInSameLayer = CheckedTileDictionary.Keys.Where(s => s.PuzzleIndex == tileKey.PuzzleIndex && !usedTileNumbers.Contains(s.TileNumber)); //var lessAmount = tilesInSameLayer.Any(a => CheckedTileDictionary[a] < DynamicCheckedTileDictionary[tileKey]); if (CheckedTileDictionary[tileKey] >= DynamicCheckedTileDictionary[tileKey]) { RemoveAndResetPuzzleTile(tile); //UsedPuzzleTilesIndices.Remove(tile.PuzzleIndex); //UsedTileList.Remove(tile); //UsedTileDictionary[tile.TileNumber] = false; //tile.PuzzleIndex = -1; //tile.PuzzleDepthCounter = 0; break; } tile.PuzzleIndex = puzzleTile.Index; UsedPuzzleTilesIndices.Add(puzzleTile.Index); if (puzzleVM.UseBailout) { if (UsedTileList.Count >= 1 && UsedTileList.Count < SubmittedPuzzleTileCount) { if (DoEarlyBailOut()) { break; } } } if (UsedTileList.Count == SubmittedPuzzleTileCount) { AmountOfCheckedSolutions++; //var solveString = String.Format("Trying to solve with: {0}", String.Join(" AND ", UsedTileList.OrderBy(s => s.PuzzleIndex).Select(s => s.ToString()))); //tries.Add(solveString); FillPuzzleRoads(UsedTileList); if (DoesDefinitiveRoadListSolvePuzzle(Initiator.SimpleConditionsList)) { var newList = new List <Tile>(); //solvedPuzzleVM.Solved = true; if (solvedPuzzleVM.TileSet.Count <= 2) { foreach (var ut in UsedTileList) { var newTile = new Tile(ut.TileNumber, ut.Degrees); newTile.PuzzleIndex = ut.PuzzleIndex; newList.Add(newTile); } solvedPuzzleVM.TileSet.Add(newList); } } //var allKeys = UsedTileList // .Select(s => new UsedTileDictionaryKey(s.PuzzleIndex, s.TileNumber, s.Degrees)).ToList(); //foreach (var key in allKeys) //{ // Initiator.CheckedTileDictionary[key]++; //} ////There are still other tile combinations to be checked //foreach (var key in allKeys.OrderByDescending(s => s.PuzzleIndex)) //{ // var relevantTile = UsedTileList.FirstOrDefault(s => // s.TileNumber == key.TileNumber && s.Degrees == key.Degrees); // //See if one of the used keys (starting at the end) has been used too much // if (Initiator.CheckedTileDictionary[key] >= DynamicCheckedTileDictionary[key]) // { // //UsedPuzzleTilesIndices.Remove(key.PuzzleIndex); // //UsedTileList.Remove(relevantTile); // //UsedTileDictionary[key.TileNumber] = false; // //We should only += the DynamicDepthCounter in the above layers. // var aboveLayer = OriginalDepthCounter.FirstOrDefault(s => s.Key > relevantTile.PuzzleDepthCounter); // if (aboveLayer.Key != 0) // { // var usedTileNumbersAboveThisLayer = allKeys.Where(s => s.PuzzleIndex < DepthToIndex[aboveLayer.Key]).Select(a => a.TileNumber).ToList(); // var relevantIndex = DepthToIndex[aboveLayer.Key]; // var everyKeyExceptUsedOnes = DynamicCheckedTileDictionary.Where(s => // s.Key.PuzzleIndex == relevantIndex && // !usedTileNumbersAboveThisLayer.Contains(s.Key.TileNumber)).ToList(); // foreach (var keyEx in everyKeyExceptUsedOnes) // { // //Update the count for the next round // DynamicCheckedTileDictionary[keyEx.Key] += OriginalDepthCounter[aboveLayer.Key]; // } // } // RemoveAndResetPuzzleTile(relevantTile); // //relevantTile.PuzzleDepthCounter = 0; // //relevantTile.PuzzleIndex = -1; // } //} } CheckTileCountAndUpIfNeeded(false); } } } var end = DateTime.Now; solvedPuzzleVM.SolveDuration = (end - start); solvedPuzzleVM.AmountOfCheckedSolutions = AmountOfCheckedSolutions; solvedPuzzleVM.AmountOfTotalSolutions = AmountOfTotalSolutions; solvedPuzzleVM.AmountOfFoundSolutions = solvedPuzzleVM.TileSet.Count; solvedPuzzleVM.TriedSolutions = tries; var nonMax = Initiator.CheckedTileDictionary.Where(s => s.Value < AmountOfMaximumTriesPerTile).ToList(); var nonCheckedAmount = nonMax.Sum(s => AmountOfMaximumTriesPerTile - s.Value); if (solvedPuzzleVM.AmountOfFoundSolutions == 1) { //Valid puzzle, lets write to JSON if (puzzleVM.Name != "Puzzle ") { var jsonPuzzles = GetJsonPuzzles(); var relevantPuzzle = jsonPuzzles.PuzzleList.FirstOrDefault(s => s.Name == puzzleVM.Name); if (relevantPuzzle != null) { if (relevantPuzzle.BestSolveTime.TotalMilliseconds == 0 || solvedPuzzleVM.SolveDuration < relevantPuzzle.BestSolveTime) { solvedPuzzleVM.ErrorList.Add("New solve record!"); relevantPuzzle.BestSolveTime = solvedPuzzleVM.SolveDuration; //open file stream using (StreamWriter file = File.CreateText(JsonPuzzlesPath)) { string json = JsonConvert.SerializeObject(jsonPuzzles); JsonSerializer serializer = new JsonSerializer(); //serialize object directly into file stream serializer.Serialize(file, jsonPuzzles); solvedPuzzleVM.SavedPuzzleName = puzzleVM.Name; } } else { solvedPuzzleVM.ErrorList.Add("Puzzle is already saved as: " + puzzleVM.Name + " !"); } } } } return(solvedPuzzleVM); }
public SolvedPuzzleViewModel SolvePuzzle(PuzzleViewModel puzzleVM) { var solvedPuzzleVM = new SolvedPuzzleViewModel(); solvedPuzzleVM.ErrorList = ValidatePuzzle(puzzleVM); if (solvedPuzzleVM.ErrorList.Any()) { return(solvedPuzzleVM); } UsedPuzzleTilesIndices = new HashSet <int>(puzzleVM.PuzzleTileList.Select(s => s.Index)); var simpleConditionsList = puzzleVM.PuzzleTileList.SelectMany(s => s.SimpleTileIndexList).ToList(); FillCheckedTileDictionary(); FillTotalAmountOfSolutions(); //usedTileList = new List<Tile>(); var start = DateTime.Now; while (!solvedPuzzleVM.Solved && AmountOfCheckedSolutions <= AmountOfTotalSolutions) { foreach (var tile in Initiator.TileList) { if (UsedTileList.Count == puzzleVM.PuzzleTileList.Count) { AmountOfCheckedSolutions++; FillPuzzleRoads(UsedTileList); if (DoesDefinitiveRoadListSolvePuzzle(simpleConditionsList)) { solvedPuzzleVM.Solved = true; break; } else { UsedTileList.Clear(); } //break; } var tileIsUsed = false; var tempTileRotationList = new List <Tile> { tile }; tempTileRotationList.AddRange(tile.TileRotationList); foreach (var rotatedTile in tempTileRotationList) { if (UsedTileList.Count == puzzleVM.PuzzleTileList.Count) { FillPuzzleRoads(UsedTileList); if (DoesDefinitiveRoadListSolvePuzzle(simpleConditionsList)) { solvedPuzzleVM.Solved = true; break; } } foreach (var puzzleTile in puzzleVM.PuzzleTileList) { if (UsedTileList.Any(s => s.PuzzleIndex == puzzleTile.Index)) { continue; } if (UsedTileList.Count == puzzleVM.PuzzleTileList.Count) { FillPuzzleRoads(UsedTileList); if (DoesDefinitiveRoadListSolvePuzzle(simpleConditionsList)) { solvedPuzzleVM.Solved = true; break; } } rotatedTile.PuzzleIndex = puzzleTile.Index; UsedTileList.Add(rotatedTile); var tileKey = new UsedTileDictionaryKey(puzzleTile.Index, rotatedTile.TileNumber, rotatedTile.Degrees); CheckedTileDictionary[tileKey]++; tileIsUsed = true; break; } if (tileIsUsed) { break; } } if (tileIsUsed) { continue; } } } var end = DateTime.Now; solvedPuzzleVM.SolveDuration = (end - start); solvedPuzzleVM.AmountOfCheckedSolutions = AmountOfCheckedSolutions; solvedPuzzleVM.AmountOfTotalSolutions = AmountOfTotalSolutions; solvedPuzzleVM.TileSet = UsedTileList.ToDictionary(s => s.PuzzleIndex); return(solvedPuzzleVM); }