Esse algoritmo vai te ajudar a entender quando utilizar Recursão ou Enum com Elixir.
Tags: elixir, beginners, algorithms, fullstackelxpro
Published: 2022-06-16 11:26:32

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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sdv6r3k9bskddhqx3co3.png)


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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/6bppat88pk396yk1tyrk.png)


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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/sm7kevu6jc91yib24f8z.png)
 


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](https://dev-to-uploads.s3.amazonaws.com/uploads/articles/xsrwihwy4vn1z359jgc9.png)




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

```