How to solve an expression from user input not using parentheses? - java

I'm trying to write a program that evaluates an expression the user inputs. I know I need to have separate methods so It evaluates multiplication and division first then adds the addition and subtraction afterwards. This is what I got so far. When I try anything involving multiplication or division, like 6*6, it will only print the first character, which would be just '6' in this instance. Any ideas?
import java.util.Scanner;
class Expressions {
String e;
void setExpressions(String exp) {
e = exp;
}
String evaluate() {
String n = "";
for (int i = 0; i < e.length(); i++)
if (e.charAt(i) == '*' || e.charAt(i) == '/') {
n += e.charAt(i);
}
else if (e.charAt(i) == '+' || e.charAt(i) == '/') {
evaluateMD();
n = "";
}
else
n += e.charAt(i);
return n;
}
int evaluateMD () {
int r = 1;
int n = 0;
char op = '*';
for (int i = 0; i < evaluate().length(); i++)
if (evaluate().charAt(i) == '*' || evaluate().charAt(i) == '/') {
if (op == '*')
r *= n;
else
r /= n;
n = 0;
op = evaluate().charAt(i);
}
else if (evaluate().charAt(i) == '*' || evaluate().charAt(i) == '/')
n = 0;
else //digits
n = n*10 + (evaluate().charAt(i)-'0');
if (op == '+') //last operation
r *= n;
else
r /= n;
return r;
}
int evaluateAS() {
//e has +, - only, multiple digit numbers
int r = 0;
int n = 0;
char op = '+';
for (int i = 0; i < e.length(); i++)
if (e.charAt(i) == '+' || e.charAt(i) == '-') {
if (op == '+')
r += n;
else
r -= n;
n = 0;
op = e.charAt(i);
}
else if (e.charAt(i) == '*' || e.charAt(i) == '/')
n = 0;
else //digits
n = n*10 + (e.charAt(i)-'0');
if (op == '+') //last operation
r += n;
else
r -= n;
return r;
}
}
public class hw10 {
public static void main(String[] args) {
Scanner in = new Scanner (System.in);
Expressions myE = new Expressions();
System.out.print("Enter E:");//E for expression
String e = in.next();
myE.setExpressions(e);
//int r = myE.evaluate1();
int r = myE.evaluateAS();
System.out.println(e+" = "+r);
}
}

If I needed to write arithmetic expressions parser, I would use pretty simple approach: get the input from user, translate it into reverse polish notation (take a look at section named Shunting-yard algorithm), and evaluate it.
Robert Lafore in his "Data Structures and Algorithms in Java" has pretty easy explanation of both algorithms - translation from infix to RPN and evaluation of expressions written in RPN, with the source code, so you can see how it can be implemented. After you read it, it'll be easy to mix both algorithms into one - take a look at one of my questions on this topic.

Changing the line
if (op == '+') //last operation
in the evaluateMD method to
if (op == '*') //last operation
,changing the return type of the method to double and making r and n doubles produces better results for the evaluateMD, but really you're overall procedure needs an overhaul, if not complete abandonment.
I think your it would be better if your evaluate method only returned the answer to the calculation.
It would only ever need to store 2 values at most: (in the case that you have an AS operation you would store it if the next operator was MD since MD needs to be evaluated first, but once the MD operation (which could involve more than one operator or more than one instance of the same operator i.e. 4*5*6 or 4/3*2) is computed you can then perform the 'waiting' AS immediately. For MD operations, you'd just store the latest update each time, as you almost had working in your evaluateMD method (which I think works with the modification I put at the top. If it doesn't feel free to ask me about it as I did make a few other changes).
This is an improvement on the method you were attempting, but as I said there may well be methods which are better still mentioned in other answers.

Related

multiplying bigintegers without bigintegers

