No momento, estou aprendendo Python e me dando motivos para aplicar o que estou aprendendo. Estou tendo problemas com alguns dos problemas do Project Euler
Atualmente, estou no número 3, que é determinar o fator primordial mais alto desse número.
Deduzi que provavelmente preciso ter dois algoritmos, um para determinar a primalidade, e o segundo que envolveria a descoberta de fatores do número.
Então, eu tenho lido sobre artigos da Wiki . Tentando determinar qual pode ser o melhor algoritmo a ser usado e como fazê-lo.
Mas já faz um tempo desde que eu fiz alguma programação hardcore baseada em matemática e estou lutando para começar em algum lugar.
Eu estava olhando para usar o método de fatoração de Fermat com a inclusão de Trial by Division, mas não quero complicar demais. Não quero quebrar o RSA. Quero apenas dois algoritmos adequados para o meu problema, e aí está a minha pergunta.
Quais algoritmos você usaria para testar a primalidade / fatoração de um número adequado ao problema em questão?
Editar
Obrigado a todos por suas respostas e idéias, eles foram muito úteis. Eu votei em todos os que foram úteis, seja por conselhos ou por meio das próprias experiências de Euler. O que eu marquei como certo foi simplesmente o mais útil, pois me deu um lugar adequado para começar, do qual foi um empurrão na direção certa. Obrigado novamente =)
fonte
Respostas:
Minha abordagem para esses problemas geralmente é a seguinte: construa o algoritmo mais simples possível para resolvê-lo, que geralmente é uma abordagem ingênua de força bruta e, em seguida, teste / calcule matematicamente se é muito lento ou não. Na maioria das vezes é bom o suficiente. Quando não é, você tem um ponto de partida claro para trabalhar e otimizar as coisas até que o algoritmo seja eficiente o suficiente.
Aqui está um algoritmo simples para resolver o Problema 3 no Projeto Euler (em C, mas a tradução para o Python deve ser trivial):
fonte
isPrime
é um exagero. Basta fazer umn/=2
tempon%2==0
e depois começari
com 3 e depois fazer um loopif (n%i==0) n/=i; else i+=2;
é suficiente (bem, pode ser interrompido uma vezi*i > n
).Vale a pena escrever algum código que fatorize e encontre o primeiro (basicamente a mesma coisa), porque você provavelmente o reutilizará em muitas outras perguntas de Euler. Você poderá melhorar o código para perguntas posteriores e, talvez, examinar testes de primalidade não exaustivos, se achar que não é mais eficiente o suficiente, por isso sugiro que a abordagem mais simples no momento seja:
fonte
Na verdade, esta é uma área de pesquisa ativa em Matemática e Ciência da Computação. O artigo da wikipedia oferece uma boa visão geral:
http://en.wikipedia.org/wiki/Integer_factorization
Escolha qualquer algoritmo que você goste / ache interessante e experimente.
Você provavelmente terá que fazer uma troca: a maioria dos algoritmos "bons" exige um pouco de experiência em matemática para realmente entender (embora você possa implementá-los sem entendê-los completamente).
Se você não sabe por onde começar, recomendo a peneira quadrática:
http://en.wikipedia.org/wiki/Quadratic_sieve
Não requer conhecimentos matemáticos insanos, mas funciona bem.
fonte
Eu resolvi alguns problemas do ProjectEuler há algum tempo em Ruby usando a divisão de teste com números primos .
Eu descobri que gerar os números primos era muito mais crítico do que o algoritmo de fatoração real. Assim que substituí minha abordagem ingênua de geração de números primos por uma peneira, meus tempos de execução diminuíram para uma quantidade razoável.
fonte
Mantendo-o muito simples ...
Encontrando os fatores de X: eu começaria (n) em 2 e trabalharia até o número inteiro (piso, não arredondado) da raiz quadrada de X. Se dividir X por n, produzimos Y e Y é um número inteiro, ambos n e Y são fatores. Os valores mais baixos de n produzirão os valores mais altos de Y.
Primalidade de Y: Novamente, faça um loop (m) de 2 à raiz quadrada de Y e veja se Y / m é um número inteiro. Se for, então Y não é primo. Volte para encontrar outro fator.
Se m atinge a raiz de Y, você tem o seu número primo. Pare de olhar. Y é a resposta.
Se n atingir a raiz do X, não haverá fatores primos.
fonte
Como já existe uma solução completa, vou postar esta Haskell ...
Basicamente, não há necessidade de testar a primalidade. Se você dividir os fatores que encontrar (e se certificar de lidar com os fatores de repetição), nunca poderá ocorrer um fator não primário, porque um fator não primário é um produto de fatores primos menores.
Carregou e executou isso com o GHCi - é instantâneo e agora tenho um total geral de 4 (sim, quatro!) Problemas de Euler resolvidos.
fonte
Também estou moldando meu conhecimento em Python e também comecei a responder aos problemas do Project Euler no meu repositório do github: https://github.com/rentes/Euler .
Para o Problema 3, programei uma solução simples, baseada nas seguintes premissas:
1) dado um número inteiro positivo n, começo a dividi-lo por 2, 3, ..., m, e se eu achar que m é um fator primordial, adiciono-o a uma lista. Não estou adicionando à lista múltiplos de fatores primos já descobertos. Por exemplo, 4 é um múltiplo de 2, portanto 4 não é adicionado a esta lista.
2) Multiplico cada primo da lista para ver se é igual a n. Se iguais, encontramos todos os fatores primos de n. Caso contrário, continue dividindo n pelo próximo número m, até que todos os fatores primos sejam iguais a n ou m atinja n.
Consulte https://github.com/rentes/Euler/blob/master/problem3.py para obter mais detalhes. Adicionei comentários que ajudarão você a entender o que eu programei. É uma solução simples e tenho certeza de que não é a solução mais rápida, mas funciona e é simples o suficiente para entender.
Cumprimentos
fonte