I have an assignment that I'm struggling with.
Write code based on referenced-based stack to implement the balance check of a user input string with ‘{’, ‘}’, ‘(’, ‘)’, and ‘[’, and ‘]’. For instance, if user inputs “(abc[d]e{f})”, your code should say that the expression is balanced.
I have the functions push / pop already written:
public void push(Object newItem) {
top = new Node(newItem, top);
} // end push
public Object pop(){
if (!isEmpty()) {
Node temp = top;
top = top.getNext();
return temp.getItem();
} else {
System.out.print("StackError on " +
"pop: stack empty");
return null;
} // end if
} // end pop
However, what I am struggling with is understanding how to create a new node for each character. Could somebody please help me?
Since your assignment instructions ask you to "Write code based on referenced-based stack", it seems your question is more about how to convert each of user's input string into a node. In that case, you can convert them first to a list of chars simply like this:
public class Main {
public static void main(String[] args){
String str = new String("[(a)bcde]");
System.out.println(str.toCharArray());
}
}
And then use ASCII table to tell whether it's a special character. eg: in above code:
(int) str.toCharArray()[0] // will show ASCII code of '[', 91
Some useful implementations about Reference-based Stack
The isbalanced mechanism simplified for [,],(,):
Always add(push) a [, or (
When you get to a ) check the last added character was a (. If it was remove(pop) it, otherwise mark as unbalanced.
When you get to a ] check the last added character was a [. If it was remove(pop) it, otherwise mark as unbalanced.
If the stack is empty by the end of the string, it is balanced.
In reponse to your comment
Based off an answer for iterate through the characters of a string
unbalanced=false;
for (int i = 0; i < s.length(); i++)
{
char c = s.charAt(i);
if(c.equal('[')
{
push(c);
}
if(c.equal(']')
{
Char tmp = (Char)pop();
if(!tmp.equals('['))
unbalanced=true;
break;
}
}
}
if(pop()!=null)
{
unbalanced=true;
}
Here is what the professor was looking for:
... }
if(currChar.equals("["))
{
myStackRef.push("[");
}
if(currChar.equals("}") && myStackRef.peek().equals("{"))
{
myStackRef.pop();
}
if(currChar.equals(")") && myStackRef.peek().equals("("))
{
myStackRef.pop();
}
if(currChar.equals("]") && myStackRef.peek().equals("["))
{
myStackRef.pop();
}
}
if(myStackRef.isEmpty())
{
System.out.println("Balanced");
}
else
{
System.out.println("Unbalanced");
}
}
}
Related
I have two classes here.
The CFG class takes a string array in its constructor that defines the context-free grammar. The SampleTest class is being used to test the CFG class by inputting the grammar (C) into the class, then inputting a string by the user, and seeing if that string can be generated by the context-free grammar.
The problem I'm running into is a stack overflow (obviously). I'm assuming that I just created a never-ending recursive function.
Could someone take a look at the processData() function, and help me out figure out how to correctly configure it. I'm basically using recursion to take generate all possibilities for strings that the CFG can create, then returning true if one of those possibilities being generated matches the user's input (inString). Oh, and the wkString parameter is simply the string being generated by the grammar through each recursive iteration.
public class SampleTest {
public static void main(String[] args) {
// Language: strings that contain 0+ b's, followed by 2+ a's,
// followed by 1 b, and ending with 2+ a's.
String[] C = { "S=>bS", "S=>aaT", "T=>aT", "T=>bU", "U=>Ua", "U=>aa" };
String inString, startWkString;
boolean accept1;
CFG CFG1 = new CFG(C);
if (args.length >= 1) {
// Input string is command line parameter
inString = args[0];
char[] startNonTerm = new char[1];
startNonTerm[0] = CFG1.getStartNT();
startWkString = new String(startNonTerm);
accept1 = CFG1.processData(inString, startWkString);
System.out.println(" Accept String? " + accept1);
}
} // end main
} // end class
public class CFG {
private String[] code;
private char startNT;
CFG(String[] c) {
this.code = c;
setStartNT(c[0].charAt(0));
}
void setStartNT(char startNT) {
this.startNT = startNT;
}
char getStartNT() {
return this.startNT;
}
boolean processData(String inString, String wkString) {
if (inString.equals(wkString)) {
return true;
} else if (wkString.length() > inString.length()) {
return false;
}
// search for non-terminal in the working string
boolean containsNT = false;
for (int i = 0; i < wkString.length(); i++) {
// if one of the characters in the working string is a non-terminal
if (Character.isUpperCase(wkString.charAt(i))) {
// mark containsNT as true, and exit the for loop
containsNT = true;
break;
}
}
// if there isn't a non-terminal in the working string
if (containsNT == false) {
return false;
}
// for each production rule
for (int i = 0; i < this.code.length; i++) {
// for each character on the RHS of the production rule
for (int j = 0; j <= this.code[i].length() - 3; j++) {
if (Character.isUpperCase(this.code[i].charAt(j))) {
// make substitution for non-terminal, creating a new working string
String newWk = wkString.replaceFirst(Character.toString(this.code[i].charAt(0)), this.code[i].substring(3));
if (processData(inString, newWk) == true) {
return true;
}
}
}
} // end for loop
return false;
} // end processData
} // end class
Your grammar contains a left-recursive rule
U=>Ua
Recursive-descent parsers can't handle left-recursion, as you've just discovered.
You have two options: Alter your grammar to not be left-recursive anymore, or use a parsing algorithm that can handle it, such as LR1. In your case, U is matching "at least two a characters", so we can just move the recursion to the right.
U=>aU
and everything will be fine. This isn't always possible to do in such a nice way, but in your case, avoiding left-recursion is the easy solution.
You don't need this for loop: "for (int j = 0; j <= this.code[i].length() - 3; j++)". jus create a var to hold the Capital letter in the nonterminal search you did above. Then do your outer for loop followed by if there is a production rule in String[] that starts with that found Non-terminal, do your substitution and recursion.
I am making a program that takes a String and puts it in the opposite order into a LinkedList.
This code doesn't seem to work (wrong input), and I can't figure out why. Any solutions?
public LargeInteger(String input)
{
TODO
size=size+input.length();
LLNode<Integer> curNode=new LLNode<Integer>();
for(int curPos=input.length()-1;curPos>=0;curPos--)
{
if(curPos==input.length()-1)
{
head=new LLNode<Integer>();
head.data=input.charAt(curPos)+'0';
curNode=head;
}
else
{
curNode.link=new LLNode<Integer>();
curNode=curNode.link;
curNode.data=input.charAt(curPos)+'0';
}
}
}
Welcome to Stack Overflow.
What about to use the methods of List interface and String class, instead of just for loops? Check this example:
String phrase = "this is the phrase"; // this is the input
List<String> list = new LinkedList<>();
// iterates the input in decreasing index order
for(int i=phrase.length()-1; i >= 0; i--) {
// gets the character from the input and add to the LinkedList
list.add(Character.toString(phrase.charAt(i)));
}
If you want not to add white spaces, add if(isEmpty(phrase.charAt(i))) continue; before adding the character.
Live example here.
I have a collection of Strings saved in 2d array.
the string has a shape of horn-clause and the complete one string can be in the form of patient(?x) as well as hasdoctor(?x,?y)
if i write the ?x=alex and ?y=john then the above string takes a structure of
patient(alex)
hasdoctor(alex, john)
Now the Question is when is use the below code it finds the ?x, but in the hasdoctor(?x,?y) it skips the ?y .
void find_var(String[][] temp)
{
System.out.println(temp.length);
System.out.println(temp[0].length);
for(int i=0;i<temp.length;i++)
for(int j=1;j<temp[0].length-1;j++)
{
String text_to_parse=temp[i][j];
Pattern y = Pattern.compile("[?]\\w[,)]");
Matcher z= y.matcher(text_to_parse);
if(z.find())
{
System.out.println("Found at::"+temp[i][j]);
System.out.println(z.group());
}
else
{
System.out.println("Not found at::"+temp[i][j]);
}
}}
the pesudo code i can explain that i want in java is
if([?]\\w[,) is found in array[][])
if([?]\\w[,) is already in other_array[]
Then skip;
else
save [?]\\w[,) to other_array[]
Can't say that I completely understand what you're trying to achieve, but I think the problem is that you're using
if (z.find()) { /* ... */ }
instead of
while (z.find()) { /* ... */ }
Using if, the string will not be completely consumed and it will return after the first match is found.
May I know how can I remove the leading zero in JAVA code? I tried several methods like regex tools
"s.replaceFirst("^0+(?!$)", "") / replaceAll("^0*", "");`
but it's seem like not support with my current compiler compliance level (1.3), will have a red line stated the method replaceFirst(String,String)is undefined for the type String.
Part of My Java code
public String proc_MODEL(Element recElement)
{
String SEAT = "";
try
{
SEAT = setNullToString(recElement.getChildText("SEAT")); // xml value =0000500
if (SEAT.length()>0)
{
SEAT = SEAT.replaceFirst("^0*", ""); //I need to remove leading zero to only 500
}
catch (Exception e)
{
e.printStackTrace();
return "501 Exception in proc_MODEL";
}
}
}
Appreciate for help.
If you want remove leading zeros, you could parse to an Integer and convert back to a String with one line like
String seat = "001";// setNullToString(recElement.getChildText("SEAT"));
seat = Integer.valueOf(seat).toString();
System.out.println(seat);
Output is
1
Of course if you intend to use the value it's probably better to keep the int
int s = Integer.parseInt(seat);
System.out.println(s);
replaceFirst() was introduced in 1.4 and your compiler pre-dates that.
One possibility is to use something like:
public class testprog {
public static void main(String[] args) {
String s = "0001000";
while ((s.length() > 1) && (s.charAt(0) == '0'))
s = s.substring(1);
System.out.println(s);
}
}
It's not the most efficient code in the world but it'll get the job done.
A more efficient segment without unnecessary string creation could be:
public class testprog {
public static void main(String[] args) {
String s = "0001000";
int pos = 0;
int len = s.length();
while ((pos < len-1) && (s.charAt(pos) == '0'))
pos++;
s = s.substring(pos);
System.out.println(s);
}
}
Both of those also handle the degenerate cases of an empty string and a string containing only 0 characters.
Using a java method str.replaceAll("^0+(?!$)", "") would be simple;
First parameter:regex -- the regular expression to which this string is to be matched.
Second parameter: replacement -- the string which would replace matched expression.
As stated in Java documentation, 'replaceFirst' only started existing since Java 1.4 http://docs.oracle.com/javase/7/docs/api/java/lang/String.html#replaceFirst(java.lang.String,%20java.lang.String)
Use this function instead:
String removeLeadingZeros(String str) {
while (str.indexOf("0")==0)
str = str.substring(1);
return str;
}
I am parsing command line arguments, they are just a letter one and a number one ( this is just school homework). Right now I have
List<Letters> letters = new ArrayList<Letters>();
List<Numbers> numbers = new ArrayList<Numbers>();
boolean letterFlag = false;
boolean numberFlag = false;
for(String arg: args){
if ("-letter".equals(arg)) {
letterFlag = true;
numberFlag = false;
} else if ("-number".equals(arg)) {
numberFlag = true;
letterFlag = false;
} else if (letterFlag) {
letters.add(Letter.valueOf(arg.toUpperCase()));
} else if (numberFlag) {
numbers.add(Number.valueOf(arg.toUpperCase()));
}/*else if(letterFlag && !numberFlag)
{
letters.add(Letter.valueOf(arg));
numbers.addAll(Number.values());
}
else if(numberFlag && !letterFlag)
{
numbers.add(Number.valueOf(arg));
letters.addAll(Letters.values());
}*/
else {
System.out.printf("Invalid argument: %s%n", arg);
}
}
TestClass.testMethod(letters, numbers)
With this code when I comment out what I have commented out I can give it a list of numbers and letters in either order but I also need to be able to do either just numbers or just letters and it work but I don't see what is wrong with my logic. Thank you in advance
Based on the comments and the situation (homework) I suspect that TestClass is a course-provided class.
Perhaps there is an option to submit only letters or only numbers with TestClass.testMethod(letters) and TestClass.testMethod(numbers).
In that case you should probably only call that method with the single argument, it appears that it will fail when an empty List is provided.