using System; using System.Collections.Generic; using System.Linq; using C5; namespace Core { public class DictionarySearcher { static HashBag GetLettersBag(string letters) { var hashBag = new HashBag(); hashBag.AddAll(letters.Canonicalize().ToCharArray()); return hashBag; } readonly struct DictWord { public readonly string Word; public readonly HashBag CharBag; public DictWord(string word) : this() { Word = word; CharBag = GetLettersBag(word); } public static implicit operator DictWord(string s) => new DictWord(s); public static implicit operator string(DictWord dw) => dw.Word; public char[] ToCharArray() => Word.ToCharArray(); public bool Contains(char c) => Word.Contains(c); public int Length => Word.Length; public bool StartsWith(string s) => Word.StartsWith(s); public string Substring(int startIndex) => Word.Substring(startIndex); } private class DictWordComprer : IComparer { private readonly IComparer _comparer; public DictWordComprer(IComparer comparer) { _comparer = comparer; } public int Compare(DictWord x, DictWord y) { return _comparer.Compare(x, y); } } private readonly List _dictionary; public DictionarySearcher(int? characterCount = null) : this(@"TWL06.txt", characterCount) { } public DictionarySearcher(string filename, int? characterCount = null) : this(filename.GetFileLines(), characterCount) { } public DictionarySearcher(IEnumerable words, int? characterCount = null) { _dictionary = new List(); foreach (var word in words) { if (characterCount != null && word.Length != characterCount) continue; var w = word.Canonicalize(); _dictionary.Add(w); } } public System.Collections.Generic.IList GetWords() { return _dictionary.Select(d => d.Word).ToList(); } public void SortDictionary(IComparer comparer) { _dictionary.Sort(new DictWordComprer(comparer)); } public IEnumerable FindWords(string letters) { var hashBag = new HashBag(); hashBag.AddAll(letters.Canonicalize().ToCharArray()); return from w in _dictionary where hashBag.ContainsAll(w.ToCharArray()) select w.Word; } public IEnumerable FindWords(string includeLetters, string excludeLetters) { var excludeBag = GetLettersBag(excludeLetters); return from w in _dictionary where w.CharBag.ContainsAll(includeLetters.Canonicalize()) && excludeBag.All(c => !w.Contains(c)) select w.Word; } public IEnumerable FindWords(string includeLetters, string excludeLetters, int? len) { return from w in FindWords(includeLetters, excludeLetters) where !len.HasValue || w.Length == len.Value select w; } public IEnumerable> MatchingWords(string firstSelector, string secondSelector) { var firstSet = _dictionary.Where(w => w.StartsWith(firstSelector.Canonicalize())).GroupBy(w => w.Length) .ToList(); var secondSet = _dictionary.Where(w => w.StartsWith(secondSelector.Canonicalize())).GroupBy(w => w.Length) .ToList(); return from len in firstSet.Select(g => g.Key) from w1 in firstSet.Where(g => g.Key == len) from w2 in secondSet.Where(g => g.Key == len) from ww1 in w1 from ww2 in w2 where ww1.Substring(1).Equals(ww2.Substring(1)) select Tuple.Create(ww1.Word, ww2.Word); } /*public Dictionary[] GetLetterPositionFreq(int wordLen) { var ws = _dictionary.Where(w => w.Length == wordLen).ToList(); var freqList = new Dictionary[wordLen]; for (var i = 0; i < wordLen; i++) { var letters = Enumerable.Range(0, 26).Select(r => Convert.ToChar('A' + r)); freqList[i] = letters.ToDictionary(c => c, c => ws.Count(w => w.Word[i] == c) ); } return freqList; }*/ } }