2016-08-31 2 views
0

J'ai le code suivant où eratosthenes(N) retourne un tableau de nombres premiers de 1 à N. Ce que je veux faire est de supprimer les nombres de cette liste qui contiennent les chiffres 0, 2 , 4, 5, 6, 8. Mon code semble assez inefficace et mauvais car il faut environ 20 secondes (eratosthenes(N) est instantané) pour arriver à seulement 100 000 et ne supprime pas tous les numéros que je le veux. Existe-t-il une meilleure solution évolutive à ce problème?Efficacité de la recherche d'une grande liste de nombres pour certains chiffres

N = 1_000_000 
primes = eratosthenes(N) 

primes.each do |num| 
    if ["0", "2", "4", "5", "6", "8"].any? { |digit| num.to_s.include?(digit) } 
     primes.delete(num) 
    end 
end 
+0

"qui contiennent les chiffres 0, 2, 4, 5, 6, 8" - Je suis sûr que ce aw approche rong pour tamis Eratosthenes efficace. Vous voulez ignorer les chiffres dont le dernier chiffre est l'un de ceux-ci, n'est-ce pas? –

+0

De même, ne mutez pas le tableau que vous êtes en train d'itérer. Cela devrait expliquer le "ne supprime pas tous les nombres que je le veux" –

+0

Mes raisons pour supprimer 0, 2, 4, 5, 6, 8 sont séparées de ma recherche initiale de nombres premiers. J'ai déjà mon tableau de primes et je veux réformer davantage. Le deuxième point est dûment noté. –

Répondre

1

Le problème avec votre approche est que chaque delete réécrit le tableau, et il est appelé à tous les éléments supprimés, de sorte que la complexité de l'algorithme est O (n^2) au lieu de O (n).

Vous devriez faire quelque chose comme ceci:

primes.reject!{|num| ["0", "2", "4", "5", "6", "8"].any? { |digit| num.to_s.include?(digit) }} 

Ou simplement:

primes.reject!{|num| num.to_s[/[024568]/]} 

Il est juste une question de style, mais je mettrais tout ensemble dans une ligne (notez l'absence de ! en reject ici):

primes = eratosthenes(N).reject{|num| num.to_s[/[024568]/]} 
+0

Cela semble me donner deux réponses différentes. Si je cours le premier je reçois 1111 nombres premiers dans mon tableau et si je cours le second j'ai 3217 nombres premiers restants. –

+0

Ah, désolé, je n'ai pas remarqué votre liste comprend 5, je pensais que ce n'était que des nombres pairs. J'ai édité ma réponse, essayez-la maintenant. – michau

0

Je pense que vous cherchez quelque chose comme:

primes.reject!{|num| num % 2 == 0} 
+0

La tâche n'est pas de supprimer les nombres pairs (les nombres premiers autres que 2 ne le sont même pas), mais tous les nombres qui contiennent des chiffres pairs. – michau

+0

Cela ne fait rien pour ma liste déjà formée de nombres premiers vu que aucun ne sera divisé de manière égale par 2. Ce que je cherche mon programme à faire est de supprimer des nombres premiers comme 23, 47, 277 etc. parce qu'ils ont 2, 4 et 2 dans eux respectivement. –