Search code examples
javajava-8hashmapfizzbuzz

Grouping of FizzBuzz numbers


I am trying to code FizzBuzz problem in Java8. It is working fine and I am getting desired output. For the number divisible by "3", it should return "Fizz", for the number divisible by "5", it should return "Buzz" and for the number divisible by both, it should return "FizzBuzz".

If I pass the value as "15" it returns:

["1","2","Fizz","4","Buzz","Fizz","7","8","Fizz","Buzz","11","Fizz","13","14","FizzBuzz"]

Now, I am stuck in one thing. I want to get an output as follows, if I pass the value as "15":

{"Fizz": [3, 6, 9, 12],"Buzz": [5, 10],"FizzBuzz": [15]}

I want to group the numbers by Fizz, Buzz, and FizzBuzz.

Here is my code:

public class FizzBuzzService {

private Map<Rule, String> ruleContainers = new HashMap();
private Set<Rule> rules  = new HashSet();

public FizzBuzzService(){
    addRule(i -> i % 15 == 0, "FizzBuzz");
    addRule(i -> i % 3 == 0, "Fizz");
    addRule(i -> i % 5 == 0, "Buzz");
}

public void addRule(Rule rule, String res) {
    rules.add(rule);
    ruleContainers.put(rule, res);
}

public String getValue(int i) {
    for (Rule rule : rules) {
        if (rule.apply(i)) {
            return ruleContainers.get(rule);
        }
    }
    return String.valueOf(i);
}

//then the origin code should be as follows:
public List<String> fizzBuzz(int n) {
     List<String> res = new ArrayList();
     for(int i = 1; i <= n; i++){
         res.add(getValue(i));
     }
     return res;
 }

interface Rule{
    boolean apply(int i);
}
}

I would really appreciate if someone can guide me. Thanks


Solution

  • I would return a Map<String, List<Integer>> (use a LinkedHashMap instead of a HashMap and your keys will preserve insertion order) creating List<Integer>(s) for fizz, buzz and fizzbuzz values. It could be done in a single static method like,

    public static Map<String, List<Integer>> fizzBuzz(int n) {
        Map<String, List<Integer>> map = new HashMap<>();
        List<Integer> fizz = new ArrayList<>(), //
                buzz = new ArrayList<>(), //
                fizzbuzz = new ArrayList<>();
        IntStream.rangeClosed(1, n).forEachOrdered(i -> {
            boolean f = i % 3 == 0, b = i % 5 == 0;
            if (f && b) {
                fizzbuzz.add(i);
            } else if (f) {
                fizz.add(i);
            } else if (b) {
                buzz.add(i);
            }
        });
        map.put("Fizz", fizz);
        map.put("Buzz", buzz);
        map.put("FizzBuzz", fizzbuzz);
        return map;
    }