Solucionado (ver solução)
Solucionado
(ver solução)
1
resposta

Estruturas de dados - Hora da prática

Questão 5 do Desafio - Hora da prática no módulo Estruturas de dados, semana 2 - Curso: Python para dados.

Para o problema da questão número 5 verifiquei em dois algoritmos o mesmo resultado, há diferenças entre o dois algoritmos principalmente no tamanho e na quantidade de código. Gostaria de saber se a refatoração de um algoritmo mais amplo para um algoritmo mais simples (simplificado), ambos produzindo o mesmo resultado para o mesmo problema, pode afetar negativamente a lógica do código e prejudicar o programa?

Os algoritmos são estes:

Algorítmo maior

num = int(input("Digite um número: "))
lista_primos = []
for n in range(2, num):
  primo = True
  for p in range(2, n):
    if n % p == 0:
      primo = False
      break
  if primo:
    lista_primos.append(n)
print(lista_primos)

Saída:

Digite um número: 18
[2, 3, 5, 7, 11, 13, 17]

Algoritmo menor

num=int(input('Digite um número: '))
primos=[i for i in range(2,num) if all(i%j for j in range(2,i))]
print(primos)

Saída:

Digite um número: 18
[2, 3, 5, 7, 11, 13, 17]
1 resposta
solução!

Olá, Aristóteles! Tudo bem?

Essa é uma dúvida excelente e toca em um dos pilares mais importantes do desenvolvimento: o equilíbrio entre legibilidade e concisão.

A resposta curta é: não, a refatoração para um código simplificado geralmente não afeta negativamente a lógica, desde que o resultado esperado e a performance sejam mantidos. No entanto, há nuances que vale a pena considerar.

Comparando os dois Algoritmos

  1. Algoritmo Maior (Explícito):

    • Utiliza laços for aninhados e uma variável de controle (primo = True).
    • É mais fácil de depurar (fazer o "debug") passo a passo.
    • É a forma mais didática de entender como o algoritmo de busca de primos funciona.
  2. Algoritmo Menor (List Comprehension):

    • Utiliza List Comprehension e a função all().
    • É muito mais "Pythônico" (segue o estilo idiomático da linguagem).
    • É extremamente conciso, o que é ótimo para scripts rápidos.

A refatoração pode ser negativa?

A simplificação só se torna negativa em dois cenários principais:

  • Legibilidade (Manutenibilidade): Em projetos grandes ou em equipe, um código muito simplificado (como o seu segundo exemplo) pode levar mais tempo para ser compreendido por outro desenvolvedor do que o código explícito. O leitor precisa entender o que o all() faz e como a lógica booleana dentro dele está operando.
  • Performance (Complexidade): No caso específico de números primos, ambos os seus algoritmos têm uma complexidade de tempo de cerca de $O(n^2)$. Para números muito grandes, ambos seriam lentos. A refatoração para simplificar o código não melhora a performance nesse caso; para isso, seriam necessárias mudanças na lógica matemática (como o Crivo de Eratóstenes).

Dica de Especialista

No dia a dia de um Cientista de Dados, preferimos o meio-termo. O segundo algoritmo é elegante, mas o primeiro é mais claro sobre o que está acontecendo.

Uma pequena correção técnica no seu segundo código: a expressão all(i%j for j in range(2,i)) funciona porque, em Python, números diferentes de zero são considerados True e o zero é False. Quando i % j == 0, o all() recebe um False e identifica que o número não é primo. É uma lógica brilhante, parabéns por explorá-la!

O veredito: Continue explorando as simplificações! Elas mostram que você domina as ferramentas avançadas da linguagem, mas sempre se pergunte: "Se eu ler esse código daqui a seis meses, vou entender o que ele faz em 3 segundos?".

Espero que possa ter lhe ajudado!

Qual desses dois estilos você se sente mais confortável escrevendo no momento?