private static List <string> SampleMatchingWords(WordRegexMatches wordRegexMatches) { byte[] wordMatches = wordRegexMatches.wordMatches; int[] countsByRegex = wordRegexMatches.countsByRegex; string[] selectedWords = new string[countsByRegex.Length]; // Examine regexes in order of increasing number of matching words List <int> remainingRegexIndices = Enumerable.Range(0, countsByRegex.Length) .OrderBy(regexIndex => countsByRegex[regexIndex]).ToList(); byte satisfiedRegexFlags = 0; while (remainingRegexIndices.Count > 0) { int? matchedRegexIndex = null; List <int> wordIndexChoices = new List <int>(); foreach (int ri in remainingRegexIndices) { for (int wi = 0; wi < ALL_WORDS.Length; wi++) { byte wm = wordMatches[wi]; byte regexFlag = (byte)(1 << ri); // If wm matches this regex, and any other matches in wm overlap only // with previously-matched regexes, then we found a new match bool matchesThisRegex = (wm & regexFlag) != 0; bool matchesOtherUnsatisfiedRegexes = (wm & ~regexFlag & ~satisfiedRegexFlags) != 0; if (matchesThisRegex && !matchesOtherUnsatisfiedRegexes) { matchedRegexIndex = ri; wordIndexChoices.Add(wi); } } // Only accept choices from a single regex if (matchedRegexIndex != null) { break; } } if (matchedRegexIndex == null) { // This should never happen! throw new System.Exception("No solution found for regexes!"); } else { satisfiedRegexFlags |= (byte)(1 << matchedRegexIndex.Value); remainingRegexIndices.Remove(matchedRegexIndex.Value); selectedWords[matchedRegexIndex.Value] = ALL_WORDS[wordIndexChoices.PickRandom()]; } } return(selectedWords.ToList()); }
public static Puzzle SamplePuzzle(int rowNorth, int rowSouth, int colWest, int colEast) { // NW, NE, SE, SW RegexData[] regexData = new RegexData[] { RegexDataAtTablePos(rowNorth, colWest), RegexDataAtTablePos(rowNorth, colEast), RegexDataAtTablePos(rowSouth, colEast), RegexDataAtTablePos(rowSouth, colWest), }; WordRegexMatches wordRegexMatches = ComputeWordRegexMatches(regexData); List <string> matchingWords = SampleMatchingWords(wordRegexMatches); List <string> decoyWords = SampleDecoyWords(regexData); return(new Puzzle(regexData.ToList(), matchingWords, decoyWords)); }