Reverse Polish Notation Code Review - java

I've been trying to solve this question on SPOJ: http://www.spoj.com/problems/ONP/.
I've tried to implement a two Stack solution for the problem stated above. It works fine on my system, but I get a 'Wrong Answer' every time I try to submit the following code to the SPOJ Engine.
import java.io.*;
import java.util.Stack;
import java.util.Scanner;
public class InfixToPostfix {
public static String postfixString(String expression) {
Stack <Character> valueStack = new Stack <Character>();
Stack <Character> operatorStack = new Stack <Character>();
char[] tokens = expression.toCharArray();
for(char c : tokens) {
if(c == '('){
continue;
}
else if(c == '+' || c == '-' || c == '*' || c == '/' || c == '^') {
operatorStack.push(c);
continue;
}
else if(c == ')') {
valueStack.push(operatorStack.peek());
operatorStack.pop();
continue;
}
else {
valueStack.push(c);
continue;
}
}
return valueStack.toString();
}
public static void main (String [] args)throws java.lang.Exception {
String inputString = "";
int n1;
Scanner numberOfTestCases = new Scanner(System.in);
try
{
n1 = numberOfTestCases.nextInt();
StringBuilder[] sbuf = new StringBuilder[n1];
Scanner inputExpression = new Scanner(System.in);
for(int i = 0; i < n1; i++) {
sbuf[i] = new StringBuilder();
if(inputExpression.hasNextLine()) {
inputString = inputExpression.nextLine();
sbuf[i].append(postfixString(inputString).replaceAll("\\[", "").replaceAll("]", "").replaceAll(", ", ""));
}
else {
break;
}
}
for(int i = 0; i < n1; i++) {
System.out.println(sbuf[i].toString());
}
}
catch (Exception e) {
// System.out.println("");
System.out.println(e.getMessage());
// numberOfTestCases.next();
}
System.exit(0);
}
}
I can't figure out where I'm going wrong; I've tried all possible test cases.
P.S.: The problem assumes all inputs to be parenthesized; there's no need to include any code for resolving operator precedence.

return valueStack.toString();
This doesn't return the required format: it returns a comma-separated format bounded by [ and ], which isn't what is specified.
But I'm sure there are other problems.
I don't see anything in the problem statement that corresponds to your PS: on the contrary, it specifically mentions operator precedence.
Are you sure you've 'tried all possible test cases'? Try (1+2)/3 and 1+3/2.
You're peeking something you haven't pushed in the case of ')'.
I don't see why you need two stacks either.
Given the problem statement, what you need is either a recursive-descent expression parser or the Dijkstra Shunting-yard algorithm.

Related

Remove all the words in a string that are in round brackets in java?

The input is a (good) example((eo)--)e). I have used an iterative way.
I tried with the following code:
public String scartaParentesi(String s)
{
ups = s.replaceAll("\\([^()]*\\)", "");
return ups;
}
The output of this code is a example(--)e).
The expected output is a examplee).
Based on description and comments, you can do:
String str = "a (good) example((eo)--)e";
StringBuilder stringBuilder = new StringBuilder();
int openedParenthesesCount = 0;
for (char c : str.toCharArray()) {
if (c == '(') {
openedParenthesesCount++;
} else if (c == ')') {
openedParenthesesCount--;
} else if (openedParenthesesCount == 0) {
stringBuilder.append(c);
}
}
System.out.println(stringBuilder);
Output:
a examplee
Assumption - number of '(' equals to number of ')'.
A more robust solution without any assumptions of the number of opening and closing braces:
String text = "a (good) example((eo)--)e)";
StringBuilder outText = new StringBuilder();
Deque<Character> stack = new ArrayDeque<Character>();
int i=0;
while (i<text.length()) {
if (text.charAt(i) == '(') {
stack.addFirst(text.charAt(i));
i++;
}
while (!stack.isEmpty()) {
if (text.charAt(i) != ')') {
stack.addFirst(text.charAt(i));
i++;
} else {
if (stack.removeFirst() == '(') {
i++;
}
}
}
outText.append(text.charAt(i));
i++;
}
Output:
before: a (good) example((eo)--)e)
after: a examplee)
You can also use your original String replaceAll method by putting it on a loop, replacing the same pattern on the last updated string. The break condition of the loop will be checking if 2 consecutive iterations output the same string, i.e. no pattern to replace:
String prev = text.replaceAll("\\([^()]*\\)", "");
while (!text.equals(prev)) {
prev = text;
text = text.replaceAll("\\([^()]*\\)", "");
}
System.out.println("after2: " + text);

