e45d2a57de8341b601c70ba3eeb9761acffed3c2
Dev Ghai Removing byte order mark us...

Dev Ghai authored 11 years ago

1) using System;
Dev Ghai Revert "Removing byte order...

Dev Ghai authored 11 years ago

2) using System.Collections.Generic;
3) using System.IO;
4) 
5) namespace Boggle
6) {
7)     /// <summary>
8)     /// Supported lists.
9)     /// </summary>
10)     public enum BoggleLists
11)     {
12)         /// <summary>
13)         /// Scrabble dictionary for USA, Canada and Thailand
14)         /// </summary>
15)         TWS,
16) 
17)         /// <summary>
18)         /// Scrabble dictionary used world wide except in USA, Canada and Thailand.
19)         /// </summary>
20)         //SOWPODS,
21) 
22)         /// <summary>
23)         /// A huge dictionary found on official Internet Scrabble Club's website (http://www.isc.ro/en/commands/lists.html)
24)         /// </summary>
25)         ZINGARELLI
26)     }
27) 
28)     public class BoggleList
29)     {
30)         /// <summary>
31)         /// Contains a hybrid tree that has been optimized for recursive search.
32)         /// </summary>
33)         private Dictionary<string, ListWord> _WordList = new Dictionary<string, ListWord>(27); //top level will store only 3 letter words or substrings. Declaring proper size makes insertion operation O(1)
34)         public Dictionary<string, ListWord> Wordlist
35)         {
36)             get
37)             {
38)                 return _WordList;
39)             }
40)         }
41) 
42)         /// <summary>
43)         /// Contains a list of dictionaries that have been loaded, indexed by enum that contains dictionaries we support.
44)         /// </summary>
45)         private Dictionary<BoggleLists, Dictionary<string, ListWord>> _LoadedDictionaries;
46) 
47)         /// <summary>
48)         /// Determines if we have an absolute path
49)         /// </summary>
50)         /// <param name="filePath">File that contains the list SORTED list of words. Path can be relative or absolute.</param>
51)         /// <returns>The absolute file path that we can use to access it.</returns>
52)         private string GetAbsoluteFilePath(string filePath)
53)         {
54)             //check if the absolute file path exists.            
55)             if (!File.Exists(filePath))
56)             {
57)                 //try checking if this is a relative file path and prepend current directory's path.
58)                 filePath = string.Format("{0}\\{1}", Directory.GetCurrentDirectory(), filePath);
59)                 if (!File.Exists(filePath))
60)                 {
61)                     filePath = string.Empty;
62)                 }
63)             }
64) 
65)             return filePath;
66)         }
67) 
68)         /// <summary>
69)         /// Curates the list for use by this solver. Basically culls out words that do not meet the criteria.
70)         /// Criteria: Min_word_length < word_length < Max_word_length. Max_word_length = sideLength^2 + 1.
71)         /// </summary>
72)         /// <param name="filePath"> Path to file that contains the SORTED list of words. 
73)         ///                         It can be relative to current execution directory or absolute.</param>
74)         /// <param name="boardSideLength">Length of the side of board in number of tiles.</param>
75)         /// <param name="minWordLength">Number of alphabets that can be there in the shortest word on the board.</param>
76)         private void CurateList(string filePath, int boardSideLength, int minWordLength)
77)         {
78)             //filePath = GetAbsoluteFilePath(filePath);
79)             //true tells stream reader to auto detect encoding of the file.
80)             StreamReader rawList = new StreamReader(filePath, true);
81)             //Create a new file. Do not append anything.
82)             string curatedFilePath = string.Format("{0}.{1}.{2}", filePath, Constants.CURATED_FILE_SUFFIX, minWordLength.ToString());
83)             StreamWriter curatedList = new StreamWriter(curatedFilePath, false);
84) 
85)             string word;
86)             //write out the words whose number of characters are between the shortest and largest provided length.
87)             while ((word = rawList.ReadLine()) != null)
88)             {
89)                 if (word.Length >= minWordLength && word.Length <= boardSideLength * boardSideLength + 1)
90)                 {
91)                     curatedList.WriteLine(word);
92)                 }
93)             }
94) 
95)             curatedList.Flush();
96)             curatedList.Close();
97)             rawList.Close();
98)         }
99) 
100)         public BoggleList()
101)         {
102)             //Initialize the dictionary containing the lists.
103)             _LoadedDictionaries = new Dictionary<BoggleLists, Dictionary<string, ListWord>>(Enum.GetNames(typeof(BoggleLists)).Length);
104)         }
105) 
106)         /// <summary>
107)         /// Loads the list depending on the selected dictionary.
108)         /// </summary>
109)         /// <param name="dict">Type of dictionary to load.</param>
110)         /// <param name="boardSideLength"></param>
111)         /// <param name="minWordLength"></param>
112)         /// <returns>A hybird tree containing the words with each level containing one alphabet (or QU)</returns>
113)         public Dictionary<string, ListWord> LoadList(BoggleLists dict, int boardSideLength, int minWordLength, string listRootPath)
114)         {
115)             if (_LoadedDictionaries.ContainsKey(dict))
116)                 return _LoadedDictionaries[dict];
117) 
118)             string filePath = string.Empty;
119) 
120)             if (NeedsCuration(dict, minWordLength, listRootPath, ref filePath))
121)                 CurateList(filePath, boardSideLength, minWordLength);
122) 
123)             _WordList = new Dictionary<string, ListWord>(27);
124) 
125)             //true tells stream reader to auto detect encoding of the file.
126)             StreamReader rawList = new StreamReader(filePath, true);
127)             string word, substring;
128)             ListWord prevListWord;
129)             int startIndex;
Dev Ghai Removed an old artifact tha...

