Files
letter-words/Core/DictionarySearcher.cs

146 lines
5.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using C5;
namespace Core
{
public class DictionarySearcher
{
static HashBag<char> GetLettersBag(string letters)
{
var hashBag = new HashBag<char>();
hashBag.AddAll(letters.Canonicalize().ToCharArray());
return hashBag;
}
readonly struct DictWord
{
public readonly string Word;
public readonly HashBag<char> 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<DictWord>
{
private readonly IComparer<string> _comparer;
public DictWordComprer(IComparer<string> comparer)
{
_comparer = comparer;
}
public int Compare(DictWord x, DictWord y)
{
return _comparer.Compare(x, y);
}
}
private readonly List<DictWord> _dictionary;
public DictionarySearcher(int? characterCount = null)
: this(@"TWL06.txt", characterCount)
{
}
public DictionarySearcher(string filename, int? characterCount = null)
: this(filename.GetFileLines(), characterCount)
{
}
public DictionarySearcher(IEnumerable<string> words, int? characterCount = null)
{
_dictionary = new List<DictWord>();
foreach (var word in words)
{
if (characterCount != null && word.Length != characterCount)
continue;
var w = word.Canonicalize();
_dictionary.Add(w);
}
}
public System.Collections.Generic.IList<string> GetWords()
{
return _dictionary.Select(d => d.Word).ToList();
}
public void SortDictionary(IComparer<string> comparer)
{
_dictionary.Sort(new DictWordComprer(comparer));
}
public IEnumerable<string> FindWords(string letters)
{
var hashBag = new HashBag<char>();
hashBag.AddAll(letters.Canonicalize().ToCharArray());
return from w in _dictionary
where hashBag.ContainsAll(w.ToCharArray())
select w.Word;
}
public IEnumerable<string> 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<string> 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<Tuple<string, string>> 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<char, int>[] GetLetterPositionFreq(int wordLen)
{
var ws = _dictionary.Where(w => w.Length == wordLen).ToList();
var freqList = new Dictionary<char, int>[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;
}*/
}
}