Stack, Parentheses Matching [duplicate] - java

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() {
...
}
....
}

Related

How do I search for a word in an array of words with the same letters in a different order

the code below is working properly i just can't understand that part in the code
if (temp.indexOf(Search.charAt(j)) == -1){
cpt=0;
} else {
cpt++;
}
what does that condition mean ??
public static void main(String[] args) {
String Search="loop";
String[] words={"loop","pool","lopo","book","kobo","oopl","olop","opol"};
int cpt=0;
String temp;
for(int i=0;i<words.length;i++){
temp=words[i];
for (int j=0 ; j<Search.length();j++) {
if (temp.indexOf(Search.charAt(j))==-1){
cpt=0;
} else {
cpt++;
}
if (cpt==4){
System.out.println("-> :"+ temp);
cpt=0;
}
}
}
}
The idea of the code is to go through each word (call it temp) in the list and compute how many characters in temp are present in Search.
For example "loop" and "pool" both have 1 'p', 1 'l' and 2 'p' characters.
But it's not completely correct...
This line if (temp.indexOf(Search.charAt(j))==-1) is checking to see if Search[j] exists in temp
but it should be more like
if(temp has this Search[j] character at some index (call it t) and t hasn't been used previously)
This should fail for cases like "loop" and "lop"
Also you're hardcoding the number 4 in the code, and it should be replaced by the length of Search
I recommend using a map.
As we know the index of method work on two condition .....
Condition 1 - if the giving character is exist in the string then it means the
character is available at index 0 to string.lenth-1 index.
Condition 2 - if giving character is not exist in string that means the character
is not available in that string from 0 index to entire string,
so is return -1.

Valid parentheses in Java

Code:
public static void main(String[] args) {
Arrays.asList("a+(b*c)-2-a", "(a+b*(2-c)-2+a)*2", "(a*b-(2+c)", "2*(3-a))", ")3+b*(2-c)(")
.stream().forEach((expression) -> {
if (replaceAll(expression, "[(]") == replaceAll(expression, "[)]")) {
System.out.println("correct");
} else {
System.out.println("incorrect");
}
});
}
private static int replaceAll(String word, String regex) {
int count = word.length() - word.replaceAll(regex, "").length();
return count;
}
I have to check if the expression is valid or not. What determine if an expression is valid or not are the parentheses. If it's self closed, is valid, otherwise, not.
My code is almost correct, it's printing:
correct
correct
incorrect
incorrect
correct
But it must print
correct
correct
incorrect
incorrect
incorrect -> the last expression isn't valid.
You need not only to check if the number of opening parentheses matches the number of closed, but also if each closing parenthesis goes after opening one which isn't "closed" yet:
static boolean checkParentheses(String s) {
int opened = 0;
for (int i = 0; i < s.length(); i++) {
if (s.charAt(i) == '(')
opened++;
else if (s.charAt(i) == ')') {
if (opened == 0) // means that all parentheses are "closed" yet
return false;
opened--;
}
}
return opened == 0;
}
If you strictly need regex to be involved, do the following:
static boolean checkParentheses(String s) {
// capture a text starting with one opening parenthesis,
// ending with one closing and having no parentheses inside
Pattern p = Pattern.compile("\\([^()]*\\)");
Matcher m;
while ((m = p.matcher(s)).find())
s = m.replaceAll("");
return !(s.contains("(") || s.contains(")"));
}
Your issue is that it's not enough just to count parentheses; you also need to spot where a ')' comes too early. For example ")(" is not valid even though there are an equal number of opening and closing parentheses.
One approach is to keep a count. Start at zero. Each time you see '(', count++. Each time you see ')', count--.
After a decrement, if(count<0) the input is invalid.
At the end of input, if(count!0) the input is invalid.
It's been pointed out that this can't be done in a single regex. That's because a regex represents a finite state machine. count could in principle increase infinitely.
If you pick a maximum nesting depth, you can write a regex to check it. For example, for a maximum depth of 3:
x*(<x*(<x*(<x*>)*x*>)*x*>)*x*
(I've used 'x' instead of arbitrary chars here, for readability. Replace it with [^<>] to actually match other chars. I've also used <> instead of \(\) again for readability. The () here are for grouping.).
You can always make it work one level deeper by replacing the x* in the middle with x*(<x*>)*x* -- but you can never made a regex that doesn't stop working at a certain depth.
An alternative method is closer to what a real statement parser would do with nested structures: recurse. Something like (pseudocode):
def consumeBlock() {
switch(next char)
case end-of-input
throw error -- reached end of input inside some parentheses
case '('
consumeBlock() -- go down a nesting level
break;
case ')'
return -- go up a nesting level
default
It's an uninteresting character. Do nothing.
(a real parser compiler would do something more interesting)
}
Here consumeBlock() assumes you've just consumed a '(' and you intend to read until its pair.
Some of your inputs don't begin with a '(', so prime it by first appending a ')' to the end, as the pair to a "silent" ')' you're saying it's already consumed.
The pseudocode already shows that if you hit end-of-input mid-block, it's invalid input. Also if you are not at end-of-input when the top-level call to consumeBlock() returns, it's invalid input.
You could go through it char by char and using a counter to tell the parenthesis level in the statement.
boolean valid = true;
int level = 0;
for(int i=0; i < expr.length(); i++) {
if(expr.charAt(i) == '(') level++;
if(expr.charAt(i) == ')') level--;
if(level < 0) { // ) with no (
valid = false;
break;
}
}
if(level > 0) valid = false; // ( with no )
return valid; // true if level returned to 0

