Replace all non digits with a restriction - java

I'm trying to extract the first number from expressions:
Here's my code for while:
String[] strArray = input.split("\\+ ");
double[] numbers = getNumbersFromString();
public static double[] getNumbersFromString() {
double[] numbers = new double[strArray.length];
for (int i = 0; i < strArray.length; i++) {
numbers[i] = Double.parseDouble(strArray[i].replaceAll("\\D", ""));
}
return numbers;
}
Inputs and their expected outputs:
Z = 4x1 + 3x2 + 6x3 // 4 3 6
Z = 24x1 + 33x2 + 68x3 // 24 33 68
Z = 412x1 + 309x2 + 612x3 // 412 309 612
Z = 4329x1 + 3901x2 + 6716x3 // 4329 3901 6716
Actually, it's removing but it retrieves besides the first number, the second also. Eg.(In the first case): // 41 32 63, while it should be only // 4 3 6.
I could do something like "\\w = |x\\d", "", but it will only work for this specific case, I want a more general thing.
Thanks in advance.
Edit:
I got the following answer for the original question:
String input = "Z = 4329x1 + 3901x22 + 6716x3";
input = input.replaceAll("^\\D+", "");
double[] numbers = Pattern.compile("x\\d+\\D*")
.splitAsStream(input)
.mapToDouble(Double::parseDouble)
.toArray();
But now appeared a new thing to be done. Inputs that has no numbers before the x1/x2/x3.. or any kind of this" should be replaced by the number "1".
Some inputs and their respective expected outputs:
Z = x11 + x2 + x90 // 1 1 1
Z = 2x1 + 2x4 + x9 // 2 2 1
By the way, I have made this regex: (?<!\d)x\d+.
Then I modified the code to:
return Pattern.compile("x\\d+\\D*")
.splitAsStream(input.replaceAll("(?<!\\d)x\\d+","1").replaceAll("^\\D+", ""))
.mapToDouble(Double::parseDouble)
.toArray();
But it's returning me `java.lang.NumberFormatException: For input string: "1 + 3".
PS: it should work for either the old and new case.

This should work as required:
String s = "Z = 4329x1 + 3901x22 + 6716x3";
String[] split = s.replaceAll("^\\D+", "").split("x\\d+\\D*");
System.out.println(Arrays.toString(split)); //[4329, 3901, 6716]
With streams you could do something like this to obtain your array of doubles:
String input = "Z = 4329x1 + 3901x22 + 6716x3";
input = input.replaceAll("^\\D+", "");
double[] numbers = Pattern.compile("x\\d+\\D*")
.splitAsStream(input)
.mapToDouble(Double::parseDouble)
.toArray();
EDIT
To also accept expressions such as x1 + x2, you can default to 1 when the string returned by split is empty (and amend the regex slightly):
String input = "Z = x1 + x2 + 6716x3";
input = input.replaceAll("^[^x\\d]+", "");
double[] numbers = Pattern.compile("x\\d+[^x\\d]*")
.splitAsStream(input)
.mapToDouble(s -> s.isEmpty() ? 1d : Double.parseDouble(s))
.toArray();
RE-EDIT
Add the missing 1 before the x manually:
String input = "Z = x1 + x2 + 6716x3 + x4";
input = input.replace(" x", " 1x")
.replaceAll("^[^x\\d]+", "");
double[] numbers = Pattern.compile("x\\d+[^x\\d]*")
.splitAsStream(input)
.mapToDouble(Double::parseDouble)
.toArray();