Hey' all so im figuring out how to multiply bigintegers without importing them and I have it almost all. The only thing that isnt working is when multiplying with -digit the output is still +. any help appreciated. ie. -20*4=80
Scanner scan = new Scanner(System.in);
System.out.println("Type the first number:");
String x = scan.nextLine();
System.out.println("Type the second number:");
String y = scan.nextLine();
if (x.charAt(0) == '-' && y.charAt(0) != '-') {
x = x.substring(1);
}
else if (x.charAt(0) != '-' && y.charAt(0) == '-') {
y = y.substring(1);
}
else if (x.charAt(0) == '-' && y.charAt(0) == '-') {
x = x.substring(1);
y = y.substring(1);
}
String s1 = new StringBuffer(x).reverse().toString();
String s2 = new StringBuffer(y).reverse().toString();
int[] m = new int[s1.length() + s2.length()];
for (int i=0; i<s1.length(); i++) {
for (int j=0; j<s2.length(); j++) {
m[i+j] = m[i+j] + (s1.charAt(i) - '0') * (s2.charAt(j) - '0');
}
}
String product = new String();
for (int i=0; i<m.length; i++) {
int digit = m[i] % 10;
int carry = m[i] / 10;
if (i+1 < m.length) {
m[i+1] = m[i+1] + carry;
}
product = digit + product;
}
while (product.length() > 1 && product.charAt(0) == '0') {
product = product.substring(1);
}
if (x.charAt(0) == '-' && y.charAt(0) != '-') {
product = new StringBuffer(product).insert(0, '-').toString();
}
else if (x.charAt(0) != '-' && y.charAt(0) == '-') {
product = new StringBuffer(product).insert(0, '-').toString();
}
else if (x.charAt(0) == '-' && y.charAt(0) == '-') {
product = product;
}
System.out.println("The multiplication of\n" + x + " \nand\n" + y + " " + "\nis\n" + product);
scan.close();
}
}
You're removing the negative symbol from the numbers here:
if (x.charAt(0) == '-' && y.charAt(0) != '-') {
x = x.substring(1);
}
else if (x.charAt(0) != '-' && y.charAt(0) == '-') {
y = y.substring(1);
}
So after those lines your x and y variables no longer contain the negative symbol.
So when you're checking it near the end here:
if (x.charAt(0) == '-' && y.charAt(0) != '-') {
product = new StringBuffer(product).insert(0, '-').toString();
}
else if (x.charAt(0) != '-' && y.charAt(0) == '-') {
product = new StringBuffer(product).insert(0, '-').toString();
}
else if (x.charAt(0) == '-' && y.charAt(0) == '-') {
product = product;
}
It will never get into any of the conditions.
One good way to debug this on your end is to set a breakpoint within the condition you think it should drop into and see if it's hit. Or breakpoint before the conditions and examine the variables to ensure they are what you expect them to be. You could also throw some println statements in there temporarily just to say "I got into this conditional".
The adjustment I'd recommend making is holding onto whether each number was negative before stripping the negative so you can use that in your logic later on.
Here's the adjustment which should accomplish what you want. I used Integers instead of bools to make the check for whether to apply the negative symbol later easier (i.e. isFirstNumberNegative + isSecondNumberNegative == 1)
Scanner scan = new Scanner(System.in);
System.out.println("Type the first number:");
String x = scan.nextLine();
System.out.println("Type the second number:");
String y = scan.nextLine();
// hold onto which numbers are negative
Integer isFirstNumberNegative = x.charAt(0) == '-' ? 1 : 0;
Integer isSecondNumberNegative = y.charAt(0) == '-' ? 1 : 0;
// strip the negative symbols from the numbers which are negative
if (isFirstNumberNegative > 0) {
x = x.substring(1);
}
if (isSecondNumberNegative > 0) {
y = y.substring(1);
}
String s1 = new StringBuffer(x).reverse().toString();
String s2 = new StringBuffer(y).reverse().toString();
int[] m = new int[s1.length() + s2.length()];
for (int i=0; i<s1.length(); i++) {
for (int j=0; j<s2.length(); j++) {
m[i+j] = m[i+j] + (s1.charAt(i) - '0') * (s2.charAt(j) - '0');
}
}
String product = new String();
for (int i=0; i<m.length; i++) {
int digit = m[i] % 10;
int carry = m[i] / 10;
if (i+1 < m.length) {
m[i+1] = m[i+1] + carry;
}
product = digit + product;
}
while (product.length() > 1 && product.charAt(0) == '0') {
product = product.substring(1);
}
// if only one number is negative put a negative symbol in front
// if both numbers are negative this condition won't hold true because it will be == 2
// if both numbers are positive this condition won't hold true because it wil be == 0
if (isFirstNumberNegative + isSecondNumberNegative == 1) {
product = new StringBuffer(product).insert(0, '-').toString();
}
System.out.println("The multiplication of\n" + x + " \nand\n" + y + " " + "\nis\n" + product);
scan.close();
Just remove the symbols from the numbers and save them. Then later, use them to determine if a negative is required. An exclusive or test for - is all that is necessary for a negative result.
You can create a record (or a class) to return the numbers and resulting sign, ready for processing.
record Numb(String sign,String num1, String num2) {}
String n1 = "-2123";
String n2 = "+2343";
Numb n = prepNums(n1,n2);
System.out.println(n.sign + ", " + n.num1 + " " + n.num);
Prints
-, 2123, 2343
After multiplying, just prepend the sign to the result. Note that the default positive sign is no sign.
And here is the method that processes the strings and returns
them and the resultant sign for multiplication.
public static Numb prepNums(String n1, String n2) {
boolean sign1 = false;
boolean sign2 = false;
char firstChar = n1.charAt(0);
if (!Character.isDigit(firstChar)) {
sign1 = firstChar == '-';
n1 = n1.substring(1); // remove sign
}
firstChar = n2.charAt(0);
if (!Character.isDigit(firstChar)) {
sign2 = firstChar == '-';
n2 = n2.substring(1); // remove sign
}
return new Numb( (sign1 ^ sign2) ? "-" : "", n1, n2);
}
just speaking in a generic concept sense - the square root of largest safe unsigned int,
4^3^3/2-1
is approx 94906265.6242. So right off the bat you know you don't have 8-full decimal digits width to work with unless you add in special tricks.
All those fancy algorithms they talk about - they frequently waste your time by having to first convert from decimal to binary, do the math, then re-convert it back out.
I just split mine into chunks of 7-digits wide, so the the maximum multiply result per op is capped at just shy of 10^14
- for 7 9's squaring each other, approx. 46.50699304-binary bits
- for 8 9's squaring ………. is approx. 53.15084949 bits
for whatever slowness one might believe in simpleton grade school multiply, you more than gain back the savings by avoiding a bidirectional base-conversion.

