-4

I have input of string containing numbers, implementing myAtoi. My program is checking all the conditions but getting failed on +-1.

I am trying to check it with:

if(str.matches("^[+-]|[-+]*"))
    System.out.println("check="+str);

but it's not working. I just want to have some insight on regex for checking +- together.

khelwood
  • 55,782
  • 14
  • 81
  • 108
Wellbeing
  • 5
  • 2
  • See [Parsing scientific notation sensibly?](https://stackoverflow.com/questions/638565/parsing-scientific-notation-sensibly) – Wiktor Stribiżew Oct 17 '18 at 08:16
  • Can you edit with the full code of what your input is? – SamHoque Oct 17 '18 at 08:18
  • can we have full code? – GauravRai1512 Oct 17 '18 at 08:21
  • 2
    `.matches` matches the entire String, so `"^[+-]|[-+]*"` will never match the digit(s). Also `[+-]` means either a `+` or `-`, not the substring `+-`, so `[+-]*` would already be enough and the `|[-+]` and `^` are redundant. Do you perhaps have some possible input `str` and which ones are supposed to be valid or invalid? If you want to check if a str starts with `+-` as one piece, I would just use `str.startsWith("+-")` and don't use regex at all.. – Kevin Cruijssen Oct 17 '18 at 08:21
  • can you please try with find() method? – GauravRai1512 Oct 17 '18 at 08:23
  • str.matches("^[-+][+-]?[0-9]*")) works. these are some of the possible inputs String s1 = "42"; String s2 = " -42"; String s3 = "4193 with words"; String s4 = "words and 987"; String s5 = "91283472332"; String s6 = "3.145677"; String s7 = "-91283472332"; String s8 = "+1"; String s9 = "-+1"; – Wellbeing Oct 17 '18 at 08:24
  • @Wellbeing it will work for integer values only. – dbl Oct 17 '18 at 08:25
  • @dbl yes I have to have integer at the end of the program – Wellbeing Oct 17 '18 at 08:27
  • @Wellbeing That will also match numbers as `-10` or `+10`, which don't have a both signs. – Ivar Oct 17 '18 at 08:31
  • @Wellbeing So if I understand correctly you just want to extract a number from a String? – Kevin Cruijssen Oct 17 '18 at 08:35
  • @Ivar You are right. I have changed it to [-+][+-][0-9]. added another check for single sign. str.matches("^[+][0-9]*") I just doubt now is this a good approach – Wellbeing Oct 17 '18 at 08:59
  • @Kevin Cruijssen yes I have to extract integer for the string and return. if no integer in first token return 0 – Wellbeing Oct 17 '18 at 09:02
  • @Wellbeing Will the String always contain only one number? So an input like "55 and 11" isn't possible? Also, can the rest of the String contain minus signs as well, like "Something-something and -44"? – Kevin Cruijssen Oct 17 '18 at 09:03
  • @KevinCruijssen I just have to check the first occurrence of the number and discard and discard other parts. I am just thinking how to handle some input like 0000000012345678. in my understanding Integer.valueOf("0000000012345678") should handle this but its not – Wellbeing Oct 17 '18 at 09:14
  • So, you mean to say `str.matches("[-+]?[1-9][0-9]*")` is all you need? – Wiktor Stribiżew Oct 17 '18 at 09:14
  • @WiktorStribiżew No, he wants to extract the number from the String. And `+-1` or `-+1` is also valid (should return `-1`), if I understand correctly. Also, decimal numbers like `3.145677` seems to be possible as well, although since OP states integers a few times I'm not sure if `3` is the expected output or `3.145677` (so a double/float output is expected instead).. – Kevin Cruijssen Oct 17 '18 at 09:17
  • 1
    Well, the title and question sound as if validation was meant. I doubt we can help since it is all too unclear. – Wiktor Stribiżew Oct 17 '18 at 09:19
  • @WiktorStribiżew Yeah, the actual question is now scattered across the comments.. – Kevin Cruijssen Oct 17 '18 at 09:21

3 Answers3

0

Perhaps something like this is what you're looking for:

/**
 * Method to extract the first number from a String
 * Will return either a double or long depending on whether the number contains decimal digits
 */
public Number extractNumber(String str) throws java.text.ParseException{
  // Check if the input-String contains any digit:
  if(!str.matches(".*\\d.*"))
    // If not, return 0
    return 0;

  // Extract the first number:
  String extractedNr = str.replaceAll(".*?([-+]*\\d+(\\.\\d*)?).*", "$1");
  // Replace any "-+" or "+-" with just "-",
  extractedNr = extractedNr.replace("-+", "-").replace("+-", "-")
  // And remove any "--" since they neutralize each other
                           .replace("--", "");

  // Convert the extracted number to a Double
  // TODO: Try-catch the ParseException
  double decResult = Double.parseDouble(extractedNr);
  // If the extracted number does NOT contain decimal digits:
  if(decResult % 1 == 0){
    // Return the result as long
    return (long)decResult;
  } else{
    // If it does contain decimal digits, just return it as double instead
    return decResult;
  }
}