Abbreviation expander for a given lexicon

I am trying to write a program that will allows users to make short blog entries by typing abbreviations for common words. On completion of the input, Program will expand the abbreviations according to the lexicon defined.
Conditions
A substituted word must be the shortest word that can be formed by adding zero or more letters (or punctuation symbols) to the abbreviation.
If two or more unique words can be formed by adding the same number of letters, then the abbreviation should be printed as it is.
Input
The input is divided into two sections.
The first section is the lexicon itself, and the second section is a user's blog entry that needs to be expanded. The sections are divided by a single | character.
For example:-
cream chocolate every ever does do ice is fried friend friends lick like floor favor flavor flower best but probably poorly say says that what white our you your strawberry storyboard the | wht flvr ic crm ds yr bst fnd lke? ur frds lk stbry, bt choc s prly th bs flr vr!
Output
what flavor ice cream does your best friend like? our friends lk strawberry, but chocolate is poorly the best floor ever!
I have written the program for this and tested it locally with many different test cases with success but it fails on submission to test server.
An automated Test suit runs to validate the program’s output on its submission to test server. In case of failure, details of the failing test case/cases are not visible.
Below is the program
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.StringTokenizer;
public class BlogEntry {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
String[][] info = readInput();
String[] output = inputExpander(info[0],info[1]);
//System.out.println();
for(int i = 0; i < output.length; ++i) {
if(i!=0)
System.out.print(" ");
System.out.print(output[i]);
}
}
public static String[][] readInput() {
BufferedReader bufferReader = new BufferedReader(new InputStreamReader(
System.in));
String input = null;
String[][] info = new String[2][];
String[] text;
String[] abbr;
try {
input = bufferReader.readLine();
StringTokenizer st1 = new StringTokenizer(input, "|");
String first = "", second = "";
int count = 0;
while (st1.hasMoreTokens()) {
++count;
if(count == 1)
first = st1.nextToken();
if(count == 2)
second = st1.nextToken();
}
st1 = new StringTokenizer(first, " ");
count = st1.countTokens();
text = new String[count];
count = 0;
while (st1.hasMoreTokens()) {
text[count] = st1.nextToken();
count++;
}
st1 = new StringTokenizer(second, " ");
count = st1.countTokens();
abbr = new String[count];
count = 0;
while (st1.hasMoreTokens()) {
abbr[count] = st1.nextToken();
count++;
}
info[0] = text;
info[1] = abbr;
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return info;
}
public static String[] inputExpander(String[] text, String[] abbr) {
String[] output = new String[abbr.length];
boolean result;
for (int i = 0; i < abbr.length; ++i) {
String abbrToken = abbr[i];
char[] char_abbr_token = abbrToken.toCharArray();
for (int j = 0; j < text.length; ++j) {
String textToken = text[j];
boolean flag2 = false;
if ((char_abbr_token[char_abbr_token.length - 1] == '!')
|| (char_abbr_token[char_abbr_token.length - 1] == '?')
|| (char_abbr_token[char_abbr_token.length - 1] == ',')
|| (char_abbr_token[char_abbr_token.length - 1] == ';')) {
flag2 = true;
}
char[] char_text_token = textToken.toCharArray();
result = ifcontains(char_text_token, char_abbr_token);
if (result) {
int currentCount = textToken.length();
int alreadyStoredCount = 0;
if (flag2)
textToken = textToken
+ char_abbr_token[char_abbr_token.length - 1];
if (output[i] == null)
output[i] = textToken;
else {
alreadyStoredCount = output[i].length();
char[] char_stored_token = output[i].toCharArray();
if ((char_stored_token[char_stored_token.length - 1] == '!')
|| (char_stored_token[char_stored_token.length - 1] == '?')
|| (char_stored_token[char_stored_token.length - 1] == ',')
|| (char_stored_token[char_stored_token.length - 1] == ';')) {
alreadyStoredCount -= 1;
}
if (alreadyStoredCount > currentCount) {
output[i] = textToken;
} else if (alreadyStoredCount == currentCount) {
output[i] = abbrToken;
}
}
}
}
if(output[i] == null)
output[i] = abbrToken;
}
return output;
}
public static boolean ifcontains(char[] char_text_token,
char[] char_abbr_token) {
int j = 0;
boolean flag = false;
for (int i = 0; i < char_abbr_token.length; ++i) {
flag = false;
for (; j < char_text_token.length; ++j) {
if ((char_abbr_token[i] == '!') || (char_abbr_token[i] == '?')
|| (char_abbr_token[i] == ',')
|| (char_abbr_token[i] == ';')) {
flag = true;
break;
}
if (char_abbr_token[i] == char_text_token[j]) {
flag = true;
break;
}
}
if (!flag)
return flag;
}
//System.out.println("match found" + flag);
return flag;
}
}
Can someone direct/hint me to/about the possible use case which I may have missed in the implementation? Thanks in advance.
Ran your program with duplicate word in input (lexicon). When a word is repeated in the lexicon, it is not getting expanded because the check is only on the length(line no. 112) of the stored word not its content.
I think you need to check:-
If same word appears more than once then expand.
If 2 or more unique words of same length appear then keep it short.
How would I approach solving this:
Parse the input, tokenize the lexicon and the text.
For each (possibly abbreviated) token like choc convert it to a regular expression like .*c.*h.*o.*c.*.
Search for shortest lexicon words matching this regular expression. Replace the text token if exactly one is found, otherwise leave it alone.
It is quite hard to say what's wrong with your code without careful debugging. It is hard to understand what one or the other part of the code does, it's not quite self-evident.