Check if string contains a character with for loop?

I am currently working on a simple code that will check if an user inputted String contains character(s) that are specified in the for loop.
My current code
import java.util.Scanner;
public class AutumnLeaves {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int G = 0;
int R = 0;
int Y = 0;
int B = 0;
String S = sc.nextLine();
for (int i = 0; i < S.length(); i++) {
if (S.contains("G")) {
G++;
} else {
if (S.contains("R")) {
R++;
} else {
if (S.contains("Y")) {
Y++;
} else {
if (S.contains("B")) {
B++;
}
}
}
}
}
int total = G + R + Y + B;
System.out.println(G/total);
System.out.println(R/total);
System.out.println(Y/total);
System.out.println(B/total);
}
}
As you can see, it checks if the string contains such characters and it will increase the counter of the character by one. However when I run it, I don't receive the results I predicted.
If I input GGRY, it outputs 1 0 0 0. When the desired out put is
0.5
0.25
0.25
0.0
Any help would be appreciated!
The problem is that S.contains returns true if the whole string contains the given character. S.charAt should solve your problem:
for (int i = 0; i < S.length(); i++) {
if (S.charAt(i) == 'G') G++;
else if (S.charAt(i) == 'R') R++;
else if (S.charAt(i) == 'Y') Y++;
else if (S.charAt(i) == 'B') B++;
}
Also, dividing integers will return an integer (rounded down). As such your output would always be 0 unless all the characters are the same. Just cast them to double before printing:
System.out.println((double) G/total);
System.out.println((double) R/total);
System.out.println((double) Y/total);
System.out.println((double) B/total);
Edit: As pointed out by Sumit Gulati in a comment, a switch statement will have better performance in Java 7. Also, as David Conrad pointed out using only ifs in the for loop would work too as the conditions are mutually exclusive.
Your earlier code S.contains("some character") was finding the index of the character in the entire string. Use S.charAt(i) to specifically find the index at ith location in the string.
Finally, you need to convert the integer to floating point in order to print output as floating values.
public class AutumnLeaves {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int G = 0;
int R = 0;
int Y = 0;
int B = 0;
String S = sc.nextLine();
for (int i = 0; i < S.length(); i++) {
if (S.charAt(i) == 'G') {
G++;
} else {
if (S.charAt(i) == 'R') {
R++;
} else {
if (S.charAt(i) == 'Y') {
Y++;
} else {
if (S.charAt(i) == 'B') {
B++;
}
}
}
}
}
int total = G + R + Y + B;
System.out.println(G * 1.0 / total);
System.out.println(R * 1.0 / total);
System.out.println(Y * 1.0 / total);
System.out.println(B * 1.0 / total);
}
}