Additional explanation of the regex str.replaceAll(".*?([-+]*\\d+(\\.\\d*)?).*", "$1"):

  • .*?: Zero or more random leading characters, where the part after it has priority due to the ?
  • (: Open capture group
  • [-+]*: Zero or more times "-" and "+" signs
  • \\d+: Followed by one or more digits
  • (\\.\\d*)?: Followed by an optional dot with zero or more digits
  • ): Close capture group
  • .* With zero or more random trailing characters
  • $1: Only leave the captured group, removing the characters before and after the first extracted number

Try it online.

Output:

"42" → 42
"-42" → -42
"4193 with words" → 4193
"words and 987" → 987
"91283472332" → 91283472332
"3.145677" → 3.145677
"-91283472332" → -91283472332
"+1" → 1
"-+1" → -1
"something-something and -44.2" → -44.2
"55 and 11" → 55
"0000000012345678" → 12345678
"--9" → 9
"+-+-+---+---+-+015.0500" → -15.05
Kevin Cruijssen
  • 9,153
  • 9
  • 61
  • 135
  • Using [almson-regex](https://github.com/almson/almson-regex) the pattern can be written a little more readably as `reluctantly(zeroOrMore(ANY_CHARACTER)) + group (zeroOrMore (charclass ('+', '-')) + oneOrMore(DIGIT) + optional(text(".") + zeroOrMore(DIGIT))) + zeroOrMore(ANY_CHARACTER)` – Aleksandr Dubinsky Oct 18 '18 at 03:14
0

IN REGULAR EXPRESSIONS The following characters need to be escaped: +*?^$\.[]{}()|/

If you just converted the following:

if (str.matches("^[+-]|[-+]*")) System.out.println("check="+str);

Into this - I think it would make more sense:

if (str.matches("^(\\+-|-\\+)*")) System.out.println("check="+str);
0

So this was the problem statement The function first discards as many whitespace characters as necessary until the first non-whitespace character is found. Then, starting from this character, takes an optional initial plus or minus sign followed by as many numerical digits as possible, and interprets them as a numerical value.

The string can contain additional characters after those that form the integral number, which are ignored and have no effect on the behavior of this function.

If the first sequence of non-whitespace characters in str is not a valid integral number, or if no such sequence exists because either str is empty or it contains only whitespace characters, no conversion is performed.

If no valid conversion could be performed, a zero value is returned.

Note:

Only the space character ' ' is considered as whitespace character. Assume we are dealing with an environment which could only store integers within the 32-bit signed integer range: [−231, 231 − 1]. If the numerical value is out of the range of representable values, INT_MAX (231 − 1) or INT_MIN (−231) is returned.

and this is my solution that passes 1000+ tests and got accepted but it doesn't look good. could itrating the list with character comparison was a better idea?

public class Main {
    public static int myAtoi(String str) {
    if(str == null)
        return 0;
    str = str.trim();
    if(str.matches(".*[A-Za-z0-9].*")){
        String [] tokens = str.split("\\s+");
         String s = tokens[0];
    if(s.matches("[a-z]*\\D*")|| s.startsWith(".") ||s.matches("[+-]?[a-z]+\\d+") || s.matches("^[-+][+-][0-9]*"))
                return 0;     

    if(s.matches("[+-]*[0-9a-z]*"))
        s = s.split("[a-z]")[0];
        if (s.matches("[+-]?([0-9]\\.?\\d*)")){ 
            if(s.length() > 9){
                Double num = Double.valueOf(s);
                if(num > Double.valueOf(Integer.MAX_VALUE))
                    return Integer.MAX_VALUE;
                if(num < Double.valueOf(Integer.MIN_VALUE))
                    return Integer.MIN_VALUE;
            }
    }
            if(s.matches("[1-9]*[.][0-9]*")){
                s = s.split("\\.",2)[0];

            }if(s.matches("([-+]?[0-9]+[-+]+[0-9]+)")){
                s=s.split("([-+][0-9]$)")[0]; 
            }if(s.matches("^[-+][+-][0-9]*") ){
                s = s.substring(2);
            }if(s.matches("[-+]?(\\d+[-+]+)")){
                s = s.split("[-+]+$")[0]; 
            }if(s.matches("^[+][0-9]*")){
                s = s.substring(1);
            }
            if(s.endsWith("-") ||s.endsWith("+"))
                s=s.substring(0,s.length()-1);
            if(s.endsWith("-+") ||s.endsWith("+-"))
                s=s.substring(0,s.length()-2);

            return Integer.valueOf(s);

        }
        return 0;
    }

    public static void main(String[] args) {
        System.out.println("Hello World!");
        String s1 = "42";
        String s2 = "   -42";
        String s3 = "4193 with words";
        String s4 = "words and 987";
        String s5 = "91283472332";
        String s6 = "3.145677";
        String s7 = "-91283472332";
        String s8 = "+1";
        String s9 = "-+1";
        String s10="  0000000000012345678";
        String s11="  -0012a42";
        String s12="-   234";
        String s13="-5-";
        String s14=".1";
        String s15="+-2";
        String s16="0-1";
        String s17="-1";
        String s18="-13+8";
        String s19="21474836++";
        String s20="  +b12102370352";
        System.out.println("returned="+ myAtoi(s20));
    }
}
Wellbeing
  • 5
  • 2