private static IEnumerable <string> _WordSlideSearch(KnownWords knownWords, UnknownWord unknownWord, char[][] availableLetters) { if (_AllUnknownWordLengthsReasonable(knownWords, unknownWord) == false) { return(new HashSet <string>()); } availableLetters = _EnsureAllLower(availableLetters); var searchLetters = _FillInSearchLettersFromPartialWord(unknownWord, availableLetters); var wordLen = unknownWord.WordPattern.Length; var possibleWords = knownWords.AllWordsOfLength(wordLen); var matches = new List <string>(); foreach (var word in possibleWords) { if (_IsPossibleMatch(searchLetters, word)) { matches.Add(word); } } matches = matches.OrderBy(w => w).ToList(); return(matches); }
public void AllWordsOfLengthTest(string[] allWords, int wordLen, string[] expected) { var knownWords = new KnownWords(allWords); var unsortedActual = knownWords.AllWordsOfLength(wordLen); var actual = unsortedActual.OrderBy(s => s); Assert.That(actual, Is.EquivalentTo(expected)); }
public void AllWordsOfLengthThrowsForZeroLength() { var allWords = new[] { string.Empty, "aa", "bb", "aaa", "bbb", "1234" }; var knownWords = new KnownWords(allWords); var ex = Assert.Throws <ArgumentException>(() => knownWords.AllWordsOfLength(0)); Assert.That(ex.Message, Is.EqualTo("A known word must have at least 1 character")); }
public IEnumerable <string> Solve(UnknownWord unknownWord, int[] subWordCount) { // call SetSubWordCounts just for the validation it does unknownWord.SetSubWordCounts(subWordCount); string[] wordsToSolve = { unknownWord.WordPattern }; if (subWordCount != null) { wordsToSolve = new string[subWordCount.Length]; var pattern = unknownWord.WordPattern; var currentIdx = 0; for (var i = 0; i < subWordCount.Length; i++) { var wordCount = subWordCount[i]; var subWord = pattern.Substring(currentIdx, wordCount); wordsToSolve[i] = subWord; currentIdx += wordCount; } } else { subWordCount = new [] { unknownWord.WordPattern.Length }; } var matches = new List <string> [wordsToSolve.Length]; for (var i = 0; i < matches.Length; i++) { var allWordsOfLen = KnownWords.AllWordsOfLength(subWordCount[i]); matches[i] = new List <string>(); foreach (var word in allWordsOfLen) { if (_IsMatch(wordsToSolve[i], word)) { matches[i].Add(word); } } } foreach (var wordList in matches) { wordList.Sort(); } var allPossiblePhrases = Permutations.CartesianProduct(matches); var formattedPhrases = allPossiblePhrases.Select(phrase => string.Join(" ", phrase)); return(formattedPhrases.ToList()); }
private static bool _AllUnknownWordLengthsReasonable(KnownWords knownWords, UnknownWord unknownWord) { // TODO: if i ever get around to implementing subwords this fancier check will be needed. //if (unknownWord.SubWordCounts == null || unknownWord.SubWordCounts.Any() == false) //{ // if (knownWords.AllWordsOfLength(unknownWord.WordPattern.Length).Count == 0) // { // return false; // } //} //else //{ // if (unknownWord.SubWordCounts.Any(cnt => knownWords.AllWordsOfLength(cnt).Count == 0)) // { // return false; // } //} return(knownWords.AllWordsOfLength(unknownWord.WordPattern.Length).Any()); }
public void SolveNullSubWordAvailableLetterMismatch() { var knownWord = "four"; var knownWords = new KnownWords(new [] { knownWord }); //var unknownWord = new UnknownWord(new string(UnknownWord.UnknownToken, knownWord.Length + 1)); var wordPattern = new string(UnknownWord.UnknownToken, knownWord.Length + 1); Assert.That(knownWords.AllWordsOfLength(wordPattern.Length), Is.Empty, "precondition: there is no known word the length of the unknown word"); //Assert.That(unknownWord.SubWordCounts, Is.Null, "precondition: unknownWord.SubWordCounts must be null"); var puzzle = new WordSlidePuzzle(knownWords); var availableLetters = new char[wordPattern.Length][]; for (var i = 0; i < availableLetters.Length; i++) { availableLetters[i] = new[] { 'X' }; } var solutions = puzzle.Solve(wordPattern, availableLetters); Assert.That(solutions, Is.Empty, "If there are no known words of the required length the solution should be empty"); }
public IEnumerable <string> Solve(string originalWord) { var letters = originalWord.ToAlphabetArray(); if (letters.Any(c => c == UnknownWord.UnknownToken)) { throw new ArgumentException("There cannot be any unknown characters in the word to find its anagrams."); } var cleanedWord = new string(letters); if (letters.Length < 2) { throw new ArgumentException("You cannot create an anagram of a word unless there are at least 2 letters"); } var matches = new List <string>(); var sortedArr = _AllLettersSorted(cleanedWord); foreach (var potential in KnownWords.AllWordsOfLength(cleanedWord.Length)) { if (string.Equals(cleanedWord, potential)) { continue; } var potentialArr = _AllLettersSorted(potential); if (sortedArr.SequenceEqual(potentialArr)) { matches.Add(potential); } } matches = matches.OrderBy(w => w).ToList(); return(matches); }