Advertisement
Guest User

Untitled

a guest
Feb 18th, 2020
117
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.97 KB | None | 0 0
  1. package predictive;
  2.  
  3. import java.io.File;
  4. import java.io.FileNotFoundException;
  5. import java.io.IOException;
  6. import java.util.HashSet;
  7. import java.util.Scanner;
  8. import java.util.Set;
  9. /**
  10. * TreeDictionary is a Tree with 8 branches each representing a number from a signature of a word.
  11. * as you progress through the tree the node will store complete words for which the subsignature created by the path of branches is a match for.
  12. * @author Henry
  13. *
  14. */
  15. public class TreeDictionary implements Dictionary {
  16.  
  17. private Set<String> nodeList;
  18. private String nodeSig;
  19. private TreeDictionary[] children;
  20.  
  21. public static void main(String[] args) throws IOException {
  22. TreeDictionary dict = new TreeDictionary("C:\\Users\\henry\\Desktop\\Programs\\WS3\\src\\words");
  23. System.out.println(dict.findSigNode("4663"));
  24. }
  25.  
  26. /**
  27. * TreeDictionary(String path) is the constructor which should be called upon to create your Tree dictionary
  28. * it will initizalise the starting node which has every valid word attached to it and then create the first 8 branches of the tree
  29. * using a different constructor.
  30. * @param path, a file path to a dictionary of words.
  31. */
  32. public TreeDictionary(String path) {
  33. this.nodeList = new HashSet<String>(); // our starting node is initialized as empty set
  34. try{
  35. File words = new File(path);
  36. Scanner scan = new Scanner(words);
  37. while(scan.hasNextLine()) { // loops whenever there is a next line
  38. String line = scan.nextLine().toLowerCase(); // initialise a String of the next line in lower case
  39. if(isValidWord(line)) {
  40. nodeList.add(line); // adds every valid word to the set
  41. }
  42. }
  43. scan.close();
  44. } catch (FileNotFoundException exception) { // exception when the dictionary cannot be found
  45. System.out.println("File Not Found");
  46. }
  47. this.nodeSig = ""; // first node signature is empty
  48. String empty = ""; // creates empty string to be the first nodes signature
  49. TreeDictionary[] childs = {new TreeDictionary(empty, "2", nodeList), // uses our next constructor to make the array of children for the first node.
  50. new TreeDictionary(empty, "3", nodeList),
  51. new TreeDictionary(empty, "4", nodeList),
  52. new TreeDictionary(empty, "5", nodeList),
  53. new TreeDictionary(empty, "6", nodeList),
  54. new TreeDictionary(empty, "7", nodeList),
  55. new TreeDictionary(empty, "8", nodeList),
  56. new TreeDictionary(empty, "9", nodeList)};
  57. this.children = childs; // sets this array to be the children of our starting node
  58. }
  59. /**
  60. * TreeDictionary(String prevNodeSig, String childSig, Set<String> prevNodeList) is a constructor which is called by our initial constructor
  61. * in which we narrow down our Set of words for each child without having to rescan the file.
  62. * @param prevNodeSig The signature of the previous node
  63. * @param childSig The number of child we are on from 2-9
  64. * @param prevNodeList The list of words from the parent node which we narrow down depending on the new part of our signature
  65. */
  66. public TreeDictionary(String prevNodeSig, String childSig, Set<String> prevNodeList) {
  67. this.nodeSig = prevNodeSig + childSig; // sets the node of the signature to be the previous plus the number of the child we are on.
  68. Set<String> newNodeList = new HashSet<>(); // initializes this nodes Set of words as empty
  69. for(String s : prevNodeList) {
  70. if(wordToSignature(s).startsWith(this.nodeSig)) // for each word in the previous list we add to the new list if our new subsignature matches it.
  71. newNodeList.add(s);
  72. }
  73. this.nodeList = newNodeList; // sets this new list as the nodes nodeList
  74. if(newNodeList.size() > 0) { // if this list is non empty we create its children recursively using this constructor.
  75. TreeDictionary[] childs = {new TreeDictionary(this.nodeSig, "2", this.nodeList),
  76. new TreeDictionary(this.nodeSig, "3", this.nodeList),
  77. new TreeDictionary(this.nodeSig, "4", this.nodeList),
  78. new TreeDictionary(this.nodeSig, "5", this.nodeList),
  79. new TreeDictionary(this.nodeSig, "6", this.nodeList),
  80. new TreeDictionary(this.nodeSig, "7", this.nodeList),
  81. new TreeDictionary(this.nodeSig, "8", this.nodeList),
  82. new TreeDictionary(this.nodeSig, "9", this.nodeList),
  83. };
  84.  
  85. this.children=childs; // sets the child array to be this nodes children
  86. }
  87.  
  88. }
  89. /**
  90. * getter for nodeList
  91. * @return this.nodeList
  92. */
  93. public Set<String> getNodeList() {
  94. return nodeList;
  95. }
  96. /**
  97. * getter for nodeSig
  98. * @return this.nodeSig
  99. */
  100. public String getNodeSig() {
  101. return nodeSig;
  102. }
  103. /**
  104. * getter for child i, we use 2-9 to simplify this class and will minus 2 to make it match the childs position in the array
  105. * @param i, name of child from 2-9
  106. * @return child i
  107. * @throws IOException if i is out of bounds
  108. */
  109. public TreeDictionary getChildI(int i) throws IOException{
  110. return children[i-2]; // matches the child's signature number from 2-9 to its position in the array 0-7
  111. }
  112. /**
  113. * signatureToWords will get a Set of Strings which match our signatures by using helper method findSigNode and getting the nodeList of the found node. Then it will return these words in a set with each word
  114. * trimmed to be the same length of the input signature.
  115. * @param signature, a numeric String signature you wish to find
  116. * @return a Set<String> of a set of substrings or strings of all words which have matching subsignatures or a matching signatures to the input signature.
  117. * @throws IOException if no matches are found
  118. */
  119. public Set<String> signatureToWords(String signature) {
  120. if(signature.length()>0) { // stops the inital node from returning every word in our TreeDictionary
  121. try {
  122. Set<String> words = new HashSet<>(); // initialize empty set
  123. for(String s : findSigNode(signature).getNodeList()) { // for each String in our nodeList
  124. if (s.length() == signature.length())
  125. words.add(s); // we add the whole String if it is of the correct length
  126. else
  127. words.add(s.substring(0, signature.length())); // else we add a substring of the word if of matching length to signature if it the String is longer than our input signature.
  128. }
  129. return words; // returns this Set of words
  130. } catch (IOException e) {
  131. System.out.println("no words found"); // catches exception if no matching words are found
  132. }
  133. }
  134. return null;
  135. }
  136. /**
  137. * findSigNode will recursively search through a TreeDictionary and return the node at which the input signature matches the signature of a node.
  138. * @param signature, signature you wish to find
  139. * @return a TreeDictionary, typically a sub TreeDictionary
  140. * @throws IOException
  141. */
  142. public TreeDictionary findSigNode(String signature) throws IOException {
  143. if (signature.length()==1) { // if the input signature is only of length 1 we return that child.
  144. return this.getChildI(Character.getNumericValue(signature.charAt(0)));
  145. }
  146. else{
  147. try {
  148. int startSig = Character.getNumericValue(signature.charAt(0)); // converts the first number in our signature to an int
  149. TreeDictionary child = this.getChildI(startSig); // gets that child node and assigns to a TreeDictionary
  150. if(child.getNodeSig() == signature) { // if this child's node has nodeSig of our input signature return the child
  151. return child;
  152. }
  153. else {
  154. return findSigNodeHelper(child, signature.substring(1), signature); // else search the child of the next character in the signature using helper method
  155. }
  156. } catch(IOException ex) {
  157. System.out.println("not found"); // if this signature cannot be found
  158. }
  159. }
  160. return null;
  161. }
  162. /**
  163. *
  164. * @param dict the node of the TreeDictionary you wish to search
  165. * @param trimmedSignature the last used signature missing the first element
  166. * @param signature the original signature you wish to search for
  167. * @return the node of TreeDictionary with a nodeSig matching the input signature
  168. * @throws IOException if no match is found
  169. */
  170. public static TreeDictionary findSigNodeHelper(TreeDictionary dict, String trimmedSignature, String signature) throws IOException {
  171. try {
  172. int startSig = Character.getNumericValue(trimmedSignature.charAt(0)); // converts the first number in our signature to an int
  173. TreeDictionary child = dict.getChildI(startSig); // gets that child node and assigns to a TreeDictionary
  174. if(child.getNodeSig().contentEquals(signature)) {// if this child's node has nodeSig of our input signature return the child
  175. return child;
  176. }
  177. else {
  178. return findSigNodeHelper(child, trimmedSignature.substring(1), signature); // else recursively search the child of the next character in the signature using this helper method
  179. }
  180. } catch(IOException ex) {
  181. System.out.println("not found"); // if this signature cannot be found
  182. }
  183. return null;
  184. }
  185. /**
  186. * boolean method returning if input word contains characters not in the alphabet
  187. * @param word, a word to be checked.
  188. * @return true if no invalid characters are found, false if they are
  189. */
  190. static boolean isValidWord(String word) {
  191. word = word.toLowerCase();
  192. for ( int i=0; i < word.length(); i++) {
  193. if(word.charAt(i) < 'a' || word.charAt(i) > 'z')
  194. return false;
  195. }
  196. return true;
  197. }
  198.  
  199. /**
  200. * wordToSignature() takes in a word and returns a String of numbers corresponding to where each
  201. * letter of the word is on an old mobile keyboard, we call this its signature. (https://i.stack.imgur.com/hHq4v.jpg)
  202. * This method makes use of the helper method letterToNumber to convert each letter individually.
  203. * @param word A String of a word you wish to convert
  204. * @return A String of the numeric signature of the word
  205. */
  206. public static String wordToSignature(String word) {
  207. StringBuffer signature = new StringBuffer();
  208. String lowerCaseWord = word.toLowerCase(); // converts to lower case
  209. for (int i=0; i < lowerCaseWord.length(); i++) {
  210. signature.append(letterToNumber(lowerCaseWord.charAt(i))); // we append the signature String for each character in the word
  211. }
  212. return signature.toString(); // converts back to string once fully appended
  213. }
  214.  
  215. /**
  216. * This helper method assigns each letter to its corresponding number on the phones keypad.
  217. * @param letter, the character you wish to convert, non letter characters will become spaces.
  218. * @return The corresponding signature of the character or space if there is none.
  219. */
  220. public static String letterToNumber(char letter) {
  221. if (letter == 'a' || letter == 'b' || letter == 'c')
  222. return "2";
  223. if (letter == 'd' || letter == 'e' || letter == 'f')
  224. return "3";
  225. if (letter == 'g' || letter == 'h' || letter == 'i')
  226. return "4";
  227. if (letter == 'j' || letter == 'k' || letter == 'l')
  228. return "5";
  229. if (letter == 'm' || letter == 'n' || letter == 'o')
  230. return "6";
  231. if (letter == 'p' || letter == 'q' || letter == 'r' || letter == 's')
  232. return "7";
  233. if (letter == 't' || letter == 'u' || letter == 'v')
  234. return "8";
  235. if (letter == 'w' || letter == 'x' || letter == 'y' || letter == 'z')
  236. return "9";
  237. else
  238. return " ";
  239. }
  240.  
  241. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement