Find the product of the number of letters "o" in all the words "google", "gooogle",... in a string

Viewed 94

I need to write a static function int count Google Product(String), which returns the product of the number of letters "o" in all the words "google", "gooogle", ... in a string.

  • P38.countGoogleProduct("google gooogle") == 6
  • P38.countGoogleProduct("google gogle gooogle gooogle") == 18 == 233
  • P38.countGoogleProduct("microsoft gogle") == 1
  • P38.countGoogleProduct("microsoft amazon facebooooook") == 1
  • P38.countGoogleProduct("googleing") == 1
  • P38.countGoogleProduct("googlee") == 1
  • P38.countGoogleProduct(" google google ") == 4 == 2*2
  • P38.countGoogleProduct("googlegoogle") == 1

The answer is guaranteed to be no more than 2*10^9.

This is my code:

import java.util.*;
import java.util.regex.*;
public class P38 {
    static int countGoogleProduct(String s) {
        boolean f = false;
        Pattern p = Pattern.compile("(( +goo+gle +)+( +goo+gle +))|( +goo+gle +)|(.*( +goo+gle +).*)");
        Matcher m = p.matcher(s);
        if (m.matches()) {
            f = true;
        } else {
            f = false;
        }
        if (f) {
            int c = 1;
            boolean g = false;
            String ns = new String();
            Pattern np = Pattern.compile("o+");
            Matcher nm = np.matcher(s);
            while (nm.find()) {
                ns = nm.group();
                c = c * ns.length();
            }
            return c;
        } else {
            return 1;
        }
    }
    public static void main(String[] args) {
        String s = new String("...");
        System.out.println(countGoogleProduct(s));
    }
}

But it doesn't work on some tests like " googlegoogle google " == 8 (right anwer 2) "googlegoogle google" == 1 (right anwer 2) Could you tell me how can I fix this?

3 Answers

One way to do this is to capture all the os in a capture group, so that you can find the captured string's length, and multiply that. Also, use \b to match the word boundaries, so you only match go+gle when it is surrounded by non-word characters.

static int countGoogleProduct(String s) {
    boolean f = false;
    Pattern p = Pattern.compile("\\bg(o+)gle\\b");
    Matcher m = p.matcher(s);
    int product = 1;
    while (m.find()) {
        product *= m.group(1).length();
    }
    return product;
}

You didn't say what should happen for ggle. Should I count that as a 1 or 0? The above code will count it as a 1. If you want to count it as a 0, replace the quantifier + with *.

You can simplify it greatly by splitting the string on whitespace and then processing each part. While processing each part, calculate the sum of o in each part and multiply the same with product where product is the variable initialized with 1 before you process the parts of the string.

public class Main {
    public static void main(String[] args) {
        // Test
        String[] arr = { "google gooogle", "google gogle gooogle gooogle", "microsoft gogle",
                "microsoft amazon facebooooook", "googleing", "googlee", " google google ", "googlegoogle" };
        for (String s : arr) {
            System.out.println(s + " => " + countGoogleProduct(s));
        }
    }

    static int countGoogleProduct(String str) {
        int product = 1;

        // Convert to a single case and then split on whitespace
        String[] arr = str.toLowerCase().split("\\s+");

        for (String s : arr) {
            if (s.matches("g(o{2,})gle")) {
                int sum = 0;
                for (char ch : s.toCharArray()) {
                    if (ch == 'o') {
                        sum++;
                    }
                }
                product *= sum;
            }
        }
        return product;
    }
}

Output:

google gooogle => 6
google gogle gooogle gooogle => 18
microsoft gogle => 1
microsoft amazon facebooooook => 1
googleing => 1
googlee => 1
 google google  => 4
googlegoogle => 1

The regex, g(o{2,})gle means g followed by two or more o followed by gle. Check this for a demo of the regex.

public static int count(String in) {

    return new Scanner(in)
        .findAll("(?<!\\w)g(o+)gle(?=(\\s|$))")
        .mapToInt(mr -> mr.group(1).length())
        .reduce(Math::multiplyExact)
        .orElse(1);
}
  • find all occurrences of g, followed by any number of repeating o, followed by gle, followed by either : a space or the end of the String ((?=(\\s|$)))

  • at the same time the previous match must not start with any word character ((?<!\\w))

  • from the previous match find how many those o where repeating.

  • reduce those using Math::multiplyExact

Related