Fizz Buzz em Elixir
Uma das coisas mais legais do Code Kata FizzBuzz é que imagino-o sendo usado em sala de aula com crianças. Sou professor, mas não sou professor de crianças, portanto nunca usei desta forma:
A professora (ou o professor) acabou de ensinar múltiplos e divisores e resolve fazer um teste com os alunos. Os alunos devem contar de um a cem, mas com certas condições. A professora escolhe o aluno que vai falar o próximo número da sequẽncia, aleatoriamente. O aluno não deve falar o próximo número, mas sim usar o próximo número para calcular o que vai falar de acordo com as seguintes regras:
- Se o número for múltiplo de 3 (mas não múltiplo de 5), o aluno deve falar “fizz” em vez do número.
- Se o número for múltiplo de 5 (mas não múltiplo de 3), a aluna deve falar “buzz” em vez do número.
- Se o número for múltiplo de 3 e múltiplo de 5, o aluno deve falar “fizzbuzz” em vez do número.
- Caso contrário, a aluna deve falar o número. Por exemplo, “quatro”.
Ou seja, a sequência seria:
1, 2, fizz, 4, buzz, fizz, 7, 8, fizz, buzz, 11, fizz, 13, 14, fizzbuzz, 16, 17, …
Simples, não é? No DojoPuzzles você encontra a descrição completa em português. Este pequeno problema (code kata) é bem popular em Coding Dojos. De acordo com o DojoPuzzles já foi usado em 476 dojos até hoje (só contando quem usou este site). Eu mesmo já usei mais de uma vez.
Como implementar o FizzBuzz? São várias as estratégias possíveis. Minha estratégia aqui é primeiro implementar uma função fizz/1, que retorna :fizz quando a entrada é múltiplo de 3 e o próprio número em caso contrário. E, de forma semelhante, implementar buzz/1.
Observe o uso da cláusula *when* para escolher quando
Para testar, basta salvar em um arquivo kata.ex e depois chamar:
> iex kata.ex
Veja os testes e resultados na imagem abaixo.
Mas isto não resolve o problema todo.
Queremos uma função fizzbuzz/1 tal que:
fizzbuzz(1) = 1
fizzbuzz(3) = :fizz
fizzbuzz(5) = :buzz
fizzbuzz(15) = :fizzbuzz
Minha ideia (não tenho certeza se é minha, mas se não for minha não lembro onde achei) é ter uma outra função, fizzbuzz_aux/2, que funcione da seguinte forma:
fizzbuzz_aux(:fizz,:buzz) = :fizzbuzz
fizzbuzz_aux(:fizz,_) = :fizz
fizzbuzz_aux(_,:buzz) = :buzz
fizzbuzz_aux(x,_) = x
Bem, o que está aí em cima é bem fácil de implementar em Elixir. Basta escrever (no mesmo arquivo kata.ex):
E depois, após recarregar o módulo com “r Kata”, testar:
Deu certo!
Agora o toque final é escrever a função fizzbuzz/2 da seguinte forma (linha 12):
E testar usando o for do Elixir. Como queremos o resultado de fizzbuzz para os números de 1 a 100, basta passar para o for, usando a variável n, os valores entre 1 e 100 (1..100 na notação de Elixir). Depois do “do:”, basta colocar o que deve ser feito com a variável n. Ou seja, algo como:
for n <- [faixa de valores], do: função_aplicada_a(n)
Na imagem abaixo, primeiro testei com 1 a 17 e depois fiz com 1 a 100.
Observe que quando chamei com 1 a 100, a lista resultante era muito grande e não foi totalmente exibida (foi até o 50). Uma solução é pedir para exibir os últimos 50 números:
(for n <- 1..100, do: Kata.fizzbuzz(n)) |> Enum.take(-50)
Enfim, dá ára fazer melhor mas por hoje é só.
Neste post aprendemos:
- a usar o when (superficialmente)
- a criar uma função que recebe dois argumentos
- a compor duas funções para obter uma nova função
- a usar o for (superficialmente) com algo como 1..100.