private uint DoExtraSearch(SolverParam param) { uint walk = 0; Random rnd = new Random(); Stroke stroke = puzzleData; int nbVerses = stroke.Verses.Count; Stack <int> proposal = new Stack <int>(), candidate = new Stack <int>(Enumerable.Reverse(Enumerable.Range(0, nbVerses))); List <Verse> result = new List <Verse>(); List <int>[] visited = new List <int> [nbVerses]; for (int vv = 0; vv < nbVerses; ++vv) { visited[vv] = new List <int>(); } while (candidate.Count > 0) { int curIdx = candidate.Pop(); List <int> curVisisted = visited[curIdx]; // Existing verses construct the constraints. List <int[]> constraints = stroke.Anchors; int requiredLength = stroke.Verses[curIdx].Length; bool foundOne = true; // Look up in the data. int s = 0; Verse v = new Verse(); if (stroke.Verses[curIdx].Content[0] != 0xFF) { // Fixed verse. s = dictDataMatrices[requiredLength].FindIndex( (x) => { bool found = true; for (int i = 0; i < requiredLength; ++i) { if (x[i] != stroke.Verses[curIdx].Content[i]) { found = false; break; } } return(found); }); } else { // Variant verse. for (s = 0; s < dictDataMatrices[requiredLength].Count; ++s) { if (param.MaxStep > 0 && walk > param.MaxStep) { return(walk); } // Prevent replicate verses. foundOne = true; if (usedIndices[requiredLength].Contains(s) || curVisisted.Contains(s)) { foundOne = false; continue; } ++walk; ushort[] content = dictDataMatrices[requiredLength][s]; foreach (int[] a in constraints) { if (a[4] == 0xFF) { // Variant anchor. if (proposal.Contains(a[0]) && curIdx == a[2]) { ushort trait = content[a[3]], check = result[a[0]].Content[a[1]]; if (trait != check) { foundOne = false; break; } } } else { // Fixed anchor. if (a[0] == curIdx && content[a[1]] != a[4]) { foundOne = false; break; } if (a[2] == curIdx && content[a[3]] != a[4]) { foundOne = false; break; } } // For each search, check the constraints. } if (foundOne) { break; } } } if (foundOne) { // Next step. curVisisted.Add(s); v.Length = requiredLength; v.Content = dictDataMatrices[requiredLength][s]; result.Add(v); proposal.Push(curIdx); } else { // Trace back. curVisisted.Clear(); result.RemoveAt(result.Count - 1); int lastIdx = proposal.Pop(); candidate.Push(curIdx); candidate.Push(lastIdx); } } // Get result. stroke.Verses = result; for (int i = 0; i < nbVerses; ++i) { int requiredLength = stroke.Verses[i].Length; int usedIdx = visited[i][visited[i].Count - 1]; if (!param.Reuse) { usedIndices[requiredLength].Add(usedIdx); } } stroke.IsCompleted = true; return(walk); }
public void ClearPuzzleData() { puzzleData = null; }