Recursion Filling a Tree - java

I have a Java class: BinaryTree< t > that I am filling from a file as follow:
E .
T -
I ..
N -.
M --
A .-
W .--
R .-.
S ...
etc (to end of alphabit)
BinaryTree has:
setRight(BinaryTree) -sets the right element
setLeft(BinaryTree) -sets the left element
setRootElement(t) -sets the root element
getRight() -gets the right element
getLeft() -gets the left element
getRootElement() -gets the root element of the node IE/ a Character
size() -returns the size of the tree
These are the only methods available in the BinaryTree class I was given
So what i want to do is I want to read each line of the file one by one getting the Letter and the string of "morse code". NOTE: I can only use the Scanner class for reading the File!
Then i want to recursively fill this tree from the contents of the file and a few rules:
A "." means tack to left so the first part of the file would mean tack node with 'E' character to the Left of the root
A "-" means tack to right so the second line in the file would mean tack node with 'T' character to the Right of the root.
So "W .--" would mean tack node with 'W' from root One node to the left, then one node to the right then tack on to the right of that Node.
In the end the tree would look like:
tree http://i56.tinypic.com/339tuys.png
Since i'm new to Recursion I am having a lot of trouble visualizing how a tree could be filled recursively while reading from a file using a scanner.
Would I have to read the file elsewhere and pass the information into the recursive method???
Or could I read the file right in the recursive method? Which doesn't seem possible.
Also, what would you use as a Base Case, i'm tempted to use t.size() == 27, because that is the size of the final tree.
Any suggestions or comments would be greatly appreciated!!
Thank you!

Scanner sc = new Scanner(new File(...));
while (sc.hasNext()) {
String letter = sc.next();
String morse = sc.next();
BinaryTree forPosition = theBinaryTree;
for(int i = 0; i < morse.length(); i++) {
if (morse.charAt(i) == '.') {
if(forPosition.getLeft() == NULL) {
forPosition.setLeft() = new BinaryTree();
}
forPosition = forPosition.getLeft();
}
else {
// similar
}
}
forPostion.setRootElement(letter);
}
A weird recursive version:
Scanner sc = new Scanner(new File(...));
while (sc.hasNext()) {
String letter = sc.next();
String morse = sc.next();
findTheNode (theBinaryTree, letter, morse);
}
forPostion.setRootElement(letter);
}
findTheNode (BinaryTree node, String letter, String morse) {
if (morse.length() == 0) {
node.setRootElement(letter);
return;
} // found
if (morse.charAt(0) == '.') {
if (node.getLeft() == NULL) {
node.setLeft() = new BinaryTree();
}
findTheNode (node.getLeft(), letter, morse.substring(1));
}
else {
// similar
}
}
Hope both of the above work.
The result may look like this.
Recursive is usually used for traversal and binary search tree, but this tree is more similar to Trie, of only 2 character in alphabet (i.e. . and -). The rule of the construction of the tree (. for left, and - for right) makes it unnecessary to use recursion.

Related

Trying to print all words in a trie in java

I'm using a trie structure called a dictionary tree which I want to print all words from. When I insert a word when I reach the last letter in the word I store the completed word in Dictionary Tree.
private Map<Character, DictionaryTree> children = new LinkedHashMap<>();
private String completeWord;
void insertionHelper(String currentPortion, String fullWord){
if(currentPortion.length() == 1){
if(children.containsKey(currentPortion.charAt(0))){
// do nothing
}else{
this.children.put(currentPortion.charAt(0), new DictionaryTree());
}
this.completeWord = fullWord;
}else{
if(children.containsKey(currentPortion.charAt(0))){
children.get(currentPortion.charAt(0)).insertionHelper(currentPortion.substring(1), fullWord);
}else{
DictionaryTree a = new DictionaryTree();
a.insertionHelper(currentPortion.substring(1), fullWord);
children.put(currentPortion.charAt(0), a);
}
}
}
After this when Looking for all words I traverse every node and try to add the words to a static array List, however, for some reason many of the words are duplicated and others are missing.
String allWordHelper(){
String holder = " ";
for (Map.Entry<Character, DictionaryTree> child : children.entrySet()) {
if(completeWord != null){
//holder += completeWord + child.getValue().allWordHelper();
Word_Holder.allWords.add(completeWord);
}else{
holder += child.getValue().allWordHelper();
}
}
return holder;
}
I can't figure out why.
I have no idea what a DictionaryTree is and what your indata looks like but if you do
children.put(currentPortion.charAt(0), a);
doesn't that mean that whenever you get a words that starts with the same character as a previous word then the old word might be replaced by the new one?
It's quite impossible to fully understand your code with an unknown data type and all the recursive calls.

