Avez-vous déjà joué au FizzBuzz autour d'un apéro ?

Cette semaine, c'est Benjamin qui vous propose un #KataOfTheWeek : FizzBuzz

Briefing du Kata : Pour ce début d'année 2020, je n'ai pas trop eu le temps de chercher un kata donc je vous en propose un très soft.

Avez-vous déjà joué au FizzBuzz lors d'apéro entre copains ?

Le principe est assez simple. Il vous faut compter de 1 à 100 en remplaçant les multiples de 5 par Fizz et les multiples de 7 ou qui se termine par 7 par Buzz. Lorsque le nombre est divisible par 5 et 7, vous le remplacez par FizzBuzz. L'une après l'autre, chaque personne autour de la table doit deviner le chiffre. La personne qui se trompe doit boire. La personne qui arrive à 100 peut rajouter une règle. Je pense que vous comprenez le jeu.

Je ne pense pas que vous allez avoir de difficulté à créer le programme pour résoudre ce problème. Cependant, j'aimerais que vous utilisiez le principe du TDD (Test Driven Development) lors du développement de votre kata. On est souvent sur des projets où l'on écrit des tests après coup. Ici, vous avez le temps vu que ce n'est pas compliqué. Vous allez devoir d'abord écrire vos tests, un test à la fois. Par exemple, si je suis un multiple de 5, je renvoie 'Fizz'. Ensuite, vous codez la solution pour que votre test passe. Vous faites du refacto si besoin et enfin, vous passez au second test.

Cet exercise est vraiment idéal pour faire de la TDD. Pour récapituler les règles :

  • on retourne Fizz si le nombre est divisible par 5.
  • on retourne Buzz si le nombre est divisible par 7 ou finit par 7.
  • on retourne FizzBuzz si le nombre est divisible par 5 et 7.
  • sinon on retourne le nombre

Après coup, j'ai trouvé un autre exercise sympa. On va dire que je suis tombé sur 100 et que j'ajoute une nouvelle règle :). Pour tous les nombres, vous devez les traduires en Romain. Ainsi, 2 devient II. Il va falloir ajouter un parser de nombre en chiffre romain.

Saurez-vous résoudre le problème ?

Bon courage !


Et voici une solution avec des tests proposée par l'auteur en Java:

package fr.takima;

import java.util.LinkedHashMap;
import java.util.Map;
import java.util.stream.IntStream;

public class FizzBuzz {
    private static Map<Integer, String> ROMAN_NUMERALS = new LinkedHashMap<>();

    {
        ROMAN_NUMERALS.put(100, "C");
        ROMAN_NUMERALS.put(90, "XC");
        ROMAN_NUMERALS.put(50, "L");
        ROMAN_NUMERALS.put(40, "XL");
        ROMAN_NUMERALS.put(10, "X");
        ROMAN_NUMERALS.put(9, "IX");
        ROMAN_NUMERALS.put(5, "V");
        ROMAN_NUMERALS.put(4, "IV");
        ROMAN_NUMERALS.put(1, "I");
    }

    public static void main(String[] args) {
        FizzBuzz app = new FizzBuzz();
        IntStream.range(1, 100).forEach(n -> System.out.println(app.processFizzBuzz(n)));
    }

    String processFizzBuzz(int i) {
        if (i % 7 == 0 || i % 10 == 7) {
            if (i % 5 == 0) {
                return "fizzbuzz";
            } else {
                return "buzz";
            }
        } else if (i % 5 == 0) {
            return "fizz";
        } else {
            return toRoman(i);
        }
    }

    private String toRoman(int number) {
        StringBuilder result = new StringBuilder();
        for (Map.Entry<Integer, String> e : ROMAN_NUMERALS.entrySet()) {
            while (number >= e.getKey()) {
                result.append(e.getValue());
                number -= e.getKey();
            }
        }
        return result.toString();
    }
}

// Les tests

package fr.takima;

import org.junit.jupiter.api.Test;

import static org.junit.jupiter.api.Assertions.assertEquals;

class FizzBuzzTest {

    private final FizzBuzz app = new FizzBuzz();

    @Test
    void testProcessFizzBuzz_of_5_return_Fizz() {
        assertEquals(app.processFizzBuzz(5), "fizz");
    }

    @Test
    void testProcessFizzBuzz_of_multiple_5_return_Fizz() {
        for(int i=5; i<100; i=i+5) {
            if (i % 7 != 0) {  // this was added after refacto
                assertEquals(app.processFizzBuzz(i), "fizz");
            }
        }
    }

    @Test
    void testProcessFizzBuzz_of_7_return_Buzz() {
        assertEquals(app.processFizzBuzz(7), "buzz");
    }

    @Test
    void testProcessFizzBuzz_of_multiple_7_return_Buzz() {
        for(int i=7; i<100; i=i+7) {
            if (i % 5 != 0) {  // this was added after refacto
                assertEquals(app.processFizzBuzz(i), "buzz");
            }
        }
    }

    @Test
    void testProcessFizzBuzz_of_17_return_Buzz() {
        assertEquals(app.processFizzBuzz(17), "buzz");
    }

    @Test
    void testProcessFizzBuzz_of_number_ending_by_7_return_Buzz() {
        for(int i=7; i<100; i=i+10) {
            assertEquals(app.processFizzBuzz(i), "buzz");
        }
    }

    @Test
    void testProcessFizzBuzz_of_35_return_FizzBuzz() {
        assertEquals(app.processFizzBuzz(35), "fizzbuzz");
        assertEquals(app.processFizzBuzz(70), "fizzbuzz");
    }

    @Test
    void testProcessFizzBuzz_of_93_print_XCIII() {
        assertEquals(app.processFizzBuzz(93), "XCIII");
    }

    @Test
    void testProcessFizzBuzz_of_51_print_LI() {
        assertEquals(app.processFizzBuzz(51), "LI");
    }

    @Test
    void testProcessFizzBuzz_of_41_print_XLI() {
        assertEquals(app.processFizzBuzz(41), "XLI");
    }

    @Test
    void testProcessFizzBuzz_of_11_print_XI() {
        assertEquals(app.processFizzBuzz(11), "XI");
    }

    @Test
    void testProcessFizzBuzz_of_9_print_IX() {
        assertEquals(app.processFizzBuzz(9), "IX");
    }

    @Test
    void testProcessFizzBuzz_of_4_print_IV() {
        assertEquals(app.processFizzBuzz(4), "IV");
    }

    @Test
    void testProcessFizzBuzz_of_1_print_I() {
        assertEquals(app.processFizzBuzz(1), "I");
    }

    @Test
    void testProcessFizzBuzz_of_19_print_XIX() {
        assertEquals(app.processFizzBuzz(19), "XIX");
    }
}

Votre équipe TakiVeille