public void UnknownWordConstructorTest() { var text = "qmilgestroph"; var target = new UnknownWord(text); Check.That(target.Text).IsEqualTo(text); }
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 CtorHappyPathTest(string pattern, string expectedWordPattern, int expectedUnknownCharCnt) { var subject = new UnknownWord(pattern); Assert.That(subject.WordPattern, Is.EqualTo(expectedWordPattern), "unexpected value for WordPattern property"); Assert.That(subject.UnknownCharCount, Is.EqualTo(expectedUnknownCharCnt), "unexpected value for UnknownCharCount property"); }
private static IEnumerable <TestCaseData> _CrosswordData() { { var knownWords = new KnownWords(new[] { "one", "two", "ane", "ene", "ine" }); var unknownWord = new UnknownWord("?ne"); int[] subWordCount = null; var expectedWord = "one"; yield return(new TestCaseData(knownWords, unknownWord, subWordCount, expectedWord) .SetName("word: something")); } { var knownWords = new KnownWords(new[] { "one", "two", "ane", "ene", "ine" }); var unknownWord = new UnknownWord("?net??"); int[] subWordCount = { 3, 3 }; var expectedWord = "one two"; yield return(new TestCaseData(knownWords, unknownWord, subWordCount, expectedWord) .SetName("word: one two")); } { var knownWords = new KnownWords(new[] { "teen", "ween", "town", "then" }); var unknownWord = new UnknownWord("t??n"); int[] subWordCount = null; var expectedWord = "teen"; yield return(new TestCaseData(knownWords, unknownWord, subWordCount, expectedWord) .SetName("word: teen")); } }
public void SolveTest(KnownWords knownWords, UnknownWord unknownWord, int[] subWordCount, string expectedWord) { var crossword = new CrosswordPuzzle(knownWords); var solutions = crossword.Solve(unknownWord, subWordCount); Assert.That(solutions, Has.Member(expectedWord), "expected word was not in the list of solutions"); }
public void SubWordCountHappyPath() { var pattern = "oneTWOthree"; var subject = new UnknownWord(pattern); var subWordCounts = new[] { 3, 3, 5 }; subject.SetSubWordCounts(subWordCounts); Assert.That(subject.SubWordCounts, Is.EquivalentTo(subWordCounts), "sub word array not expected"); }
public void FillInUnknownTooManyLetters() { var pattern = "??"; var subject = new UnknownWord(pattern); var letters = new[] { 'x', 'y', 'z' }; var ex = Assert.Throws <ArgumentException>(() => subject.FillInUnknown(letters)); Assert.That(ex.Message, Is.EqualTo($"You provided {letters.Length} letters but the unknown characters are {pattern.Length}. These 2 counts must be the same.")); }
private static UnknownWord _ReadUnknownWord() { var wordPattern = _ReadLn(); if (string.IsNullOrWhiteSpace(wordPattern)) { throw new PrintToConsoleException("That word pattern looks a bit brief, don't think you're solving this puzzle..."); } var unknownPattern = new UnknownWord(wordPattern); return(unknownPattern); }
public void SubWordCountTooLong() { var pattern = "oneTWOthree"; var subject = new UnknownWord(pattern); var subWordCounts = new[] { 12 }; var wordPatternLength = 11; Assert.That(subject.WordPattern.Length, Is.EqualTo(wordPatternLength), "precondition: the length of the WordPattern"); Assert.That(subWordCounts.Sum(), Is.GreaterThan(wordPatternLength), "precondition: the subWordCounts about to be applied add up to more than the length of word pattern"); var ex = Assert.Throws <ArgumentException>(() => subject.SetSubWordCounts(subWordCounts)); Assert.That(ex.Message, Is.EqualTo("Summing all the word counts is " + subWordCounts.Sum() + " but unknown word has " + wordPatternLength + " letters.")); }
public void FillInUnknownHappyPath(string pattern, int[] subWords, char[] letters, string[] expectedWords) { var subject = new UnknownWord(pattern); if (subWords != null) { subject.SetSubWordCounts(subWords); } var words = subject.FillInUnknown(letters); Assert.That(words, Is.EquivalentTo(expectedWords), "FillInUnknown did not produce the expected words"); }
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()); }
/// <summary> /// Solves a "word slide" type puzzle, some apps call this "quote slide" or something similar. This type of puzzle is where you /// fill in the blank words in a phrase by sliding individual characters down to make up the words in the phrase, with words /// stacked on top of each other so there are multiple characters possible for each slot in a word. /// </summary> /// <param name="pattern"></param> /// <param name="availableLetters"></param> /// <returns></returns> public IEnumerable <string> Solve(string pattern, char[][] availableLetters) { if (pattern == null) { throw new ArgumentNullException(nameof(pattern)); } if (availableLetters == null) { throw new ArgumentNullException(nameof(availableLetters)); } var unknownWord = new UnknownWord(pattern); var wordLen = unknownWord.WordPattern.Length; if (wordLen != availableLetters.Length) { throw new ArgumentException($"The partial word had a length of {wordLen} but the available letters only had {availableLetters.Length} slots."); } var matches = _WordSlideSearch(KnownWords, unknownWord, availableLetters); return(matches); }
/// <summary> /// Builds an index based on char position and set of possible chars for that position /// </summary> /// <param name="partialWordOrLength"></param> /// <param name="availableLetters"></param> /// <returns></returns> private static HashSet <char>[] _FillInSearchLettersFromPartialWord( UnknownWord partialWordOrLength, char[][] availableLetters ) { var searchLetters = new HashSet <char> [availableLetters.Length]; for (var i = 0; i < availableLetters.Length; i++) { var c = partialWordOrLength.WordPattern[i]; if (c == UnknownWord.UnknownToken) { searchLetters[i] = new HashSet <char>(availableLetters[i]); } else { searchLetters[i] = new HashSet <char>(new[] { c }); } } return(searchLetters); }