2

I need to write a piece of code which accepts an input string parameter and determine if exactly 3 question marks exist between every pair of numbers that add up to 10. If so, return true, otherwise return false.Some examples test cases are below

"arrb6???4xxbl5???eee5"      => true
"acc?7??sss?3rr1??????5"     => true
"5??aaaaaaaaaaaaaaaaaaa?5?5" => false
"9???1???9???1???9"          => true
"aa6?9"                      => false

I already tried to implement it in Java as below but the result is not as expected

public static String QuestionsMarks(String str) { 
str = str.replaceAll("[a-z]+","");
Pattern pattern = Pattern.compile("([0-9])([?])([?])([0-9])");
Pattern pattern01 = Pattern.compile("([0-9])([?])([?])([0-9])");
Matcher matcher01 = pattern01.matcher(str);
Pattern pattern02 = Pattern.compile("([0-9])([0-9])");
Matcher matcher02 = pattern02.matcher(str);
Matcher matcher = pattern.matcher(str);

if (matcher01.find() || matcher02.find()) {
return "false";
} else if (matcher.find()) {
  return "true";
 }

return "false";
}
Jim Garrison
  • 85,615
  • 20
  • 155
  • 190
maryam bg
  • 23
  • 4
  • Do you mean _"exactly 3 total question marks appear between pairs of 'adjacent' digits that add up to 10, in a string, where two digits are 'adjacent' if there are no other digits between them"_? – Jim Garrison Jan 20 '21 at 17:47
  • Why `9???1???9???1???9` results in `true` if it has only 5 digits? Can the matching digits overlap (9 & (1) & (9) & (1) & 9) between two groups? – Nowhere Man Jan 20 '21 at 18:24
  • @JimGarrison yes two numbers with add up to 10 should be adjacent without any other number in between – maryam bg Jan 21 '21 at 07:55
  • @AlexRudenko yes can overlap. groups can be like this 9&1,1&9,9&1,1&9 – maryam bg Jan 21 '21 at 07:55
  • @maryambg, please check the answer below – Nowhere Man Jan 21 '21 at 07:58

1 Answers1

1

The regular expression to detect overlapping numbers separated with a number of question marks is as follows:

(?=((\d)([^?\d]*\?[^?\d]*)*(\d))) It uses a positive lookahead (?=) to handle overlapping numbers between adjacent matches of this pattern:
(\d)([^?\d]*\?[^?\d]*)*(\d): two digits separated by any number of question marks with other optional characters.

Online demo of the regexp

So, the regular expression provides a stream of matches in the form: Group1=StringWithQuestionMarks, Group2=Digit, Group4=Digit which should be validated against the rules: count the sum of the digits to be 10 and count the question marks between to be 3.

Example implementation using Stream API:

private static final Pattern DIGS = Pattern.compile("(?=((\\d)([^?\\d]*\\?[^?\\d]*)*(\\d)))");

public static boolean hasTotal10Around3QMarks(String str) {
    
    Supplier<Stream<MatchResult>> ss = () -> DIGS
        .matcher(str)
        .results()
        .filter(r -> r.groupCount() == 4 
            && 10 == Integer.parseInt(r.group(2)) + Integer.parseInt(r.group(4))
        );
    
    return ss.get().findAny().isPresent() &&
           ss.get().allMatch(r -> 3 == r.group(1).chars()
                                                 .filter(c -> c == '?')
                                                 .count()
    );
}

Supplier<Stream> helps to reuse stream of MatchResult to handle the last test case when there's no matching pair of digits with 3 question marks between (allMatch for empty stream returns true).

Tests:

String[] tests = {
    "arrb6???4xxbl5???eee5",
    "acc?7??sss?3rr1??????5",
    "5??aaaaaaaaaaaaaaaaaaa?5?5",
    "9???1???9???1???9",
    "aa6?9",
    ""
};

Arrays.stream(tests)
      .forEach(t -> System.out.printf("'%s' => %s%n", t, hasTotal10Around3QMarks(t)));

Output:

'arrb6???4xxbl5???eee5' => true
'acc?7??sss?3rr1??????5' => true
'5??aaaaaaaaaaaaaaaaaaa?5?5' => false
'9???1???9???1???9' => true
'aa6?9' => false
'' => false
Nowhere Man
  • 19,170
  • 9
  • 17
  • 42