Binary to Decimal - java

I want to write a program which receive a string value and print the decimal number.
In addition, if the string value is not 1 or 0, I need to print a message.
I wrote this code but it is always getting inside the if command.
I Would appreciate your support!
Thank you
import java.util.Random;
public class Decimal {
public static void main(String[] args) {
String input = (args[0]);
int sum = 0;
for (int i = 0; i <= input.length(); i++) {
if (!(input.charAt(i) == '0') || (input.charAt(i) == '1')) {
System.out.println("wrong string");
break;
}
char a = input.charAt(i);
if (a == '1') {
sum |= 0x01;
}
sum <<= 1;
sum >>= 1;
System.out.println(sum);
}
}
}
The ! (not) operator of the if statement only applies to the first part:
if ( ! (input.charAt(i) == '0')
||
(input.charAt(i) == '1')
) {
So that is the same as:
if ((input.charAt(i) != '0') || (input.charAt(i) == '1')) {
When you actually meant to do:
if (input.charAt(i) != '0' && input.charAt(i) != '1') {
It's a good thing though, because once that works, you're going to get an IndexOutOfBoundsException when i == input.length(). Change the loop to:
for (int i = 0; i < input.length(); i++) {
And for performance, move variable a up and use it in that first if statement. Rename to c or ch is more descriptive/common.
Doing both sum <<= 1 and sum >>= 1 leaves you where you started. Is that what you wanted? You should also do the left-shift before setting the right-most bit.
Applying all that, I believe you meant to do this:
String input = args[0];
int sum = 0;
for (int i = 0; i < input.length(); i++) {
char c = input.charAt(i);
if (c != '0' && c != '1') {
System.out.println("wrong string");
break;
}
sum <<= 1;
if (c == '1')
sum |= 1;
}
System.out.println(sum);

Java loop to evaluate all operators

I need to modify this code in order to use order of operations and to be able to multiply and divide but I have no idea where to start. I know if works for addition and subtraction but I just need to figure out how to make it multiply and divide.
import java.util.Scanner;
class Expressions {
String e;
void setExpressions(String exp){
e =exp;
}
int evaluate1(){
//e has +. -. only, single digit numbers
int r = e.charAt(0)-'0';
int l = e.length();
for(int i=1; i<=l-1; i++ )
if (e.charAt(i) == '+')
r += (e.charAt(i+1)-48);
else
r -= (e.charAt(i+1)-'0');
return r;
}
int evaluateAS(){
//e has +, -, only, multiple digit numbers
int r = 0;
int n = 0;
int op = '+'; //+, -
for(int i=0; i<e.length(); i++ ){
if (e.charAt(i) == '-' || e.charAt(i) == '+'){
if (op == '+')
r += n;
else
r -= n;
n = 0;
op = e.charAt(i);
}
else //digits
n = n*10+(e.charAt(i) - '0');
}
if (op == '+')
r += n;
else
r -= n;
return r;
}
}
public class Runner {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
Expressions myE = new Expressions();
System.out.println("Enter E: ");
String e = in.next();
myE.setExpressions(e);
//int r = myE.evaluate1();
int r = myE.evaluateAS();
System.out.println(e+" = "+ r);
}
}
Multiplication (or division) together with addition requires priority, which means that you cannot continue to evaluate your expression from left to right.
Usually, computation parsers use the reversed polish notation (http://en.wikipedia.org/wiki/Reversed_Polish_notation) which gives you a tree representation of the mathematical expression. The wikipedia article contains many information as too how to use this.
Typically, you'll use the Shunting-yard algorithm to convert your infix (usual) notation to RPN, then you'll see how easy it is to evaluate an expression represented in the RPN.

what is wrong with this java code? [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 10 years ago.
I was going through an ICPC question HERE
The problem boils down to finding maximum.'s which can be achieved with K operations in a matrix having * and . such that we are allowed to toggle elements in a row in one operation.I first toggled the rows which result in positive or zero(toggling a row 2 times gives 0 change) change in *'s in decreasing order. At the end, if there is 1 toggle left, toggle the row with the least absolute value amongst the rows having negative changes.
Here is my code - BELOW CODE IN IDEONE.COM WITH SOME TEST CASES
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
int t = sc.nextInt();
for (t = t; t > 0; t--) {
int n = sc.nextInt();
int m = sc.nextInt();
int k = sc.nextInt();
char[][] array = new char[n][m] ;
int[] tracker = new int[n];
int[] trackerl = new int[n];
int i,j;
for (i = 0; i < n; i++) {
String temp = sc.next();
for (j = 0; j < m; j++) {
array[i][j] = (temp.charAt(j));
}
}
int light = 0, diamond = 0;
for (i = 0; i < n; i++) {
for (j = 0; j < m; j++) {
if (array[i][j] == '*') {
diamond++;
}
}
tracker[i] = diamond;
diamond = 0;
}
int a, b;
int temp;
int sortTheNumbers = n;
for (a = 1; a < sortTheNumbers; a++) {
for (b = 0; b < sortTheNumbers-a; b++) {
if (tracker[b] > tracker[b + 1]) {
temp = tracker[b];
tracker[b] = tracker[b + 1];
tracker[b + 1] = temp;
}
}
}
for (i = 0; i < n; i++)
trackerl[i]=m-tracker[i];
int br = 0;
try {
if (m % 2 == 0) {
for ( i = 0; i <= n - 1; i++)
if (tracker[i] > (m) / 2)
br++;
}
if (m % 2 !=0 ) {
for (i = 0; i <= n - 1; i++)
if (tracker[i] >= (m + 1) / 2)
br++;
}
} catch (Exception e) {
}
int ans = 0;
try {
if (br >= k) {
for (i = n - 1; i > (n - 1 - k); i--)
ans += tracker[i];
for (i = (n - 1 - k); i >= 0; i--)
ans += trackerl[i];
}
if (br < k) {
if (br != 0 && br != n) {
for (i = n - 1; i > (n - br); i--) {
ans += tracker[i];
k--;
}
int pass1 = 0, pass2 = 0;
if (k % 2 == 0)
pass1 = Math.max(tracker[(n - br)] + tracker[(n - br - 1)],
trackerl[(n - br)] + trackerl[(n - br - 1)]);
if (k % 2 != 0)
pass2 = Math.max(tracker[(n - br)] + trackerl[(n - br - 1)],
trackerl[(n - br)] + tracker[(n - br - 1)]);
// System.out.print("Hp" + tracker[(n - br)]);
}
ans += Math.max(pass1, pass2);
for (i = (n - 2 - br); i >= 0; i--)
ans += trackerl[i];
}
if (br != 0 && br == n) {
for (i = n - 1; i > (n - br); i--) {
ans += tracker[i];
k--;
}
if (k % 2 != 0) {
ans += tracker[(n - br)];
}
if (k % 2 == 0) {
ans += trackerl[(n - br)];
}
for (i = (n - 1 - br); i >= 0; i--) {
ans += trackerl[i];
}
}
if (br == 0) {
if (k % 2 != 0) {
ans += tracker[(n - 1)];
}
if (k % 2 == 0) {
ans += trackerl[(n - 1)];
}
for (i = (n - 2); i >= 0; i--) {
ans += trackerl[i];
}
}
}
} catch (Exception e) {
}
System.out.println(""+ans);
}
}
}
Whichever test case I choose gives the correct answer. I maintained variety in my test cases, as you can see from the link.Still the code isn't correct as it is not accepted by the judge. I really can't find where is the flaw.Is it in my code or my logic? Please point it out for me.
Writing code is the same as writing a paper, there are grammar, spelling, punctuation, and other rules which make the code readable and the point clear. Studying these and writing clear code pays off, not just for others who need to read your code, but for you too (you will see more of your own errors).
I'll just point out a few items I ran across when formatting your code. (Examples are from memory and not your code)
if(x=3;y>(2-2-x);y++)
Don't write a line like this because
if is not a function, and choosing "if(" over "if (" makes it look a little more like a function. The same goes with the keyword while.
Putting multiple strings of arithmetic operations (especially '+' and '-') in a long line (as in "(2-2-x)" confuses the dual roles that the '-' character can play, you would be better off putting in spaces "(2 - 2 - x)" to make the reader realize that we are dealing with multiple subtractions, without a unary negation operation (negative number).
if statements require three parameters (separated by semicolons). putting in spaces after each parameter can signal the reader that they are in the "next" parameter. Favour "if (x=3; y>(2-2-x); y++)" over "if (x=3;y>(2-2-x);y++)".
In the continued example
if(x=3;y>(2-2-x);y++)
{x=3;y=2;}
The brackets on the following line create reading comprehension issues.
They are subject to the same formatting problems as having no brackets after an if statement. By putting your entire block on a line, you confuse blocks and lines, and any line reordering will dramatically affect the operation of your program. This is bad. To fix this, favour "if (x = 3; y >(2 - 2 - x); y++) {".
There is a compound statement on a single line which mimics the formatting of the if statement above it, which could confuse a reader into believing that this is part of a subsequent nested if statement. It is far more readable to put the two assignment statements on their own lines.
You tie the end of the block to a statement, which couples the block boundaries to a particular operation. Often one needs to update their code, and odds are slim that the statement and end of the block should be connected over the lifetime of the program. Favour putting the end of block delimiter on a non statement line.
All of the above points, when used together, result in code that looks like
if (x = 3; y > (2 - 2 - x); y++) {
x = 2;
y = 3;
}
After some simple formatting, it is clear that you have multiple blocks of "if this, then that". It is also clear that lots of these blocks follow a pattern, "If this, then that. If not this, then that". The language has a built-in ability to handle such a pattern with an "else" block attached to the prior if block.
(example directly from your code)
if (k % 2 != 0) {
ans += tracker[(n - 1)]
}
if (k % 2 == 0) {
ans += trackerl[(n - 1)];
}
which could much more cleanly be written
if (k % 2 != 0) {
ans += tracker[(n - 1)]
} else {
ans += trackerl[(n - 1)];
}
or, using reordering to emphasize the equality over the inequality
if (k % 2 == 0) {
ans += tracker1[(n - 1)]
} else {
ans += tracker[(n - 1)];
}
One could go on, but after you make changes like these, really your code is starting in a much better place, so it doesn't make sense to talk about higher level techniques of making your code readable until some of the basics are done. Even so, I will recommend that you use full words for your variable names that attempt to describe the variable's purpose.
Good luck, and in my reformatting, I might have clipped a closing block delimiter (they don't match up) or maybe it wasn't there in the first place (not like one could check in the unformatted version).

Categories