My program is working with expression like 12 + 3 * 45.But Its not working expression like 12*4+(7/2). please give correction in my code.I am attaching my code:
import java.util.Stack;
public class EvaluateString
{
public static int evaluate(String expression)
{
char[] tokens = expression.toCharArray();
// Stack for numbers: 'values'
Stack<Integer> values = new Stack<Integer>();
// Stack for Operators: 'ops'
Stack<Character> ops = new Stack<Character>();
for (int i = 0; i < tokens.length; i++)
{
// Current token is a whitespace, skip it
if (tokens[i] == ' ')
continue;
// Current token is a number, push it to stack for numbers
if (tokens[i] >= '0' && tokens[i] <= '9')
{
StringBuffer sbuf = new StringBuffer();
// There may be more than one digits in number
while (i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9')
sbuf.append(tokens[i++]);
values.push(Integer.parseInt(sbuf.toString()));
}
// Current token is an opening brace, push it to 'ops'
else if (tokens[i] == '(')
ops.push(tokens[i]);
// Closing brace encountered, solve entire brace
else if (tokens[i] == ')')
{
while (ops.peek() != '(')
values.push(applyOp(ops.pop(), values.pop(), values.pop()));
ops.pop();
}
// Current token is an operator.
else if (tokens[i] == '+' || tokens[i] == '-' ||
tokens[i] == '*' || tokens[i] == '/')
{
// While top of 'ops' has same or greater precedence to current
// token, which is an operator. Apply operator on top of 'ops'
// to top two elements in values stack
while (!ops.empty() && hasPrecedence(tokens[i], ops.peek()))
values.push(applyOp(ops.pop(), values.pop(), values.pop()));
// Push current token to 'ops'.
ops.push(tokens[i]);
}
}
// Entire expression has been parsed at this point, apply remaining
// ops to remaining values
while (!ops.empty())
values.push(applyOp(ops.pop(), values.pop(), values.pop()));
// Top of 'values' contains result, return it
return values.pop();
}
// Returns true if 'op2' has higher or same precedence as 'op1',
// otherwise returns false.
public static boolean hasPrecedence(char op1, char op2)
{
if (op2 == '(' || op2 == ')')
return false;
if ((op1 == '*' || op1 == '/') && (op2 == '+' || op2 == '-'))
return false;
else
return true;
}
// A utility method to apply an operator 'op' on operands 'a'
// and 'b'. Return the result.
public static int applyOp(char op, int b, int a)
{
switch (op)
{
case '+':
return a + b;
case '-':
return a - b;
case '*':
return a * b;
case '/':
if (b == 0)
throw new
UnsupportedOperationException("Cannot divide by zero");
return a / b;
}
return 0;
}
// Driver method to test above methods
public static void main(String[] args)
{
System.out.println(EvaluateString.evaluate("10 + 2 * 6"));
}
}
Let's take a look at your block which parses digits:
for (int i = 0; i < tokens.length; i++) {
// ...
if (tokens[i] >= '0' && tokens[i] <= '9')
{
StringBuffer sbuf = new StringBuffer();
// There may be more than one digits in number
while (i < tokens.length && tokens[i] >= '0' && tokens[i] <= '9')
sbuf.append(tokens[i++]);
values.push(Integer.parseInt(sbuf.toString()));
}
// ...
}
Let's assume our tokens are {'1', '+', '2'} and your initial i value is 0. We're entering the if-body (as tokens[0] == 1), declare an sbuf variable and again make exactly the same check for that i (but we're inside the if-block with the same check as your while condition). So, we're going inside while loop, append tokens[0] to sbuf and increase our i. So now i is 1 and points to +, while condition is false, we parse "1" into 1 and add it to values. But now the next iteration of outer for-loop begins and the i value will be 2. So, we totally missed + as we incremented it's value inside while-loop but haven't processed it in any way.
Now let's find an alternative approach:
for (int i = 0; i < tokens.length; i++) {
// ...
if (tokens[i] >= '0' && tokens[i] <= '9') {
StringBuilder sb = new StringBuilder();
sb.append(tokens[i]);
// There may be more than one digits in number
while (i + 1 < tokens.length && tokens[i + 1] >= '0' && tokens[i + 1] <= '9') {
sb.append(tokens[++i]);
}
values.push(Integer.parseInt(sb.toString()));
}
// ...
}
This approach adds the current value right after declaring sb (I changed StringBuffer to StringBuilder as there is no need to use thread-safe StringBuffer implementation). Next we're checking the next value of i without incrementing. If it is also a number we're incrementing i and appending it to sb. Otherwise no changes to i happens and it will still point to the same value (1 in our case). Now your outer for-loop will increment it and you'll correctly process +.
By the way, if you're writing parser it's better not only return values.pop() but also check that values.size() == 1. If the size is not one then the expression either is not correct or has not been parsed correctly.
Related
I am trying to create some code to read roman numerals and turn them into an integer. the issue im having is the 9s and 4s. I am able to get it to read if the 9 or 4 is inside a number (I.E LIV is 54 and LXI is 59) but by its self (IV and IX) it only reads 6 and 11.
here is my code:
public static void RomantoInt(String s) {
HashMap<Character, Integer> RomanNums = new HashMap<>();
int count = 0;
RomanNums.put('I', 1);
RomanNums.put('V', 5);
RomanNums.put('X', 10);
RomanNums.put('L', 50);
RomanNums.put('C', 100);
RomanNums.put('D', 500);
RomanNums.put('M', 1000);
LinkedList<Character> UserInput = new LinkedList<>();
//Adds Each numeral to the Array
for (int i = 0; i < s.length(); i++) {
char userint = s.charAt(i);
UserInput.add(userint);
}
//loop through the array backwards and adds up the count.
for(int j =UserInput.toArray().length -1; j> -1 ; j--) {
int grab = RomanNums.get(UserInput.get(j));
count += grab;
// Checks for 4s and 9s.
if(grab == RomanNums.get('X') && (j - 1) == RomanNums.get('I')) {
count -= 2;
}
}
System.out.println(count);
Comparing j - 1 -- which is a position in a string -- to the value of a roman numeral does not seem to make any sense.
Specifically, it only works when the roman 'I' is the second character, exactly.
What you really want to be testing is whether the character at the (j-1)'th position is 'I'.
The correct formulation should be something like
if (grab == RomanNums.get('X') &&
j > 0 &&
UserInput.get(j-1) == 'I') ...
This was my solution for leetcode: https://leetcode.com/problems/roman-to-integer/
You have the right idea about reading the input backwards and one loop should be enough to get the job done.
All you need to do is account for the cases when you have to subtract the roman numeral, and you can do that by keeping track of the previous roman numeral for comparison.
For example when input string is: "IX"
We start at 'X' in the first iteration and since previous is equal to '?' we just add 10 and set previous to 'X'. Now when we attempt to sum up 'I' in the next iteration, we look at previous and notice that it is an 'X' and instead of adding 1 to the running sum , we should subtract 1. The total should be 9.
public int romanToInt(String s) {
int sum = 0;
char prev = '?';
for(int i = s.length()-1;i >= 0;i--) {
switch(s.charAt(i)) {
case 'I' : sum += prev == 'V' || prev == 'X' ? -1 : 1;
break;
case 'V' : sum += 5;
break;
case 'X' : sum += prev == 'L' || prev == 'C' ? -10 : 10;
break;
case 'L' : sum += 50;
break;
case 'C' : sum += prev == 'D' || prev == 'M' ? -100 : 100;
break;
case 'D' : sum += 500;
break;
case 'M' : sum += 1000;
break;
default :
break;
}
prev = s.charAt(i);
}
return sum;
}
Time complexity is O(n) - Iterated the length of the input string
Space complexity is O(1) - No additional data structure was needed
I do have a question. I have to determine if the input string is indeed a valid four character double literal
Consists of exactly the following characters: ’+’, ’-’, ’.’ (decimal point), and ’0’ through ’9’
Either the ’+’ or ’-’ character may appear only as the first character
The ’.’ (decimal point) character must appear exactly once
All other characters must be the ’0’ through ’9’ characters
my big problems is to put the +- at the first character and . once
Try this -
static boolean isValid(String s) {
// 1
if (s.length() != 4) return false;
String digits = "0123456789";
// 2
if (s.charAt(0) != '+' && s.charAt(0) != '-' && digits.indexOf(s.charAt(0)) == -1) return false;
byte decimalCount = 0;
for (int i = 1; i < 4; i++) {
if (s.charAt(i) == '.') decimalCount++;
// 4
else if (digits.indexOf(s.charAt(i)) == -1) return false;
}
//3
return decimalCount == 1;
}
I'm supposed to create a program that finds the longest palindrome in a DNA string. Unlike a regular palindrome program, this one requires A to match with T and C to match with G (so instead of 1221 we'd have TCGA for example). After trying myself I did find a very good program for the normal palindrome problem, the one on this website:
http://www.journaldev.com/530/java-program-to-find-out-longest-palindrome-in-a-string
I then tried to modify it to fit my needs. Basically the changes I made were the following:
Instead of those strings shown in the example, I read a string from the argument line. The string is the following DNA sequence (although I tested the program with only parts of it):
http://introcs.cs.princeton.edu/java/31datatype/genomeVirus.txt
Instead of the command
while (left >= 0 && right < s.length()
&& s.charAt(left) == s.charAt(right)) {
left--;
right++;
}
I did:
while (left >= 0 && right < s.length()
&& s.charAt(left) == 'A' && s.charAt(right) == 'T' || s.charAt(left) == 'T' && s.charAt(right) == 'A'
|| s.charAt(left) == 'G' && s.charAt(right) == 'C' || s.charAt(left) == 'C' && s.charAt(right) == 'G')
{
left--;
right++;
(Full code below)
However, when I try this program on a string, I always get the error:
java.lang.StringIndexOutOfBoundsException: String index out of range: -1
at java.lang.String.substring(Unknown Source)
at LongestPalindrome.intermediatePalindrome(LongestPalindrome.java:17)
at LongestPalindrome.longestPalindromeString(LongestPalindrome.java:26)
at LongestPalindrome.main(LongestPalindrome.java:5)
I just don't get it! I don't realize how I'm getting out of the string, when I try the original program I linked to, it always works with no matter which string. I feel like I'm doing everything correctly, simply replacing the == command with various scenarios that should make sense.
I figured it might have something to do with
return s.substring(left+1, right);"
I tried to take the +1 away but it seems to ruin the whole deal. I just don't realize how I'm going out of the string, since it worked perfectly before my adjustments.
Any help would be greatly appreciated! Below is the code!
public class LongestPalindrome {
public static void main(String[] args) {
String gen = new String(args[0]);
System.out.println(longestPalindromeString(gen));
}
static public String intermediatePalindrome(String s, int left, int right) {
if (left > right) return null;
while (left >= 0 && right < s.length()
&& s.charAt(left) == 'A' && s.charAt(right) == 'T' || s.charAt(left) == 'T' && s.charAt(right) == 'A'
|| s.charAt(left) == 'G' && s.charAt(right) == 'C' || s.charAt(left) == 'C' && s.charAt(right) == 'G')
{
left--;
right++;
}
return s.substring(left+1, right);
}
// O(n^2)
public static String longestPalindromeString(String s) {
if (s == null) return null;
String longest = s.substring(0, 1);
for (int i = 0; i < s.length() - 1; i++) {
//odd cases like 121
String palindrome = intermediatePalindrome(s, i, i);
if (palindrome.length() > longest.length()) {
longest = palindrome;
}
//even cases like 1221
palindrome = intermediatePalindrome(s, i, i + 1);
if (palindrome.length() > longest.length()) {
longest = palindrome;
}
}
return longest;
}
}
You are calling it with right == 0. You need to change the first call to:
String palindrome = intermediatePalindrome(s, i, i+1)
Operator precedence problem. You've added some || conditions which are also evaluated even if the range checks fail. It should be:
while (left >= 0 && right < s.length()
&& (s.charAt(left) == 'A' && s.charAt(right) == 'T'
|| s.charAt(left) == 'T' && s.charAt(right) == 'A'
|| s.charAt(left) == 'G' && s.charAt(right) == 'C'
|| s.charAt(left) == 'C' && s.charAt(right) == 'G'))
Note the parentheses around the entire second operand of the second &&.
So I am doing some practice problems for an upcoming exam and one of the problems is posing a bit of a challenge to me.
The problem states that our code should take a string that has been encoded and decode it. It must work as follows:
Each letter is decoded using the letter immediately before it in the alphabet ("b" becomes "a", "c" becomes "b" ect.)
"a" becomes "z".
each digit works the same way, 8 becomes 7, 5 becomes 4.
0 becomes 9.
characters neither letters nor digits are unchanged.
THE ONLY JAVA METHOD I CAN USE IS IO
Ex:
NFFU NF BU 23 JO UIF CFMM UPXFS
meet me at 12 in the bell tower
heres my current code, i cannot decide whether to use for loops or not. TBH I am not really sure how to tackle this.
public class prb1 {
public static void main(String[] args) {
char letter[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'};
int num[]={0,1,2,3,4,5,6,7,8,9};
System.out.println("Enter Message");
String mssg=IO.readString();
for(char i=0; i<letter.length; i++){
System.out.print(letter[i]--);}
for(int j=0; j<num.length; j++){
System.out.print(num[j]--);
}
}
}
The basic is like this. But this doesn't account yet for the a => z conversion.
String cypher ="ABCDEF";
String plain = "";
for (char c : cypher.toCharArray())
plain += (char) (c - 1);
System.out.println(plain);
With the modulo A => Z, it looks like this:
int A = 'A';
plain += (char) (((c - A - 1 + 26) % 26) + A);
The +26 is needed because java says -1 % 26 == -1 instead of 25.
So this just works for A-Z, but you can easily modify it to work for wider ranges.
You can use a loop to iterate through each character of the message and subtract one from its ascii code if its not a space, an a, or an A:
String message = "NFFU NF BU 23 JO UIF CFMM UPXFS";
String result = "";
for (char thisChar : message.toCharArray()) {
if (thisChar == ' ') {
result += " ";
} else if(thisChar == 'a') {
result += 'z';
} else if (thisChar == 'A') {
result += 'Z';
} else
result += (char)(thisChar - 1);
}
}
System.out.println(result);
Alternatively, you could do:
String message = "NFFU NF BU 23 JO UIF CFMM UPXFS";
String result = "";
for (int i = 0; i < message.length(); i ++) {
char thisChar = message.charAt(i);
if (thisChar == ' ') {
result += " ";
} else if(thisChar == 'a') {
result += 'z';
} else if (thisChar == 'A') {
result += 'Z';
} else
result += (char)(thisChar - 1);
}
}
System.out.println(result);
Technically,
else if(thisChar == 'a') {
result += 'z';
} else if (thisChar == 'A') {
result += 'Z';
}
could be shortened to:
else if(thisChar == 'a' || thisChar == 'A') {
result += (char)(thisChar + 25);
}
I'm having a bit of trouble with detecting a CHAR in an if statement.
I have a score integer, which i made in to a String, and from the string, i made a char Array.
My problem is, that when i try to detect what number the char is, it returns the "Error.png".
Please help me :)
code:
scoreString = "" + score;
System.out.println(scoreString + " - " + scoreString.length());
scoreA = scoreString.toCharArray();
for(int counter = 0; counter < scoreString.length(); counter++){
Texture drawT;
if(scoreA[counter] == 0) drawT = i0;
else if(scoreA[counter] == 1) drawT = i1;
else if(scoreA[counter] == 2) drawT = i2;
else if(scoreA[counter] == 3) drawT = i3;
else if(scoreA[counter] == 4) drawT = i4;
else if(scoreA[counter] == 5) drawT = i5;
else if(scoreA[counter] == 6) drawT = i6;
else if(scoreA[counter] == 7) drawT = i7;
else if(scoreA[counter] == 8) drawT = i8;
else if(scoreA[counter] == 9) drawT = i9;
else drawT = error;
MainClass.batch.draw(drawT, 5 + (9 * counter), 95);
}
scoreA[counter] == 1 compares a character to the numerical value of 1, which is not correct. '1' is not the same thing as 1. In fact, '1' is actually equal to 31 in hex. Use something like:
if(scoreA[counter] == '0') drawT = i0;
else if(scoreA[counter] == '1') drawT = i1;
//continue on
I obviously included a short snippet but it should be enough.
You want character literals.
You need to write
if(scoreA[counter] == '1')
Your mistake is thinking that the char representation for numbers are the same as the numbers themselves - they're not. chars represent ASCII characters (strictly speaking unicode but for this purpose we can just assume ASCII), so the code of the character 0 is NOT the number 0. To fix the problem you can just use char literals in your comparisons:
if(scoreA[counter] == '0') drawT = i0;
else if(scoreA[counter] == '1') drawT = i1;
... etc
Always you have to set character literals with in the single coats
i.e.
scoreA[counter] == '0'