Simple math-to-english calculator - java

I'm currently taking a basic programming course. The teacher refuses to look at my code and attempts to guess the question I'm asking, and then answer that (incorrect) question. The basics of this is, it's supposed to take an equation, like 5 * 6, and output "Five times six equals 30," with the answer just being a number. The code I have right now is as such:
package mainPackage;
import java.util.*;
public class Main
{
public static void main(String[]args)
{
Scanner scan = new Scanner(System.in);
System.out.println("Please enter the equation");
String input = scan.nextLine();
String space = " ";
int firstSpace = 0;
int secondSpace = 0;
int numInt1 = 0;
int numInt2 = 0;
String a = "0";
char b = 'a';
String c = "0";
firstSpace = input.indexOf(space);
String sub = input.substring((firstSpace + 1), input.length());
secondSpace = sub.indexOf(space);
a = input.substring(firstSpace--);
b = input.charAt(firstSpace++);
c = input.substring(secondSpace++);
numInt1 = Integer.parseInt(a);
numInt2 = Integer.parseInt(c);
String num1 = "";
String op = "";
String num2 = "";
switch (numInt1)
{
case 0:
{
num1 = "Zero";
}
case 1:
{
num1 = "One";
}
case 2:
{
num1 = "Two";
}
case 3:
{
num1 = "Three";
}
case 4:
{
num1 = "Four";
}
case 5:
{
num1 = "Five";
}
case 6:
{
num1 = "Six";
}
case 7:
{
num1 = "Seven";
}
case 8:
{
num1 = "Eight";
}
case 9:
{
num1 = "Nine";
}
}
System.out.println(a);
System.out.println(b);
System.out.println(c);
}
}
She has told us that between each number and operand, she WILL put a space. So rather than 5/6, it would be 5 / 6, and that we only have to do it for 0 to 9, but still have to detect if she puts a two digit number, and print invalid number. This part I know how to do. The problem arises when I try to run this. No errors are showing up in the lines, but when I run it, I get this:
Exception in thread "main" java.lang.NumberFormatException: For input string: " * 6"
at java.lang.NumberFormatException.forInputString(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at java.lang.Integer.parseInt(Unknown Source)
at mainPackage.Main.main(Main.java:44)
This ends up being this line:
numInt1 = Integer.parseInt(a);
When removing them, the code prints out something like this:
"5
* 6
* 6"
Would anyone know why this is happening? I feel as though it is something painfully obvious that I missed.
EDIT: Thank you all so much for your quick replies. She never taught us the split method. Thanks again!

First I think you should get familiar with the debugger. It's very useful and there is almost no way one can code a program larger than 20 lines without the need of it ;)
Now take into consideration two things here: substring(beginIndex) returns a sub-string beginning from that index (0 based) to the end of the string.
This is why "5 * 6".substring(1) will return " * 6" (1 is the "position"/index of the first space in the string "5 * 6", because it's 0-based).
That is why you are getting an Exception parsing the expression into an Integer value.
The other thing is, that firstSpace++ or firstSpace-- will increase and decrease the value of firstSpace, respectively, and will do it AFTER the rest of the command.
So actually:
a = input.substring(firstSpace--);
b = input.charAt(firstSpace++);
c = input.substring(secondSpace++);
is equivalent to something like that:
a = input.substring(firstSpace);
firstSpace = firstSpace - 1;
b = input.charAt(firstSpace);
firstSpace = firstSpace + 1;
c = input.substring(firstSpace);
firstSpace = firstSpace - 1;
And you lost what you wanted to achieve.
There are several solutions to your problems. Some of them are suggested above. Some use tools that are a bit more advanced, but you can also solve the problems without other help methods (longer and uglier, but will still work).
My advice is get used to using the debugger, it could help you find out the problem very quickly in this situation.

This can be done using String.split(String regex) function
String arr[] = input.split("\\s+");// splitting input by space
numInt1 = Integer.parseInt(arr[0]);//5
numInt2 = Integer.parseInt(arr[2]);//6
char b = arr[1].charAt(0);//*

If you know that the input is a number, a space, an operator, a space and a number, then that means the length of the input is five characters. Anything other than that is wrong. You can then also check whether these five characters match the given format.
In general, you should always verify user input before passing it to methods that expect a certain input. The user could enter anything and it's up to your program to ensure the input adheres to the desired format.

Your problem is most likely in these lines.
a = input.substring(firstSpace--);
b = input.charAt(firstSpace++);
There are two problems that I see. First the use of -- and ++ is actually changing the value of firstSpace. It looks like b will contain the space instead of the arithmetic operator. You can help yourself figure out what is going on by sprinkling some System.out.println() messages in there to see what is happening to your index variables.
Second, the substring method with a single parameter creates a substring from the given index to the end of the string. I think you may really want to do something like:
a = input.substring(0, firstSpace-1);
This will give you the substring from the beginning of input to the character before the first space.

Related

How can i create a recursive method that does the exp of n but returns a String n number of times in Java

So i'm doing an exercise but i'm having a bad time with recursive methods.
I want the method starPower to return the power of 2 to the n in asterisks ("*") but i get a Stack Overflow.
Can someone tell me what am i doing wrong?
Here is what i have so far:
public static String starPower(int n){
String str = "*";
if (n<0)
throw new IllegalArgumentException("n has an invalid value");
if (n==0)
{return str;
}
return str + starPower( Math.pow(2,n-1));
}
Don't use Math.pow(). Your method is supposed to be recursive and use simple operations.
I will not give you the code, but explain how it should work. First, here are the expected results:
starPower(0) = "*" // 2^0 = 1 stars
starPower(1) = "**" // 2^1 = 2 stars
starPower(2) = "****" // 2^2 = 4 stars
starPower(3) = "********" // 2^3 = 8 stars
starPower(4) = "****************" // 2^4 = 16 stars
starPower(5) = "********************************" // 2^5 = 32 stars
starPower(6) = "****************************************************************"
. . .
As you can see, the result if starPower(n) is double1 the result of starPower(n - 1). That is your simple recursion.
1) By double, I mean double the length, i.e. the string concatenated with itself.
You need to understand the pattern of the outputs in your problem to solve it.
if you can find a relation between input and output in each case of n you could solve it.this way of thinking is called Reverse Engineering.
As Andreas said in his answer from the test cases you can conclude that starPower(n) is double the result of starPower(n - 1):
starPower(0) = "*"
starPower(1) = "**"
starPower(2) = "****"
so you only need to double the result of "*" in each recursive call:
public static String starPower(int n){
if (n < 0){
throw new IllegalArgumentException("n has an invalid value");
}
if (n==0){
return "*";
}
return starPower(n-1) + starPower(n-1);
}
public static void main(String[] args) {
System.out.println(starPower(3));
}
Output:
********
You have to think recursively, which is pretty difficult. If you concatenated the results of two function calls for n-1, you'd have two halves, making a whole. Notice however that since calling the function twice with the same input would yield the same output twice. So you can help lessen the burden on the stack by only calling once and using the result twice.
Try to visualize it like this for an example of calling starPower(3). It calls starPower(2) and concatenates the result of that with itself. Calling starPower(2) calls starPower(1) and concatenates the result of that with itself. starPower(1) calls starPower(0) and concatenates the result of that with itself.
starPower(0) always returns "*"; it's the base case. You can now build up from here. starPower(1) takes two of them and pastes them together making "**". starPower(2) concatenates two of those to make "****". There's a pattern emerging for you now hopefully. Lastly, starPower(3) takes two of those and concatenates them to make the final result of "********", which is 8, or 2³, asterisks.
3: ********
2: **** ****
1: ** ** ** **
0: * * * * * * * *
Here's the modified code implementing that solution.
public static String starPower(int n) {
if (n < 0) {
throw new IllegalArgumentException("n has an invalid value");
}
if (n == 0) {
return "*";
}
String halfResult = starPower(n - 1);
return halfResult + halfResult;
}

What am I missing with this code? Google foo.bar

So recently I got invited to this google foo.bar challenge and I believe the code runs the way it should be. To be precise what I need to find is the number of occurrences of "abc" in a String. When I verify my code with them, I pass 3/10 test cases. I'm starting to feel bad because I don't know what I am doing wrong. I have written the code which I will share with you guys. Also the string needs to be less than 200 characters. When I run this from their website, I pass 3 tests and fail 7. Basically 7 things need to be right.
The actual question:
Write a function called answer(s) that, given a non-empty string less
than 200 characters in length describing the sequence of M&Ms. returns the maximum number of equal parts that can be cut from the cake without leaving any leftovers.
Example : Input : (string) s = "abccbaabccba"
output : (int) 2
Input: (string) s = "abcabcabcabc"
output : (int) 4
public static int answer(String s) {
int counter = 0;
int index;
String findWord ="ABC";
if(s!=null && s.length()<200){
s = s.toUpperCase();
while (s.contains(findWord))
{
index = s.indexOf(findWord);
s = s.substring(index + findWord.length(), s.length());
counter++;
}
}
return counter;
}
I see a couple of things in your code snippet:
1.
if(s.length()<200){
Why are you checking for the length to be lesser than 200? Is that a requirement? If not, you can skip checking the length.
2.
String findWord ="abc";
...
s.contains(findWord)
Can the test program be checking for upper case alphabets? Example: "ABC"? If so, you might need to consider changing your logic for the s.contains() line.
Update:
You should also consider putting a null check for the input string. This will ensure that the test cases will not fail for null inputs.
The logic of your code is well but on the other hand i found that you didn't check for if input string is empty or null.
I belief that google foo.bar wants to see the logic and the way of coding in a proper manner.
so don't be feel bad
I would go for a simpler approach
int beforeLen = s.length ();
String after = s.replace (findWord, "");
int afterLen = after.length ();
return (beforeLen - afterLen) / findWord.length ();
String pattern = "abc";
String line="<input text here>";
int i=0;
Pattern TokenPattern=Pattern.compile(pattern);
if(line!=null){
Matcher m=TokenPattern.matcher(line);
while(m.find()){
i++;
}}
System.out.println("No of occurences : "+ " "+i);
put declaration of index out before while block, isn't never good re-declare the same variable n time.
int index;
while (s.contains(findWord))
{
index = s.indexOf(findWord);
....
}
I hope this help
Update:
try to compact your code
public static int answer(String s) {
int counter = 0;
int index;
String findWord = "ABC";
if (s != null && s.length() < 200) {
s = s.toUpperCase();
while ((index = s.indexOf(findWord)) > -1) {
s = s.substring(index + findWord.length(), s.length());
counter++;
}
}
return counter;
}
Update:
The logic seems good to me, I'm still try to improve the performance, if you can try this
while ((index = s.indexOf(findWord, index)) > -1) {
//s = s.substring(index + findWord.length(), s.length());
index+=findWord.length();
counter++;
}

Java - How to create a substring until a non-numerical character is reached?

The title speaks for itself. I'm trying to create a calculator that integrates polynomial functions using basic coding, not just whipping out a math operator to do it for me :). I haven't had to go far until I hit a wall, as I'm unable to find a way to: create a substring of the numbers in the original string until a non-numerical character is reached. i.e. if the string is 123x, I want to create a substring of 123, without the 'x'. Here is what I've got so far:
public static void indefinite()
{
int x = 0;
System.out.print("Enter your function to integrate:\n F ");
Scanner input = new Scanner(System.in);
String function = input.nextLine();
String s1 = "";
for (int i = 0; i < function.length(); i++)
{
s1 = s1 + function.substring(x, i+1);
x = i+1;
}
}
It all looks a bit nonsensical, but basically, if the string 'function' is 32x^4, I want the substring to be 32. I'll figure out the rest myself, but this part I cant seem to do.
p.s. i know the for loop's repetition variable is wrong, it shouldn't repeat until the end of the string if I'm looking at functions with more than just 2x^3. I haven't gotten around trying to figure that out yet, so I just made sure it does it for 1 part.
Use replaceAll() to "extract" it:
String number = str.replaceAll("\\D.*", "");
This replaces the first non digit and everything after it with nothing (effectively deleting it), leaving you with just the number.
You can also go directly to a numeric primitive, without having to use a String variable if you prefer (like me) to have less code:
int number = Integer.parseInt(str.replaceAll("\\D.*", ""));
You could split your string at the letter-digit marks, like so:
str.split("(?<=\\D)(?=\\d)|(?<=\\d)(?=\\D)");
For instance, "123x54y7z" will return [123, x, 54, y, 7, z]

Java String Manipulation: extracting integer and float from string based on pattern

I have the following two possible contents of a String.
Obviously the amounts always vary and I would like to extract the key information and
Case 0: pricesString = ""
Case 1: pricesString = "$0.023"
Case 2: pricesString = "10+: $1.46 100+: $0.16 500+: $0.04"
In Case 0 I would like to do nothing.
In Case 1 I would like to perform:
article.addPrice(1, 0.023);
In Case 2 I would like to perform:
article.addPrice(10, 1.46);
article.addPrice(100, 0.16);
article.addPrice(500, 0.04);
How can I extract this information so I can can call article.addPrice with the float and integer values contained?
That looks like a job for regex:
String pricesString = "10+: $1.46 100+: $0.16 500+: $0.04";
Pattern p = Pattern.compile("(\\d+)\\+: \\$(\\d\\.\\d\\d)");
Matcher m = p.matcher(pricesString);
while (m.find()) {
Intger.parseInt(m.group(1));
Double.parseDouble(m.group(2));
}
You can choose between the 3 cases by a simple .length() check. The code above is for the last case. The rest is eaiser
Apply the regex \d+\.?\d* as often as you can. The array of the results can be checked whether it contains 0, 1 or more values.
If there are 0, it is Case 0.
If there is one, it is Case 1. You can edd it with qunantity 1 to the articles.
If there are more, you can loop with something like
for(int i = 0; i < result.length / 2; i++) {
articles.addArticle(Integer.parseInt(result[i]), Double.parseDouble(result[i+1]));
}

How can I extract the numbers from a string only using charAt(), length() and/or toCharArray() in Java

I have to do this for an assignment in my java class. I have been searching for a while now, but only find solutions with regex etc.
For my assignment however I may only use charAt(), length() and/or toCharArray(). I need to get from a string like gu578si300 for example just the numbers so it will become: 578300.
i know numbers are 48 - 57 in ASCII but i can't figure out how to do this in java. You guys any ideas?
i was thinking about a for loop that checks whether the (int) char is between 48-57 en if so puts the value into a seperate array. Howeevr i dont know how to programm that last thing.
I now have this;
public static String filterGetallenreeks(String reeks){
String temp = "";
for (char c : reeks.toCharArray()) {
if ((int) c > 47 && (int) c < 58)
temp += c;
}
return temp;
however it is not working, it just outputs the same as goes in.
is it something in my mainm which looks like this. If i'm right the return temp; will return the temp string into the reeks string in the main right? why is my input still the same a sthe output?
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("Voer een zin, woord of cijferreeks in:");
String reeks = sc.nextLine();
if (isGetallenreeks(reeks)){
System.out.println("is getallenreeks");
filterGetallenreeks(reeks);
System.out.println(reeks);
}
Since this is homework I will not be providing the complete solution, however, this is how you should go about it:
Do a for loop that iterates for the total amount of characters within the string (.length). Check if the character is a digit using the charAt and isDigit methods.
You could do a loop that checks a character in the string, and if it's a number, append it to another string:
//I haven't tested this, so you know.
String test = "gu578si300 ";
String numbers = "";
for(int i=0; i<test.length(); i++){
if("0123456789".indexOf(test.charAt(i)) // if the character at position i is a number,
numbers = numbers + test.charAt(i); // Add it to the end of "numbers".
}
int final = Integer.parseInt(numbers); // If you need to do something with those numbers,
// Parse it.
Let me know if that works for you.
It seems like a reasonable approach, but I'd make a couple of changes from what you suggested:
If you need to result as a string then use a StringBuilder instead of an array.
Use character literals like '0' and '9' instead of ASCII codes to make your code more readable.
Update
The specific problem with your code is this line:
temp = temp + (int)c;
This converts the character to its ASCII value and then converts that to a decimal string containing the ASCII value. That's not what you want. Use this instead:
temp += c;

Categories