Dev Ghai authored 11 years ago

130)             int maxWordLength = boardSideLength * boardSideLength + 1;
Dev Ghai Revert "Removing byte order...

Dev Ghai authored 11 years ago

131)             while ((word = rawList.ReadLine()) != null)
Dev Ghai Removed an old artifact tha...

Dev Ghai authored 11 years ago

132)             {
133)                 //ignore the word if it cannot logically exist on the board.
134)                 if (word.Length < minWordLength || word.Length > maxWordLength)
135)                     continue;
136) 
Dev Ghai Revert "Removing byte order...

Dev Ghai authored 11 years ago

137)                 //First deal with the head node and then deal with following letters.
138)                 startIndex = 0;
139)                 word = word.ToUpper();
140)                 substring = word.Substring(0, 1);
141)                 //if the string starts with Q and there is a 'U' following it, then put QU on tile and increment starting index accordingly.
142)                 if (substring == "Q" && word[1] == 'U')
143)                 {
144)                     substring += "U";
145)                     startIndex++;
146)                 }
147) 
148)                 //If there is no space allocated for this letter at root level, allocate some.
149)                 if (!_WordList.ContainsKey(substring))
150)                 {
151)                     _WordList.Add(substring, new ListWord());
152)                 }
153)                 prevListWord = _WordList[substring];
154) 
155)                 //fit the word in the tree structure
156)                 for (int i = startIndex + 1; i < word.Length; i++)
157)                 {
158)                     //We are dealing with one letter at each level
159)                     substring = word.Substring(i, 1);
160)                     //But if the letter is Q and there is a U following it, then treat this as one letter.
161)                     if (substring == "Q" && i + 1 < word.Length && word[i + 1] == 'U')
162)                     {
163)                         substring += "U";
164)                         //also increment the index as we have consumed the next letter.
165)                         i++;
166)                     }
167)                     //Has this combination of letters appeared before?
168)                     if (prevListWord.Next == null)
169)                     {
170)                         //if not, then make some space to store this combination
171)                         prevListWord.Next = new Dictionary<string, ListWord>(27);
172)                         //and store it.
173)                         prevListWord.Next.Add(substring, new ListWord());
174)                     }
175)                     //if it has,
176)                     else if (!prevListWord.Next.ContainsKey(substring))
177)                     {
178)                         //then just store it.
179)                         prevListWord.Next.Add(substring, new ListWord());
180)                     }
181) 
182)                     //Update the dictionary to point to current substring's last character/entry in the tree.
183)                     prevListWord = prevListWord.Next[substring];
184)                 }
185)                 //set the value of the leaf node to be true to point that we have completed the word.
186)                 prevListWord.IsWord = true;
187)             }
188) 
189)             //Store it in the collection 
190)             _LoadedDictionaries.Add(dict, _WordList);
191)             return _WordList;
Dev Ghai Removed an old artifact tha...

Dev Ghai authored 11 years ago

192)         }
193) 
194)         private void SaveDictToDisk(Dictionary<string, ListWord> hierarchicalDict, string filename)
195)         {
196)         }
197) 
198)         private Dictionary<string, ListWord> LoadDictFromDisk(string filename)
199)         {
200)         }
201) 
202)         private bool DictExistsOnDisk(string filename)
203)         {
204)         }
205) 
206)         private string DictFilenameOnDisk(int boardSideLength, int minWordLength)
207)         {