You could do the whole grabbing in a single regex (per row which I assume from your example what you're interested in) -
(?:=|\+)\s*(\d+)
It matches either a = or a +, skipping any spaces and then captures the number. Make it global and it'll capture the entire row. The result will be in the capture group array. (Don't speak java well enough to tell you exactly how from the top of my head).
Check it here at regex101. (Note - sample shows all the rows at once - you'd have to do them one by one.)

Since you pattern is a number followed by an x, using positive lookahead like this will work.
Regex: \d+(?=x)
Explanation:
(?=x) looks ahead and checks if x is present. If yes then \d+ is matched.
Regex101 Demo
Note: Use double escape \\d if necessary.

Related

Printf in Java with variable spaces before the output

With printf I can decide how many space characters should be before the variable i that I want to print. In the example below, it is 10. Is it possible to have there a variable instead of the number 10? So that the spaces characters depend on the value of a variable?
System.out.printf("%10d" , i);
The format string is still a string, so assuming a width variable System.out.printf("%" + width + "d", x); does the trick.
So for example
var width = 10; var x = 123;
System.out.printf("%" + width + "d", x);
prints 123 (7 leading spaces + 3 digits = 10), while
var width = 3; var x = 123;
System.out.printf("%" + width + "d", x);
prints 123
Define a lambda to create the desired width and then call that prior to printing the value.
Function<Integer, String> format = width-> "%%%dd\n".formatted(width);
int x = 4567;
System.out.printf(format.apply(10),x);
System.out.printf(format.apply(5),x);
// or create it once for multiple printf calls.
String form = format.apply(3);
System.out.printf(form, 2);
System.out.printf(form, 4);
prints
4567
4567
2
4
%%%dd - the first % escapes the second so on the last %d formats the width value.
then that format string is returned and used to format the supplied argument in the printf statement

Splitting polynomial with negatives

I am writing a program to add and subtract user inputted polynomials but I ran into trouble dealing with negative numbers. The program will work fine with positive numbers but I get the following output with negative numbers.
Output:
Coeficent: -2x^-2+3
Coeficent: 6
Exponent: 0
Exponent: 0
Exponent: 0
Exponent: 1
Exponent: 0
Code:
Scanner in = new Scanner(System.in);
LinkedList list = new LinkedList();
String polynomial= "-2x^-2+3x^1+6";
String[] parts = polynomial.split("x\\^\\d+\\+?");
for (String part : parts) {
System.out.println("Coeficent: " + part);
}
String[] terms = polynomial.split("(-|\\+)");
for (String term : terms) {
String[] exponent = term.split("\\^");
System.out.println("Exponent: " + (exponent.length > 1 ? exponent[1] : "0"));
}
Here's an example that separates out the two parts of each term:
public static void main(String ...args) {
Pattern termPat = Pattern.compile("([+-]?(\\d+|(?=x)))(x(\\^([+-]?(\\d+)))?)?");
System.out.println("Input: " + polynomial);
int pos = 0;
Matcher m = termPat.matcher(polynomial);
while (true) {
if (!m.find(pos))
break;
int coeff = Integer.parseInt(m.group(1) + (m.group(2).length() == 0 ? "1" : ""));
int degree = Integer.parseInt((m.group(3) == null)? "0" : (m.group(5) == null)? "1" : m.group(5));
System.out.println(String.format("Term - Coeff: %d Degree: %d", coeff, degree));
pos = m.end();
}
}
Output:
Input: -2x^-2+3x^1+6
Term - Coeff: -2 Degree: -2
Term - Coeff: 3 Degree: 1
Term - Coeff: 6 Degree: 0
You could expand on using a regular expression for splitting input.
Using the regex: ((?:[\-\+]\dx\^[\-\+]\d)|[\-\+]\d) will give you a proper start to capture polynomials with all +/- signs written out. For example: +2x^+2+3x^+1+4x^-3+6 would be an accepted input. You would then interate through the matches and process each for themself. The example before will give you the following matches:
+2x^+2
+3x^+1
+4x^-3
+6
try it out here
Consider sequence of mathematical operations. Split step-by-step:
first, split additions/subtractions, but here check if your finding has a left-operand. If there is no left-operand, it's a sign instead of an operation.
So, identify those +/- which do have a number or a variable on its left side, but NO operatator.
Then, split multiplications and divisions
Finally, split for those operations with highest priority - in your case, exponential function

Java Addition with characters [duplicate]

This question already has answers here:
Java: parse int value from a char
(9 answers)
Closed 6 years ago.
I am fairly new to java, about 3 weeks into my course. In my assignment, I needed to use charAt to separate the string into 14 parts. Now I need to use addition and add these together.
I have tried many times with no success. Every time I add them together and print it out it gives me a number way bigger than it should be.
char num1 = roulette.charAt(0);
char num2 = roulette.charAt(1);
char num3 = roulette.charAt(2);
char num4 = roulette.charAt(3);
char num5 = roulette.charAt(4);
char num6 = roulette.charAt(5);
When I add num1+num2+num3+num4+num5+num6, I get a number way bigger than it should be.
Am I missing something?
This is due to you adding the characters together, they will not turn into the number equivalent automatically. You will need to change them yourself, to do this you can use Integer.parseInt(char) and you can add them together like that. For example Integer.parseInt(String.valueOf('1') + Integer.parseInt(String.valueOf('2')) this will add 1 + 2 together correctly now resulting in 3 rather than appending 2 to the 1 making 12
If you want to add the characters then each character has a character code that will be used. so for example according to the ASCII Table 'a' = 97, 'b' = 98, 'c' = 99; so if you add these together you will get 294. ASCII Table https://www.cs.cmu.edu/~pattis/15-1XX/common/handouts/ascii.html.
However, if each character represents a number and you want to add the numbers then you can do something like this:
char num1 = roulette.charAt(0);
int firstNum = Integer.parseInt(Character.toString(num1));
char num2 = roulette.charAt(1);
int secondNum = Integer.parseInt(Character.toString(num2));
char num3 = roulette.charAt(2);
int thirdNum = Integer.parseInt(Character.toString(num3));
char num4 = roulette.charAt(3);
int fourthNum = Integer.parseInt(Character.toString(num4));
char num5 = roulette.charAt(4);
int fifthNum = Integer.parseInt(Character.toString(num5));
char num6 = roulette.charAt(5);
int sixthNum = Integer.parseInt(Character.toString(num6));
int result = firstNum + secondNum + thirdNum + fourthNum + fifthNum + sixthNum;
You cannot cast your chars to integer first try like this
Integer.parseInt(num1) + Integer.parseInt(num2) +Integer.parseInt(num3)...
and so on.
EDIT
I just learned that you cannot use Integer.parseInt(num1) for Character.
You should cast your chars as below:
char a = '5';
int b = Integer.parseInt(String.valueOf(a));
int c=b+b;
System.out.println(c); //this will give 10
If you add characters to characters, it means you are adding their ascii values. But if you want to add the numeric value which is presented as a Character in the String, then you have to convert the character to integer first. See the example given below.
N.B. when you want to add a sequence of values, use loop.
Example
String roulette = "123456";
int sum = 0;
for (int i = 0; i < roulette.length(); i++) {
sum = sum + roulette.charAt(i);
}
System.out.println("Sum : " + sum);
sum = 0;
for (int i = 0; i < roulette.length(); i++) {
sum = sum + Integer.parseInt(String.valueOf(roulette.charAt(i)));
}
System.out.println("Sum : " + sum);
Output
Sum : 309
Sum : 21
Case 1: sum = sum + roulette.charAt(i);
Adding ascii values of the numbers. So the sum is 309.
ascii_value('1') - 49
ascii_value('2') - 50
...
ascii_value('5') - 53
ascii_value('6') - 54
Sum = 49 + 50 + 51 + 52 + 53 + 54 = 309
Case 2: sum = sum + Integer.parseInt(String.valueOf(roulette.charAt(i)));
Adding the numeric value instead of the ascii values. So the sum is 21.
Sum = 1 + 2 + 3 + 4 + 5 + 6 = 21

java scan coordinates as (X, Y) format

How can I scan coordinates with (x, y) format?
For example:
(1, 3)
(2, 4)
(4, 1)
(3, 2)
What I've tried is this:
String m = input.next();
String parts[] = m.split(",");
String part1 = parts[0];
String part2 = parts[1];
part1 = part1.substring(1, part1.length());
part2 = part2.substring(0, part2.length()-1);
That code works for a coordinate with (x,y) format but doesn't work for (x, y)
You mentioned you could get it working with format (x,y) but not (x, y) with the space in between. I would suggest using .trim() to get rid of the spaces:
public static void main(String args[])
{
Scanner input = new Scanner(System.in);
System.out.println("Enter a coordinate: ");
String coordinate = input.nextLine();
String[] parts = coordinate.split(",");
// if input is (x, y)
// then parts[0] is "(x"
// and parts[1] is " y)"
String x = parts[0].trim().substring(1).trim();
String y = parts[1].trim().substring(0, parts[1].trim().length() - 1).trim();
System.out.println("x: " + x + "\ny: " + y);
}
I trimmed the part before getting the substring, and then trimmed the part after getting the substring as well, so that when the brackets are ignored in the substrings, the spaces will also be removed. It seems to work for all cases no matter how much whitespace there is.
Samples:
Without a space
Enter a coordinate:
(155,54)
x: 155
y: 54
With a space
Enter a coordinate:
(118, 43)
x: 118
y: 43
With a lot of spaces
Enter a coordinate:
( 155 , 4 )
x: 155
y: 4
Here's an outline for one way to go about doing this:
Instantiate a Scanner object.
Read the next token (the next line) from it with the next() method.
Split the read in String on the comma and save the resulting array into a String[] - e.g. nums[].
For the first number, parse the first string in the String[] from the 2nd character (at index 1, not 2) onwards into an int. You can use Integer.valueOf() and substring(1) to do this.
For the second number, substring from the 1st character of the second string in the nums[] array (index 0) until the character before the last character. So substring(0, nums[1].length()-1). Again, use Integer.valueOf().
Hopefully that helps and doesn't completely give away the solution without some more effort on your part. Also, note that you should handle exceptions that might pop up.

Why is myArrayList.size(); producing incorrect/gigantic numbers?

Basically, I'm trying to write a program that converts a number from base 2 to base 10. What I tried doing was translating the process listed on this website under the "Doubling method" into a for loop, but for some reason the numbers I'm getting are way to big.
The basic formula is (2 * previousTotal) + (currentDigit of the ArrayList that holds the user's inputted binary number) = previousTotal.
So for 1011001 in binary, the math would be:
(0 x 2) + 1 = 1
(1 x 2) + 0 = 2
(2 x 2) + 1 = 5
(5 x 2) + 1 = 11
(11x 2) + 0 = 22
(22 x 2) + 0 = 44
(44 x 2) + 1 = 89
The console however, prints out 6185 as the result. I'm thinking it might have something to do with me using an ArrayList of characters, but the charWhole.size() returns 7, which is how many digits are in the user's binary number. As soon as I do charsWhole.get(w); however, I start getting big numbers such as 49. I'd really appreciate some help!
I wrote out this loop, and according to some print statements that I placed throughout the code and my variable addThis seems to be where the problem is. The console prints out a final total of 6185, when 1011001 in base 10 is actually 89.
public static void backto2(){
System.out.println("What base are you coming from?");
Scanner backToB10 = new Scanner(System.in);
int bringMeBack = backToB10.nextInt();
//whole
System.out.println("Please enter the whole number part of your number.");
Scanner eachDigit = new Scanner(System.in);
String theirNumber = eachDigit.nextLine();
String str = theirNumber;
ArrayList<Character> charsWhole = new ArrayList<Character>();
for (char testt : str.toCharArray()) {
charsWhole.add(testt);
}
System.out.println(theirNumber); // User's number
System.out.println(charsWhole); // User's number separated into elements of an ArrayList
System.out.println(charsWhole.size()); // Gets size of arrayList, comes out as 7 which seems fine.
int previousTotal = 0, addThis = 0, q =0;
for( int w = 0; w < charsWhole.size(); w ++) {
addThis = charsWhole.get(w); //current digit of arraylist PROBLEM
q = previousTotal *2;
previousTotal = q + addThis; // previous total gets updated
System.out.println(q);
System.out.println(addThis);
System.out.println(q + " and " + addThis + "equals " + previousTotal);
}
System.out.println(previousTotal);
You are attempting to add a character to an integer. The implicit conversion uses the ASCII value of the character, so that '1' gets converted to 49, not 1, because 49 is the code for the character '1'. Subtract '0' to get the actual integer value.
addThis = charsWhole.get(w) - '0';
This works because the digits 0-9 are represented in ASCII as the codes 48-57, so in effect you will, for '1', subtract 49 - 48 to get 1.
You'll still have to handle cases when the character is outside the range of allowable characters.
EDIT
Java uses Unicode, but for the purposes of the codes for the digits 0-9, the codes are the same (48 thru 57, or 0x30 thru 0x39) in both ASCII and Unicode.
The problem is that you're using the chars rather than the number value they represent. In the line
addThis = charsWhole.get(w);
the value of addThis is the ascii value of the character. For '0', this is 48. Use this instead:
addThis = Integer.parseInt(charsWhole.get(w));
Another suggestion to solve the same problem:
addThis = charsWhole.getNumericValue(w);
See here for more information.

Categories

Resources