Adolfo Neto
4 min readFeb 14, 2018

--

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:

Fonte: https://www.freeimages.com/photo/a-village-school-programme-1239862

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.

--

--

Adolfo Neto

Associate Professor at UTFPR. Interested in programming (Elixir), logic and Deep Work.