How do you double each letter in a string using a for loop and an if statement in java

I need to double each letter in a string using a for loop and an if-then statement. How can you comb through a string and test if each character is a letter or a symbol like an exclamation point? And then print the string back out with each letter doubled and each exclamation point tripled.
This is what I have so far. It's unfinished and it doesn't work at all, but am I on the right track?
import java.util.Scanner;
public class DoubleLetters{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println("Enter a sentence:");
String sentence = scan.nextLine();
boolean isLetter = false;
for (int i = 0; i < sentence.length(); i++){
isLetter = Character.isLetter(sentence.charAt(i));
if (i == sentence.length() || sentence.charAt(i) == ' ' || isLetter == false){
System.out.print(sentence.charAt(i) + sentence.charAt(i));
}
}
It looks like you were on the right way, then passed the right exit and carried on the wrong way.
for (int i = 0; i < sentence.length(); i++){ [...] } is a right way to iterate over a string's characters.
Character.isLetter(c) is a right way to check whether a character is a letter.
However, your condition is chaotic :
why would you make special conditions for spaces and end characters?
why is your isLetter condition negated?
I think your condition should simply be
if (isLetter) { /* print twice */ }
else if (isExclamationPoint) { /* print "thrice" */ }
else { /* print once */ }
Try this:
import java.util.*;
public class DoubleLetters{
public static void main(String[] args){
Scanner scan = new Scanner(System.in);
System.out.println("Enter a sentence:");
String sentence = scan.nextLine();
StringBuilder sb = new StringBuilder();
for (Character c: sentence.toCharArray()){
sb.append(c);
if(Character.isLetter(c)){
sb.append(c);
}
else if(c == '!'){
sb.append(c).append(c);
}
}
sentence = sb.toString();
System.out.println(sentence);
}
}
When manipulating strings like this, it is best to use StringBuilder, which allocates a contiguous character buffer of a given size. You can count how big your output String needs to be, and pass this size to the StringBuffer on construction.
I would also recommend continuing to call String.charAt for maximum efficiency.
You may also want to encapsulate your routine in a function. You can take the input as a CharSequence for maximum utility.
public class DoubleLetters {
private static int getRepetitionCount(char c) {
if (Character.isLetter(c)) {
return 2;
} else if (c == '!') {
return 3;
} else {
return 1;
}
}
public static String doubleLetters(CharSequence in) {
int inLength = in.length();
int outLength = 0;
for (int i = 0; i < inLength; ++i) {
outLength += getRepetitionCount(in.charAt(i));
}
StringBuilder out = new StringBuilder(outLength);
for (int i = 0; i < inLength; ++i) {
char c = in.charAt(i);
int reps = getRepetitionCount(c);
for (int r = 0; r < reps; ++r) {
out.append(c);
}
}
return out.toString();
}
public static void main(String[] args) {
String test = "hello! world!";
System.out.print(doubleLetters(test));
}
}
In this specific case, you could alternatively allocate a buffer of size 3 * inLength, which will be large enough to hold any potential output string.

What is causing me to get this EmptyStackException?

My program takes a postfix expression and changes it to an infix expression.
I have included two reasons for error in the code which is if the program does not have enough operators and if the input is not a valid number or operator.
The errors are caught when I put in input that is not good, however, when putting correct input in the scanner it gives me this error:
Exception in thread "main" java.util.EmptyStackException
at java.util.Stack.peek(Stack.java:102)
at java.util.Stack.pop(Stack.java:84)
at PostfixToInfix.change(PostfixToInfix.java:67)
at PostfixToInfix.main(PostfixToInfix.java:27)
What needs to be changed in my code?
Code:
import java.util.Scanner;
import java.util.Stack;
import java.util.EmptyStackException;
public class PostfixToInfix
{
int x = 0;
public static void main(String[] args)
{
PostfixToInfix exp = new PostfixToInfix();
Scanner stdin =new Scanner(System.in);
try {
boolean inputNeeded = true;
int value = 0;
while(inputNeeded){
System.out.print("Postfix : ");
if(stdin.hasNextInt()){
inputNeeded = false;
}
else{
throw new Error("Not a number or valid operator");
}
}
String pf = stdin.nextLine().replaceAll("\\s+", "");
System.out.println("Infix : "+exp.change(pf));
}
catch (EmptyStackException e) {
System.out.println("Too few operators to produce a single result.");
}
}
static boolean isOperator(char c)
{
if(c == '+' || c == '-' || c == '*' || c =='/' || c == '^')
{
return true;
}
return false;
}
boolean empty() //whether the stack is empty
{
return x == 0;
} // end empty
public String change(String pf)
{
Stack<String> s = new Stack<>();
for(int i = 0; i < pf.length(); i++)
{
char z = pf.charAt(i);
if(isOperator(z))
{
String x = s.pop();
String y = s.pop();
s.push("("+y+z+x+")");
}
else
{
s.push(""+z);
}
}
return s.pop();
}
}
Consider the input 1 1 +.
The Scanner reads the 1 and stores it in value.
The Scanner reads the remaining string and a modified version of it ("1+") is stored in pf, which is passed as an argument to the change method.
charAt returns the first character of pf (a '1'), isOperator returns false, and the else block executes, which pushes "1" to the Stack.
charAt returns the second character of pf (a '+'), isOperator returns true, and the if block executes.
pop is called once, removing the only element in the stack, "1", and assigning it to x. The stack is now empty, and the second call to pop results in the EmptyStackException.
This is how to debug your code if your IDE does not have a debugger already. Through this, you should find that using nextInt is the issue, since only one number will be present in the remaining string when the if block is expecting two.

JAVA: Parentheses match method not printing

Hey I am doing a programming assignment and we have to match parentheses in a String. We have to output an Error message such as the following:
Sample I/O:
Enter a string to test:
( < [ { } ( { > ) ] >
error: '>' does not match with '{'.
I am trying to print this message in my isBalanced() method however it will not print the System.out.println() however it is reaching that code block (otherwise it would never return false) which it is. I think the problem lies in my main method but I have been trying for a while now and I am stumped!
Any help is appreciated.
Thanks,
Kyle.
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.EmptyStackException;
import java.util.Stack; //using java's default stack in this case as it has more extraneous error checking
public class Question3 {
private static final String OPEN = "([{<";
private static final String CLOSED = ")]}>";
public static void main(String[] args) throws IOException {
BufferedReader inKb = new BufferedReader(new InputStreamReader(
System.in));
System.out.println("Enter a test string:");
String input = inKb.readLine();
boolean successful = isBalanced(input);
System.out.println(successful);
}
public static void printError(char ch, char expected) {
System.out.println("Error: '" + ch + "' does not match with '"
+ expected + "'");
}
private static boolean isOpen(char bracket) {
return OPEN.indexOf(bracket) >= 0;
}
private static boolean isClosed(char bracket) {
return CLOSED.indexOf(bracket) >= 0;
}
private static boolean matches(char openBracket, char closedBracket) {
return OPEN.indexOf(openBracket) == CLOSED.indexOf(closedBracket);
}
public static boolean isBalanced(String input) {
Stack<Character> stack = new Stack<Character>();
try {
for (int i = 0; i < input.length(); i++) {
char ch = input.charAt(i);
if (isOpen(ch)) {
stack.push(ch);
} else if (isClosed(ch)) {
char corBracket = stack.pop(); // pop corresponding bracket
if (!matches(ch, corBracket)) {
System.out.println("Print Test!"); //Not printing?
return false;
}
}
}
} catch (EmptyStackException ex) {
return false;
}
return stack.isEmpty(); //if stack is empty then the corresponding bracket wasn't found!
}
}
In
if (!matches(ch, corBracket)) {
ch is the closing and corBracket is the opening. You need to reverse them
if (!matches(corBracket, ch)) {
to match the method semantics
private static boolean matches(char openBracket, char closedBracket) {
boolean value = OPEN.indexOf(openBracket) == CLOSED.indexOf(closedBracket);
return value;
}
You use descriptive names in the matches method. You should do the same everywhere else.
This is an example where it would be useful to use a debugger.
Debugging your application with the input ( < ) tells me that !matches(ch, corBracket) is evaluated as false and therefore your if statement is ignored. This leads us to believe that your matches(char, char) method is incorrect.
If you try changing your matches method to the following:
private static boolean matches(char openBracket, char closedBracket) {
int i1 = OPEN.indexOf(openBracket);
int i2 = CLOSED.indexOf(closedBracket);
return (i1 == i2);
}
You will see in your debugger that i1 and i2 are both -1 (the return value of indexOf in the case of no occurrence) and since -1 == -1 evaluates to true, !(-1 == -1) evaluates to false, as expected.
Hope this helps.
You are looking for opening brakets in CLOSED and for closing brackets in OPENED!
you need to change
return OPEN.indexOf(openBracket) == CLOSED.indexOf(closedBracket);
into
return CLOSED.indexOf(openBracket) == OPEN.indexOf(closedBracket);
or just swap the parameters in your call
matches(corBracket, ch)
instead of
matches(ch, corBracket)
debuging into the call that function would have show you that OPEN.indexOf(openBracket) return -1 witch is supicious since you are expecting to find what you are searching for i.e. an index which is greater or equal than 0 and less than OPEN.length()

Categories