0

I need to extract both positive and negative integers from a binomial expression in String form. Then those numbers will be assigned to an array.

This string:

"(-22x+43)^2"

would become this array:

[-22, 43, 2]

Or,

This string:

"(x-22)^-2"

would become this array:

[1, -22, -2]

I'm familiar with arrays, but have no idea how to extract numbers. I've looked into regular expressions and that process seems mysterious. Can this be done without regular expressions? What is the best way to think about solving this type of problem?

Slot Machine
  • 71
  • 1
  • 9
  • 2
    *"What is the best way to think about solving this type of problem?"* Either use regular expressions, or write your own parser. For regular expressions, you want to extract all parts matching the `-?\d+` pattern, and run them through `Integer.parseInt()`. – Robby Cornelissen Aug 27 '18 at 05:23
  • Regarding the best way to think about solving it, the "meta answer" is to think about what _you_ did, in your head, to go from `"(-22x+43)^2"` to `[-22, 43, 2]`. Forget coding for a moment -- how did you solve it? Can you try to solve a few such expressions, and figure out a common pattern? Once you figure out the pattern, can you formalize it? Once you formalize it, coding is the "easy" part -- you just need write that formula down in the form of Java. – yshavit Aug 27 '18 at 05:28
  • Normally this is the sort of problem you solve with a parser. They're not easy to write. And a parser would normally parse out the other tokens too, which are needed to correctly evaluate the expression. Something like: `[ '(', 'x', '-', 22, ')', '^', -2 ]` It's a complex topic however. https://en.wikipedia.org/wiki/Parsing – markspace Aug 27 '18 at 05:31
  • It's a pretty simple parser. If it's not a number, add a space in front of it. Then split the string at the spaces and check each token with Integer.parseInt(). The only trick you need to manage is negative integers but you can deal with that when you have the first part running. Once done you can optimize it so you don't create excess strings and whatnot. – Torben Aug 27 '18 at 05:36
  • 1
    Perhaps my coffee didn't wake me up already, but, why this `"(x-22)^-2"` would become `[0, -22, -2]`? shouldn't it be `[1, -22, -2]` as there is one `x`? If there were 0 `x` then it would have been `(-22)^-2` – Julio Aug 27 '18 at 07:16
  • @Julio, yes you are drinking the appropriate amount of coffee. I've corrected that above. Thank you! And thanks everyone for the answers above, they are much appreciated. – Slot Machine Aug 27 '18 at 13:52

7 Answers7

1

With and without regex:-

public static void main(String[] args) {
    String test = "(-22x+43)^2";
    System.out.println(extractNumbers(test));
    System.out.println(extractNumbersRegexStyle(test));
}

private static List<Integer> extractNumbers(String str) {
    str += " ";
    List<String> arr = new ArrayList<>();
    StringBuilder sb = new StringBuilder();
    for (char c : str.toCharArray()) {
        if (Character.isDigit(c) || (sb.length() == 0 && c == '-')) {
            sb.append(c);
        } else if (Character.isLetter(c) && sb.length() == 0) {
            sb.append(1);
        } else {
            if (Character.isLetter(c) && sb.toString().equals("-")) {
                sb.append(1);
            }
            if (sb.length() > 0) {
                arr.add(sb.toString());
                sb = new StringBuilder();
            }
            if (c == '-') {
                sb.append(c);
            }
        }
    }
    return arr.stream()
            .map(Integer::parseInt)
            .collect(Collectors.toList());
}

private static List<Integer> extractNumbersRegexStyle(String str) {
    List<String> arr = new ArrayList<>();
    Pattern p = Pattern.compile("-?\\d+");
    Matcher m = p.matcher(str);
    while (m.find()) {
        arr.add(m.group());
    }
    return arr.stream()
            .map(Integer::parseInt)
            .collect(Collectors.toList());
}

Output

[-22, 43, 2]
[-22, 43, 2]

You can then convert List to int array if you want.

Kartik
  • 7,677
  • 4
  • 28
  • 50
  • Thanks @NishantModi I was in middle of fixing it. Fixed this case you mentioned, try now. Thinking about other loop-holes. – Kartik Aug 27 '18 at 06:50
0

You can try matching it through this regex : "[-\d++\d+]"

Adya
  • 1,084
  • 9
  • 17
0

You should do this by checking condition on each characters.

