Algoritmos em JavaScript e Python com a pura e antiga matemática.
Algoritmo bom é aquele que considera o tempo de processamento e memória utilizada. Se um problema tende a ter crescimento de complexidade exponencial, o código para resolvê-lo precisa ser elegante para obter sucesso mesmo com alta carga de processamento, é o que demonstro com a abordagem Euclidiana abaixo. É bom lembrar que o motivo do algoritmo existir é executar uma tarefa. Considerar seus recursos é uma prática excelente e sempre bem vinda.
Fato é que a programação é extremamente poderosa, mesmo que você não saiba como resolver um problema, muito provavelmente ele ainda pode ser resolvido computacionalmente. Algoritmos de força bruta são muito utilizados, são martelos gigantes que resolvem a maioria dos problemas e, assim como várias outras coisas na computação, se apoiam na lei de Moore e efetivamente encontram o resultado esperado. Porém, frequentemente não são os mais eficientes no sentido de reduzir custo computacional, que pode ser medido por quão rápido um programa executa ("complexidade de tempo") ou quanto de memória é necessário ("complexidade de espaço").
O problema
O Mínimo Múltiplo Comum é um problema matemático maravilhoso para resolvermos com o poder da programação. Muitos de nós lembramos de resolver MMCs e MDCs com lápis e papel. O problema é escrever um programa que retorne o mínimo multiplicador comum de um conjunto de números inteiros composto pelo maior e menor número e todos os números inteiros entre eles. Ou seja f_mmc(1,4) retorna o mmc de [1,2,3,4]. Como objetos de controle que podem ser verificados aqui, o MMC esperado do conjunto [18,19,20,21,22,23] é 6056820, e do conjunto [15,16,18,19,20,21,22,23] é 411863760.
Força Bruta:
JavaScript - bad algorithm:
O tempo de execução pode alterar de acordo com o ambiente onde o código será executado. De toda forma, o número de iterações contabilizadas nos loops mais ativos indica o custo computacional para alcançar o resultado. No meu caso, 770 milissegundos para 1843380 iterações, pode parecer um esforço quase imperceptível mas esconde um perigo escalonável. Para retornar o MMC do conjunto [15,16,17,18,19,20,21,22,23] seriam necessárias mais de 179 milhões de iterações e aproximadamente 1 minuto de execução até o retorno com esse bad algorithm.
A elegância Euclidiana:
Para este problema proposto, a elegância Euclidiana está em entender relações como: subtrair os restos entre dois inteiros para encontrar o MDC, utilizar o MDC para encontrar o MMC e a clássica recursividade.
JavaScript - good algorithm
Escrevi em Python esses mesmos algoritmos e eles podem ser editados e executados direto do navegador nesse notebook aqui.
Clique em 'Run' para executar ambos os códigos e verificar os resultados. Observe que mesmo utilizando um exemplo com maior carga, a função com a matemática Euclidiana se mostra excepcionalmente mais eficiente, apenas 49 iterações para retornar corretamente o MMC de [15,16,17,18,19,20,21,22,23]: 411863760 em aproximadamente 3 milissegundos.
O importante aqui não é decorar determinado algorítimo ou competir por milésimos de segundo de execução, mas entender que existem milhares de abordagens para resolver qualquer problema. A abordagem Euclidiana pode nem mesmo ser o método mais eficiente para o problema aqui proposto, mas ela considera o custo computacional. Encontrar abordagens elegantes depende de um olhar minucioso sobre as relações matemáticas existentes congruentes com o problema. Não se engane, no fundo toda programação é matemática.
Plante uma árvore!
Top comments (0)