Finding Palindromes in a word list

I'm working on a program for Java on how to find a list of palindromes that are embedded in a word list file. I'm in an intro to Java class so any sort of help or guidance will be greatly appreciated!
Here is the code I have so far:
import java.util.Scanner;
import java.io.File;
class Palindromes {
public static void main(String[] args) throws Exception {
String pathname = "/users/abrick/resources/american-english-insane";
File dictionary = new File(pathname);
Scanner reader = new Scanner(dictionary);
while (reader.hasNext()) {
String word = reader.nextLine();
for (int i = 0; i > word.length(); i++) {
if (word.charAt(word.indexOf(i) == word.charAt(word.indexOf(i)) - 1) {
System.out.println(word);
}
}
}
}
}
There are 3 words that are 7 letters or longer in the list that I am importing.
You have a few ways to solve this problem.
A word is considered a palindrome if:
It can be read the same way backwards as forwards.
The first element is the same as the last element, up until we reach the middle.
Half of the word is the same as the other half, reversed.
A word of length 1 is trivially a palindrome.
Ultimately, your method isn't doing much of that. In fact, you're not doing any validation at all - you're only printing the word if the first and last character match.
Here's a proposal: Let's read each end of the String, and see if it's a palindrome. We have to take into account the case that it could potentially be empty, or be of length 1. We also want to get rid of any white space in the string, as that can cause errors on validation - we use replaceAll("\\s", "") to solve that.
public boolean isPalindrome(String theString) {
if(theString.length() == 0) {
throw new IllegalStateException("I wouldn't expect a word to be zero-length");
}
if(theString.length() == 1) {
return true;
} else {
char[] wordArr = theString.replaceAll("\\s", "").toLowerCase().toCharArray();
for(int i = 0, j = wordArr.length - 1; i < wordArr.length / 2; i++, j--) {
if(wordArr[i] != wordArr[j]) {
return false;
}
}
return true;
}
}
I'm assuming that you're reading in strings. Use string.toCharArray() to convert each string to a char[]. Iterate through the character array using a for loop as follows: on iteration 1, if the first character is equal to the last character, then proceed to the next iteration, else return false. On iteration 2, if the second character is equal to the second-to-last character then proceed to the next iteration, else return false. And so on, until you reach the middle of the string, at which point you return true. Be careful of off-by-one errors; some strings will have an even length, some will have an odd length.
If your palindrome checker is case insensitive, then use string.toLowerCase().toCharArray() to preprocess the character array.
You can use string.charAt(i) instead of string.toCharArray() in the for loop; in this case, if the palindrome checker is case insensitive then preprocess the string with string = string.toLowerCase()
Let's break the problem down: In the end, you are checking if the reverse of the word is equal to the word. I'm going to assume you have all of the words stored in an array called wordArray[].
I have some code for getting the reverse of the word (copied from here):
public String reverse(String str) {
if ((null == str) || (str.length() <= 1)) {
return str;
}
return new StringBuffer(str).reverse().toString();
}
So, now we just need to call that on every word. So:
for(int count = 0; count<wordArray.length;count++) {
String currentWord = wordArray[count];
if(currentWord.equals(reverse(currentWord)) {
//it's a palendrome, do something
}
}
Since this is homework, i'll not supply you with code.
When i code, the first thing i do is take a step back and ask myself,
"what am i trying to get the computer to do that i would do myself?"
Ok, so you've got this huuuuge string. Probably something like this: "lkasjdfkajsdf adda aksdjfkasdjf ghhg kajsdfkajsdf oopoo"
etc..
A string's length will either be odd or even. So, first, check that.
The odd/even will be used to figure out how many letters to read in.
If the word is odd, read in ((length-1)/2) characters.
if even (length/2) characters.
Then, compare those characters to the last characters. Notice that you'll need to skip the middle character for an odd-lengthed string.
Instead of what you have above, which checks the 1st and 2nd, then 2nd and 3rd, then 3rd and fourth characters, check from the front and back inwards, like so.
while (reader.hasNext()) {
String word = reader.nextLine();
boolean checker = true;
for (int i = 0; i < word.length(); i++) {
if(word.length()<2){return;}
if (word.charAt(i) != word.charAt(word.length()-i) {
checker = false;
}
}
if(checker == true)
{System.out.println(word);}
}

Ensure parenthesis are balanced?

I am tasked to create a function that checks if a number of small "(" and big "[" parentheses and closes properly. For example...
(()) [] ([])[(())]
...is correct, but...
() [(])
...is incorrect.
Any advice on how to start approaching this problem? The use of recursive functions is prohibited.
This is what I have so far:
{
int nr_ap_x = 0; // fie x - "("
int nr_ap_y = 0; // fie y - ")"
boolean corect = true;
for (int i=0; i < sir.length; i++)
{
if (sir[i].compareTo("(") == 0) nr_ap_x++;
else
if (sir[i].compareTo(")") == 0) nr_ap_y++;
if (nr_ap_x < nr_ap_y) corect = false;
}
if (nr_ap_x != nr_ap_y) corect = false;
if (corect) System.out.println("Parantezele sunt inchise corect ! ");
else System.out.println("Parantezele NU sunt inchise corect ! ");
}
General outline of how to do this (assuming you have an array of strings each containing a parenthesis):
Create a stack which contains strings.
For each "(" or "[", push onto the stack.
For each ")" or "]", check if the top of the stack matches the type of parenthesis.
If it does, discard the top of the stack.
Otherwise, the parenthesis are mismatched.
If you have a non empty stack once all your strings run out, you also have mismatched parentheses.
Hint: keep a data structure containing the opening glyphs, and use and update it when a closing glyph appear.
Anything that's done with recursion can also be done with iteration. If you already know how to do it recursively then map it to a while loop. This is explained in Replace Recursion with Iteration.
You could use a deterministic finite automaton - http://en.wikipedia.org/wiki/Deterministic_finite-state_machine

Can I improve this Pig-Latin converter? [closed]

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 9 years ago.
Improve this question
I'm brand-spanking new to Java and I made this little translator for PigLatin.
package stringmanipulation;
public class PigLatinConverter {
public String Convert(String word){
int position = 0;
if (!IsVowel(word.charAt(0))) {
for (int i= 0; i < word.length(); i++) {
if (IsVowel(word.charAt(i))) {
position = i;
break;
}
}
String first = word.substring(position, word.length());
String second = word.substring(0, position) + "ay";
return first + second;
} else {
return word + "way";
}
}
public boolean IsVowel(char c){
if (c == 'a')
return true;
else if(c == 'e')
return true;
else if(c == 'i')
return true;
else if(c == 'o')
return true;
else if(c == 'u')
return true;
else
return false;
}
}
Are there any improvements I can make?
Are there any nifty Java tricks that are in the newest Java version I might not be aware of? I come from a C# background.
Thank you!
I'd rewrite isVowel(char ch) as follows:
return "aeiou".indexOf(ch) != -1;
And I'd write the following instead:
// String first = word.substring(position, word.length());
String first = word.substring(position);
I'd also rename method names to follow coding convention.
And of course, being me, I'd also use regex instead of substring and for loop.
System.out.println("string".replaceAll("([^aeiou]+)(.*)", "$2$1ay"));
// ingstray
References
Java Coding Convention - Naming Convention
Disclaimer: I don't know Java.
Inverted logic is confusing please write your if statement as such:
if (IsVowel(word.charAt(0))) {
return word + "way";
} else {
for (int i= 0; i < word.length(); i++) {
// ...
return first + second;
}
You can even drop the else.
IsVowel may need to be private. It can also be rewritten using a single || chain, or as a "".indexOf (or whatever it is in Java).
Your for logic can be simplified int a short while:
while (position < word.length() && !IsVowel(word.charAt(position)) {
++position;
}
Here's a complete rewrite that makes the code more readable if you know how to read regex:
String[] words =
"nix scram stupid beast dough happy question another if".split(" ");
for (String word : words) {
System.out.printf("%s -> %s%n", word,
("w" + word).replaceAll(
"w(qu|[^aeiou]+|(?<=(w)))([a-z]*)",
"$3-$1$2ay"
)
);
}
This prints (as seen on ideone.com):
nix -> ix-nay
scram -> am-scray
stupid -> upid-stay
beast -> east-bay
dough -> ough-day
happy -> appy-hay
question -> estion-quay
another -> another-way
if -> if-way
Note that question becomes estion-quay, which is the correct translation according to Wikipedia article. In fact, the above words and translations are taken from the article.
The way the regex work is as follows:
First, all words are prefixed with w just in case it's needed
Then, skipping that w, look for either qu or a non-empty sequence of consonants. If neither can be found, then the actual word starts with a vowel, so grab the w using capturing lookbehind
Then just rearrange the components to get the translation
That is:
"skip" dummy w
|
w(qu|[^aeiou]+|(?<=(w)))([a-z]*) --> $3-$1$2ay
\ 2\_/ /\______/
\_________1_________/ 3
References
regular-expressions.info
Character class:[…], Alternation: |, Repetition:+,*, Lookaround:(?<=…), and Capturing:(…)
I know this question is well over a year old, but I thought I would put my modification of it. There are several improvements in this code.
public String convert(String word)
{
int position = 0;
while(!isVowel(word.charAt(position)))
{
++position;
}
if(position == 0)
{
return word + "-way";
}
else if(word.charAt(0) == 'q')
{
++position;
}
return word.substring(position) + "-" + word.substring(0, position) + "ay";
}
public boolean isVowel(char character)
{
switch(character)
{
case 'a': case 'e': case 'i': case 'o': case 'u':
return true;
default:
return false;
}
}
First the code will find the position of the first vowel, and then jump out of the loop. This is simpler than using a for loop to iterate through each letter and using break; to jump out of the loop. Secondly, this will match all the testcases on the Wikipedia site. Lastly, since chars are actually a limited range int, a switch statement can be used to improve performance and readability.
Not strictly an improvement as such, but Java convention dictates that methods should start with a lowercase letter.
I'm years removed from Java, but overall, your code looks fine. If you wanted to be nitpicky, here are some comments:
Add comments. It doesn't have to follow the Javadoc specification, but at least explicitly describe the accepted argument and the expected return value and perhaps give some hint as to how it works (behaving differently depending on whether the first character is a vowel)
You might want to catch IndexOutOfBoundsException, which I think might happen if you pass it a zero length string.
Method names should be lower case.
IsVowel can be rewritten return c == 'a' || c == 'e' and so on. Due to short-circuiting, the performance in terms of number of comparisons should be similar.
Is this homework? If so, tag it as such.
Unclear what expected behaviour is for "honest" or "ytterbium".
It doesn't respect capitals ("Foo" should turn into "Oofay", and AEIOU are also vowels).
It crashes if you pass in the empty string.

Categories

Resources