public static void main(String[] args) {
        String exp="(x-y)^-2";
        String arr[]=new String[5];
        int i=0;
        String input1="";
        for(int x=0;x<exp.length();x++){
            char ch=exp.charAt(x);
            if(ch=='-'||(ch>=48&&ch<=57)){
                input1 += String.valueOf(ch);
            }
            else{
                if((ch>=65&&ch<=90)||(ch>=97&&ch<=122)||ch=='^'){
                    if(input1.equals("")){
                        input1="0";
                    }
                    if(!input1.equals("-")){
                    arr[i]=input1;

                    i++;
                    }
                    input1="";
                    }
            }

        }
        if(!input1.equals("")){
            arr[i]=input1;
        }
        System.out.println("Array IS");
        for(String c:arr){
            System.out.println(c);
        }
    }
Mostch Romi
  • 531
  • 1
  • 6
  • 19
0

Considering the string has expression of form (ax-b)^n and you require the coefficients [a , b, n]

A custom parser could be written for this and I would do it in Java.(You could use any other language, but logic would be pretty much same)

public static int[] getBinomialCoefficients(String exp){

     int l=exp.length();
     // "(x-22)^-2" for example

     int obIndex = exp.indexOf('('); //opening bracket Index
     int xIndex  = exp.indexOf('x'); // x index
     int cbIndex = exp.indexOf(')'); // closing bracket Index

     int a=0,b=0,n=1;
     if(obIndex+1!=xIndex){
          a = Integer.parseInt(exp.substring(obIndex+1,xIndex));
     }
     if(cbIndex-1!=xIndex){
          b = Integer.parseInt(exp.substring(xIndex+1,cbIndex));
     }
     if(cbIndex!=l-1){
          n = Integer.parseInt(exp.substring(cbIndex+2,l));
     }


    return new int[] {a,b,n};
}

Here I am calculating indexes of each variable, but if you think splitting it into array would help, you can use that approach as well. The string wont be that much long, so we could use any of these approaches.

anubhs
  • 566
  • 1
  • 8
  • 26
0

You can try

import java.util.ArrayList;

public class NumberExtraction
{
    private static String oneNumber ="";
    private static ArrayList<Integer> ar = new ArrayList<Integer>();
    public static void main(String[] args)
    {
        String exp = "(-22x+43)^2";
        char[] cr = exp.toCharArray();
        for(char c : cr)
        {
            doCheck(c);
        }
        doCheck('e');
        System.out.println(ar);
    }
    static void doCheck(char c)
    {
        if((c>=48 && c<=57) || c==45)
        {
            oneNumber +=c;
        }else if(((c>=97 && c<=122) || (c>=65 && c<=90) ) &&("".equalsIgnoreCase(oneNumber)||"-".equalsIgnoreCase(oneNumber) ))
        {
            oneNumber +=0;
        }else if(!"".equalsIgnoreCase(oneNumber))
        {
            ar.add(Integer.parseInt(oneNumber));
            oneNumber="";
        }

    }
}
Nishant Modi
  • 669
  • 1
  • 6
  • 19
0

using string functions, try this one

import java.io.*;
 import java.util.*;
 public class Series
 {
  public static void main(String [] args) {
      String str = "(x-22)^-2";  
      String[] arstr = str.replaceFirst("\\)","").split("[x^]"); // replacing ")", with "" and splitting at x and ^ 
      if(arstr[0].equals("("))   // checking for coefficient
            arstr[0]="0";
       else
           arstr[0]=arstr[0].substring(1);
       if(arstr[1].contains("+"))         // checking sign "+" to remove
           arstr[1]=arstr[1].substring(1);
      System.out.println(Arrays.toString(arstr));   // printing result

    }  
 }

input

String str = "(x-22)^-2"; 
String str2 =  "(-22x+43)^2"

output:

[0, -22, -2]
[-22, 43, 2]
The Scientific Method
  • 2,374
  • 2
  • 14
  • 25
0

You may use this regex (and an extra replacement):

\((-?(?:\d+|x))x?(?:\+(\d+)|(-\d+))\)\^(-?\d+)

Replace by: [$1, $2$3, $4]. Then, replace x by 1

Demo (for the first part)

Code:

String str = "(-x-99)^-9";

str = str.replaceAll("\\((-?(?:\\d+|x))x?(?:\\+(\\d+)|(-\\d+))\\)\\^(-?\\d+)", "[$1, $2$3, $4]")
         .replaceAll("x", "1");

Output:

[-1, -99, -9]

The regex, explained:

\(                   # Literal '('
  (-?(?:\d+|x))      # First capturing group: Either digits or single x
  x?                 # Followed by an optional x
  (?:\+(\d+)|(-\d+)) # Match either: positive number on 2nd capturing group (without + sign)
                     # or negative number on 3rd capturing group (with - sign)
\)                   # Literal ')'
\^                   # Literal '^'
(-?\d+)              # Exponent, 4th capturing group
Julio
  • 5,208
  • 1
  • 13
  • 42