DEV Community

Elxpro
Elxpro

Posted on • Updated on

Esse algoritmo vai te ajudar a entender quando utilizar Recursão ou Enum com Elixir.

Seja muito bem vindo, seja muito bem vinda ao FullstackElxpro

Do you want to learn Elixir in three months? https://elxpro.com/sell

Aqui nós discutimos as estratégias e dicas de sua jornada de aprendizado em Elixir. Isso é do zero até a sua primeira vaga como desenvolvedor elixir

Eu sou o Gustavo e o tema de hoje é: Recursao ou Enum, quando utilizar com Elixir.

Qual a Diferença entre Recursão e Enum?

Enum: Um conjunto de algoritmos para fazer enumeração em coleções.

Recursão é um método de resolução de problemas que envolve quebrar um problema em subproblemas menores e menores até chegar a um problema pequeno o suficiente para que ele possa ser resolvido trivialmente. Normalmente a recursão envolve uma função que chama a si mesma. Embora possa não parecer muito, a recursão nos permite escrever soluções elegantes para problemas que, de outra forma, podem ser muito difíceis de programar.

Quais os maiores benefícios de usar Recursão?

Todos os meus posts estão sempre relacionados a minha experiência, e como eu utilizo no dia a dia e sempre o meu maior e te explicar e te dar as situações que eu passei para você tomar as suas decisões no dia a dia. O que eu tenho visto como vantagem com a recursão é ter o controle total do seu algoritmo e saber quebrá-lo em pequenos passos e etapas (o que no começo não é tão simples e te exige muita prática) mas vamos ter um exemplo técnico hoje. te possibilita dar bons nomes para variáveis, utilizar diversos patterns matchings, chamadas de funções independentes.

O que vale mais? utilizar Recursão ou Enum?

E uma pergunta bem interessante, e o mais interessante a se pensar aqui são 3 pontos:

  1. Performance
  2. Leitura de código
  3. Resolução de problemas.

Performance

A questão da performance é sempre importante em grande escala, processamento de milhares de linhas e onde pode complicar a sua recursão. O que te existe saber mais sobre análise assintótica. notação big O e saber análises de algoritmos para melhorar.

Veja o artigo: https://joaoarthurbm.github.io/eda/posts/analise-assintotica

ps: alguns pontos e estrutura de dados em elixir é um tópico interessante para abordar mas isso fica para um outro artigo.

A questão do Enum, quando eu fiz comparação de performance ele sempre sai ganhando, porém em algumas estruturas eu tive muito mais controle em recursão e saídas de dados e utilizando técnicas de railway e você pode aprender sobre esse tópico no video abaixo:

*vide o video: https://youtu.be/oyoRNxTF7-U
*

Leitura de Código

Acredito que a recursão te possibilita bons nomes de variáveis no dia a dia, tem que tomar cuidado pois um deslize, dependendo de como foi criado a recursão pode ser fatal, e dificultando a leitura de código de outros desenvolvedores.

O mesmo vale para o Enum, mas para um desenvolvedor (ou não) Elixir o enum é muito mais confortável.

Resolução de Problemas

Recursão neste caso sempre foi o meu favorito pois eu tenho controle sobre técnicas de TDD e não preciso ficar na tentativa e Erro de qual é a melhor função a ser chamada do Enum. Mas essa tem sido a minha experiência, utilizando pair programming foram as melhores soluções e outros devs acompanharam muito bem. Porém a leitura para outros devs sem o contexto foi complicada para refatorar ou corrigir bugs…

Conclusão.

Como desenvolvedor não tenho certo ou errado de utilizar Enum ou Recursão e por muito tempo eu usei mais recursao, pois para mim e mais fácil para quebrar o problema em pequenos pedaços e por facilitar a utilização de TDD.

Só que eu me deparei que pessoas não conseguiram ler meu código ao utilizar recursão.

Um Benchmark se for necessário e também outra pessoa revisando seu código para te dar feedback do que é o melhor para o contexto do seu algoritmo.

O que é importante lembrar que tipo de baixo dos panos o Enum utiliza recursão e não saber os os utilizar recursão pode colocar em situações complicadas de tomar decisão.

Por onde começar?

Calculo de Troco

Imagine um cenario onde voce tem 5 reais, e gastou 0.99 centavos, e voce tem que retornar o troco com moedas de:

  • 1 centavo
  • 5 centavos
  • 10 centavos
  • 25 centavos
  • 50 centavos
  • E valor em Dolar

Image description

A funcao get_change(5, 0.99) te possibilita receber os valores e o primeiro calculo e a subtracao. E como estamos falando de Nao inteiros vamos utilizar o float para para aredondar o valor:

Image description

A nossa proxima iteracao e muito simples. Basta converter este valor para String o que esta a esquerda do ponto e o nosso valor em Dolar a direita e onde temos que calcular o troco.

Image description

Agora para calcular os centavos temos que fazer 3 coisas.

Ter certeza que vamos pegar somente duas casas decimais
Converter para String
E criar uma recusao com um valor padrao de um array contando as moedas de troco, subtraindo o valor, pelo valor da maior moeda, e incrementando um contado como o exemplo abaixo:

Image description

E o resultado final sera:

defmodule ChangeCalculator do
  # 1c, 5c, 10c, 25c, 50c
  def get_change(money, value_spent) do
    (money - value_spent)
    |> Float.round(2)
    |> get_usd
    |> get_cents
  end

  defp get_usd(value) do
    value
    |> Float.to_string()
    |> String.split(".")
    |> then(fn [real, cents] ->
      real = String.to_integer(real)
      {real, cents}
    end)
  end

  defp get_cents({real, cents}) do
    cents =
      cents
      |> String.split_at(2)
      |> then(fn {cents, _} -> String.to_integer(cents) end)

    convert_cents_to_currency(cents) ++ [real]
  end

  defp convert_cents_to_currency(cents) do
    check_currency(cents, [0, 0, 0, 0, 0])
  end

  defp check_currency(0, array), do: array

  defp check_currency(value, [one_c, five_c, ten_c, t_c, fifty_c]) when value >= 50 do
    rest = value - 50
    check_currency(rest, [one_c, five_c, ten_c, t_c, fifty_c + 1])
  end

  defp check_currency(value, [one_c, five_c, ten_c, t_c, fifty_c]) when value >= 25 and value < 50 do
    rest = value - 25
    check_currency(rest, [one_c, five_c, ten_c, t_c + 1, fifty_c])
  end

    defp check_currency(value, [one_c, five_c, ten_c, t_c, fifty_c]) when value >= 10 and value < 25 do
    rest = value - 10
    check_currency(rest, [one_c, five_c, ten_c + 1, t_c, fifty_c])
  end

  defp check_currency(value, [one_c, five_c, ten_c, t_c, fifty_c]) when value >= 5 and value < 10 do
    rest = value - 5
    check_currency(rest, [one_c, five_c + 1, ten_c, t_c, fifty_c])
  end

  defp check_currency(value, [one_c, five_c, ten_c, t_c, fifty_c]) when value >= 1 and value < 5 do
    rest = value - 1
    check_currency(rest, [one_c + 1, five_c, ten_c, t_c, fifty_c])
  end

end

Enter fullscreen mode Exit fullscreen mode

Top comments (0)