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.

--

--

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

Love podcasts or audiobooks? Learn on the go with our new app.

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store
Adolfo Neto

Adolfo Neto

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