Using a user inputted string of characters find the longest word that can be made

Basically I want to create a program which simulates the 'Countdown' game on Channel 4. In effect a user must input 9 letters and the program will search for the largest word in the dictionary that can be made from these letters.I think a tree structure would be better to go with rather than hash tables. I already have a file which contains the words in the dictionary and will be using file io.
This is my file io class:
public static void main(String[] args){
FileIO reader = new FileIO();
String[] contents = reader.load("dictionary.txt");
}
This is what I have so far in my Countdown class
public static void main(String[] args) throws IOException{
Scanner scan = new Scanner(System.in);
letters = scan.NextLine();
}
I get totally lost from here. I know this is only the start but I'm not looking for answers. I just want a small bit of help and maybe a pointer in the right direction. I'm only new to java and found this question in an interview book and thought I should give it a .
Thanks in advance
welcome to the world of Java :)
The first thing I see there that you have two main methods, you don't actually need that. Your program will have a single entry point in most cases then it does all its logic and handles user input and everything.
You're thinking of a tree structure which is good, though there might be a better idea to store this. Try this: http://en.wikipedia.org/wiki/Trie
What your program has to do is read all the words from the file line by line, and in this process build your data structure, the tree. When that's done you can ask the user for input and after the input is entered you can search the tree.
Since you asked specifically not to provide answers I won't put code here, but feel free to ask if you're unclear about something
There are only about 800,000 words in the English language, so an efficient solution would be to store those 800,000 words as 800,000 arrays of 26 1-byte integers that count how many times each letter is used in the word, and then for an input 9 characters you convert to similar 26 integer count format for the query, and then a word can be formed from the query letters if the query vector is greater than or equal to the word-vector component-wise. You could easily process on the order of 100 queries per second this way.
I would write a program that starts with all the two-letter words, then does the three-letter words, the four-letter words and so on.
When you do the two-letter words, you'll want some way of picking the first letter, then picking the second letter from what remains. You'll probably want to use recursion for this part. Lastly, you'll check it against the dictionary. Try to write it in a way that means you can re-use the same code for the three-letter words.
I believe, the power of Regular Expressions would come in handy in your case:
1) Create a regular expression string with a symbol class like: /^[abcdefghi]*$/ with your letters inside instead of "abcdefghi".
2) Use that regular expression as a filter to get a strings array from your text file.
3) Sort it by length. The longest word is what you need!
Check the Regular Expressions Reference for more information.
UPD: Here is a good Java Regex Tutorial.
A first approach could be using a tree with all the letters present in the wordlist.
If one node is the end of a word, then is marked as an end-of-word node.
In the picture above, the longest word is banana. But there are other words, like ball, ban, or banal.
So, a node must have:
A character
If it is the end of a word
A list of children. (max 26)
The insertion algorithm is very simple: In each step we "cut" the first character of the word until the word has no more characters.
public class TreeNode {
public char c;
private boolean isEndOfWord = false;
private TreeNode[] children = new TreeNode[26];
public TreeNode(char c) {
this.c = c;
}
public void put(String s) {
if (s.isEmpty())
{
this.isEndOfWord = true;
return;
}
char first = s.charAt(0);
int pos = position(first);
if (this.children[pos] == null)
this.children[pos] = new TreeNode(first);
this.children[pos].put(s.substring(1));
}
public String search(char[] letters) {
String word = "";
String w = "";
for (int i = 0; i < letters.length; i++)
{
TreeNode child = children[position(letters[i])];
if (child != null)
w = child.search(letters);
//this is not efficient. It should be optimized.
if (w.contains("%")
&& w.substring(0, w.lastIndexOf("%")).length() > word
.length())
word = w;
}
// if a node its end-of-word we add the special char '%'
return c + (this.isEndOfWord ? "%" : "") + word;
}
//if 'a' returns 0, if 'b' returns 1...etc
public static int position(char c) {
return ((byte) c) - 97;
}
}
Example:
public static void main(String[] args) {
//root
TreeNode t = new TreeNode('R');
//for skipping words with "'" in the wordlist
Pattern p = Pattern.compile(".*\\W+.*");
int nw = 0;
try (BufferedReader br = new BufferedReader(new FileReader(
"files/wordsEn.txt")))
{
for (String line; (line = br.readLine()) != null;)
{
if (p.matcher(line).find())
continue;
t.put(line);
nw++;
}
// line is not visible here.
br.close();
System.out.println("number of words : " + nw);
String res = null;
// substring (1) because of the root
res = t.search("vuetsrcanoli".toCharArray()).substring(1);
System.out.println(res.replace("%", ""));
}
catch (Exception e)
{
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Output:
number of words : 109563
counterrevolutionaries
Notes:
The wordlist is taken from here
the reading part is based on another SO question : How to read a large text file line by line using Java?

Stack, Parentheses Matching [duplicate]

This question already has answers here:
Handling parenthesis while converting infix expressions to postfix expressions
(2 answers)
Closed 5 years ago.
So I'm working on some homework with PostFix and Infix Expressions. I'm running into a bit of a problem and can't seem to find where I'm having the issue. I can get the Infix to Postfix working...for the most part. Some of the equations I'm getting a ( or ) printed when I don't want it to be printed. Also when I have no matching parentheses I don't get an error like I want it to.
public String Infix(String equation) throws Exception{
Stack stack=new Stack();
boolean parensMatch=false;
int priority=0;
String temp="";
for(int i=0; i<equation.length(); i++){
char c=equation.charAt(i);
//if the character is equal to left paren, push
if(c=='('){
stack.push(c);
}
//if the character is equal to right paren, we start popping until we find a match
else if(c==')'){
try{
while(stack.peek()!='('){
temp+=stack.pop();
}
if(stack.peek()=='('){
char ch=stack.pop();
parensMatch=true;
}
if(parensMatch==false){
throw new Exception("Parens Not Match Error");
}
}catch(Exception e){
System.out.println(e);
}
parensMatch=false;
}
//if the character is equal to an operator, we do some extra work
//to figure out what is going to happen
else if(c=='+' || c=='-' || c=='*' || c=='/' || c=='^'){
char top=stack.peek();
if(top=='^')
priority=2;
else if(top=='*' || top=='/')
priority=1;
else
priority=0;
if(priority==2){
if(c=='*' || c=='/'){
temp+=stack.pop();
}
else if(c=='+' || c=='-'){
temp+=stack.pop();
}
else{
temp+=stack.pop();
}
}
else{
if(c=='*' || c=='/'){
temp+=stack.pop();
stack.push(c);
}
else if(c=='+' || c=='-'){
stack.push(c);
}
else{
stack.push(c);
}
}
}
//if the character is a space, we ignore it and move on
else if(c==' '){
;
}
//if the character is a letter, we add it to the string
else{
temp+=c;
}
}
int len = stack.size();
for (int j = 0; j < len; j++)
temp+=stack.pop();
return temp;
}
This is my Infix to Postfix method
(((A + B) - (C - D)) / (E - F)) This is one of the expressions that I need to solve, and AB+CD--(EF-/ is what I get when it prints to the screen. ((A is another, this one should give me an error but A(( is printed to the screen.
I have been running the debug for quite a while and can't seem to get anywhere.
Any help would be very helpful. I know it has something to with the code posted but I can't find the logic error. Thanks in advance!
So I added a new function to help with matching parens that I think will be useful. It takes the equation and just counts to see if they match or not.
public static int matchingParens(String equation){
int match=0;
for(int i=0; i<equation.length(); i++){
char c=equation.charAt(i);
if(c=='(')
match++;
else if(c==')')
match--;
else
;
}
return match;
}
To validate if parenthesis are all matched up, you can run through your String input of the math expression with a counter of initial value of 0, and if you find a (, increment your counter by 1, and if you find a ), decrement your counter by 1. If the counter ever reaches -1, break out, as it isn't a valid parenthesis match. In the end, you should have the counter's value as 0. If not, you have a mismatched parenthesis.
For the infix to postfix case, here's a standard algorithm:
Define a stack
Go through each character in the string
If it is between 0 to 9, append it to output string.
If it is left brace push to stack
If it is operator *,+,- or / then
If the stack is empty push it to the stack
If the stack is not empty then start a loop:
If the top of the stack has higher precedence
Then pop and append to output string
Else break
Push to the stack
If it is right brace then
While stack not empty and top not equal to left brace
Pop from stack and append to output string
Finally pop out the left brace.
Well I would like give you some "software engineering" tip, which in the end can solve your problem and you can learn a lot by doing it "nice".
Mathematical expression, no matter if you write them in pre, in, post order, looks always the same, if you store them in some tree structure.
Then, if you want to print that tree structure into String, you just go through the whole tree, and it varies only in the moment (and additional braces for some cases), when you write it to that string.
Preorder do it when you first go into that node, Inorder when you finished left child and Postorder, if you do it when you leaving that node.
My advice :
Class : Expression, UnaryExpression extends Expression, BinaryExpression extedns Expression and then you can make numbers and operators : Add extends BinaryExpression etc.
Then you should have class Tree, which stores the Expression root and it has methods printPreOrder(), printInOrder(), printPostOrder()
To create that tree, it would be really nice to use a Builder pattern which can be used like this :
public class Director {
private IExpressionBuilder builder;
public ArithmeticExpression construct(String text){
for (int i=0;i<text.length();i++){
if (text.charAt(i) == '+'){
builder.buildAddOperator();
}
...
}
}
And then you create concrete Builder classes, which look like this :
public class InOrderBuilder implements IExpressionBuilder {
public void buildAddOperator() {
...
}
....
}

Normalization in DOM parsing with java - how does it work?

I saw the line below in code for a DOM parser at this tutorial.
doc.getDocumentElement().normalize();
Why do we do this normalization ?
I read the docs but I could not understand a word.
Puts all Text nodes in the full depth of the sub-tree underneath this Node
Okay, then can someone show me (preferably with a picture) what this tree looks like ?
Can anyone explain me why normalization is needed?
What happens if we don't normalize ?
The rest of the sentence is:
where only structure (e.g., elements, comments, processing instructions, CDATA sections, and entity references) separates Text nodes, i.e., there are neither adjacent Text nodes nor empty Text nodes.
This basically means that the following XML element
<foo>hello
wor
ld</foo>
could be represented like this in a denormalized node:
Element foo
Text node: ""
Text node: "Hello "
Text node: "wor"
Text node: "ld"
When normalized, the node will look like this
Element foo
Text node: "Hello world"
And the same goes for attributes: <foo bar="Hello world"/>, comments, etc.
In simple, Normalisation is Reduction of Redundancies.
Examples of Redundancies:
a) white spaces outside of the root/document tags(...<document></document>...)
b) white spaces within start tag (<...>) and end tag (</...>)
c) white spaces between attributes and their values (ie. spaces between key name and =")
d) superfluous namespace declarations
e) line breaks/white spaces in texts of attributes and tags
f) comments etc...
As an extension to #JBNizet's answer for more technical users here's what implementation of org.w3c.dom.Node interface in com.sun.org.apache.xerces.internal.dom.ParentNode looks like, gives you the idea how it actually works.
public void normalize() {
// No need to normalize if already normalized.
if (isNormalized()) {
return;
}
if (needsSyncChildren()) {
synchronizeChildren();
}
ChildNode kid;
for (kid = firstChild; kid != null; kid = kid.nextSibling) {
kid.normalize();
}
isNormalized(true);
}
It traverses all the nodes recursively and calls kid.normalize()
This mechanism is overridden in org.apache.xerces.dom.ElementImpl
public void normalize() {
// No need to normalize if already normalized.
if (isNormalized()) {
return;
}
if (needsSyncChildren()) {
synchronizeChildren();
}
ChildNode kid, next;
for (kid = firstChild; kid != null; kid = next) {
next = kid.nextSibling;
// If kid is a text node, we need to check for one of two
// conditions:
// 1) There is an adjacent text node
// 2) There is no adjacent text node, but kid is
// an empty text node.
if ( kid.getNodeType() == Node.TEXT_NODE )
{
// If an adjacent text node, merge it with kid
if ( next!=null && next.getNodeType() == Node.TEXT_NODE )
{
((Text)kid).appendData(next.getNodeValue());
removeChild( next );
next = kid; // Don't advance; there might be another.
}
else
{
// If kid is empty, remove it
if ( kid.getNodeValue() == null || kid.getNodeValue().length() == 0 ) {
removeChild( kid );
}
}
}
// Otherwise it might be an Element, which is handled recursively
else if (kid.getNodeType() == Node.ELEMENT_NODE) {
kid.normalize();
}
}
// We must also normalize all of the attributes
if ( attributes!=null )
{
for( int i=0; i<attributes.getLength(); ++i )
{
Node attr = attributes.item(i);
attr.normalize();
}
}
// changed() will have occurred when the removeChild() was done,
// so does not have to be reissued.
isNormalized(true);
}
Hope this saves you some time.

Recursive Traverse of Binary Tree Not Terminating At Return Statement

I have created a class that populates a binary tree with morse code. Where traversing to the left signifies a DOT and traversing to the right signifies a DASH. Everything was going great until I am writing an encode method to convert a alpha character into a morse code string. The method should recursively do a preorder traverse of the tree(creating a string of the morse code along the way) until it finds a target character and then returns that string.
However, for some reason my recursion won't terminate on my base case. It just keeps running the entire traverse. I attached my code for the method below. Why does the return statement at in the if statement not trigger and end the method?
Sorry if this is ambiguous, but I didn't want to post 300 lines of code for my entire project when someone smarter than I would notice the problem right off.
Thanks for any help
//wrapper class
//#parameter character is the character to be encoded
//#return return the morse code as a string corresponding to the character
public String encode(char character){
return encode(morseTree, character, "");
}
//#Parameters tree is the binary tree is the tree to be searched,
//element is the target character trying to be foudn, s is the string being used to build the morse code
//#return returns the morse code that corresponds to the element being checked
public String encode(BinaryTree<Character> tree, char target, String s){
if(tree.getData() == target){ //if the data at the current tree is equal to the target element
//return the string that is holding the morse code pattern for this current traversal
return s;
}else{
if(tree.getLeftSubtree() != null){
//Traverse the left side, add a DOT to the end of a string to change the morse code
encode(tree.getLeftSubtree(), target, s + DOT);
}
if(tree.getRightSubtree() != null){
//Traverse the left side, add a DOT to the end of a string to change the morse code
encode(tree.getRightSubtree(), target, s + DASH);
}
}
//The code should never get this far!
return s;
}
Your calls in the else block don't return - they probably should, like this:
if (tree.getLeftSubtree() != null) {
// Traverse the left side, add a DOT to the end of a string to
// change the morse code
return encode(tree.getLeftSubtree(), target, s + DOT);
}
if (tree.getRightSubtree() != null) {
// Traverse the left side, add a DOT to the end of a string to
// change the morse code
return encode(tree.getRightSubtree(), target, s + DASH);
}
However, what do you want to happen if both the left and right subtrees are null? And if they're both non-null, what do you want to return?
Note that just because your base call already returned, that only returns for that single call - not all the other calls in the stack. Recursing doesn't replace the stack frame with the new call - it just adds another stack frame1. Returning from that new stack frame just gets you back to where you were.
1 Yes, I know about tail recursion. Let's not confuse things though.

Categories

Resources