J'apprends Ruby et je fais des trucs en mathématiques. Une des choses que je veux faire est de générer des nombres premiers.
Je veux générer les dix premiers nombres premiers et les dix premiers seulement. Je n'ai aucun problème à tester un nombre pour voir s'il s'agit d'un nombre premier ou non, mais je me demandais quel était le meilleur moyen de générer ces chiffres?
J'utilise la méthode suivante pour déterminer si le nombre est premier:
class Integer < Numeric
def is_prime?
return false if self <= 1
2.upto(Math.sqrt(self).to_i) do |x|
return false if self%x == 0
end
true
end
end
Dans Ruby 1.9, il existe une classe principale que vous pouvez utiliser pour générer des nombres premiers ou pour vérifier si un nombre est premier:
require 'prime'
Prime.take(10) #=> [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
Prime.take_while {|p| p < 10 } #=> [2, 3, 5, 7]
Prime.prime?(19) #=> true
Prime implémente la méthode each
et inclut le module Enumerable, afin que vous puissiez faire toutes sortes de choses amusantes comme le filtrage, le mappage, etc.
require 'prime'
Prime.first(10) # => [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
Si vous souhaitez le faire vous-même, quelque chose comme ceci pourrait fonctionner:
class Integer < Numeric
def is_prime?
return false if self <= 1
2.upto(Math.sqrt(self).to_i) do |x|
return false if self%x == 0
end
true
end
def next_prime
n = self+1
n = n + 1 until n.is_prime?
n
end
end
Maintenant, pour obtenir les 10 premiers nombres premiers:
e = Enumerator.new do |y|
n = 2
loop do
y << n
n = n.next_prime
end
end
primes = e.take 10
Les gens ont déjà mentionné la classe Prime
, qui serait certainement la voie à suivre. Quelqu'un vous a également montré comment utiliser un Enumerator et je voulais contribuer une version utilisant un Fibre (il utilise votre méthode Integer#is_prime?
):
primes = Fiber.new do
Fiber.yield 2
value = 3
loop do
Fiber.yield value if value.is_prime?
value += 2
end
end
10.times { p primes.resume }
Découvrez le tamis d'Eratosthène. Ce n'est pas spécifique à Ruby mais c'est un algorithme pour générer des nombres premiers. L’idée derrière cet algorithme est que vous avez une liste/un tableau de nombres
2..1000
Vous prenez le premier numéro, 2. Parcourez la liste et éliminez tout ce qui est divisible par 2. Vous resterez avec tout ce qui n'est pas divisible par 2 sauf 2 lui-même (par exemple, [2,3,5,7,9, 11 ... 999]
Allez au nombre suivant, 3. Et encore une fois, éliminez tout ce que vous pouvez diviser par 3. Continuez jusqu'à ce que vous atteigniez le dernier nombre et que vous obteniez un tableau de nombres premiers. J'espère que cela pourra aider.
# First 10 Prime Numbers
number = 2
count = 1
while count < 10
j = 2
while j <= number
break if number%j == 0
j += 1
end
if j == number
puts number
count += 1
end
number += 1
end
Je l'ai fait pour un kata de codage et j'ai utilisé le tamis d'Eratosthène.
puts "Up to which number should I look for prime numbers?"
number = $stdin.gets.chomp
n = number.to_i
array = (1..n).to_a
i = 0
while array[i]**2 < n
i = i + 1
array = array.select do |element|
element % array[i] != 0 || element / array[i] == 1
end
end
puts array.drop(1)
class Numeric
def prime?
return self == 2 if self % 2 == 0
(3..Math.sqrt(self)).step(2) do |x|
return false if self % x == 0
end
true
end
end
Avec cela, maintenant, 3.prime?
renvoie true
, et 6.prime?
renvoie false
.
Sans passer aux efforts d'implémentation de l'algorithme tamis, il est possible de gagner du temps en vérifiant simplement la divisibilité jusqu'à la racine carrée et en sautant les nombres impairs. Ensuite, parcourez les nombres, en vérifiant leur primauté.
Rappelez-vous: temps humain> temps machine.
Je pense que cela peut être une solution coûteuse pour un très grand nombre max mais semble bien fonctionner sinon
def multiples array
target = array.shift
array.map{|item| item if target % item == 0}.compact
end
def prime? number
reversed_range_array = *(2..number).reverse_each
multiples_of_number = multiples(reversed_range_array)
multiples_of_number.size == 0 ? true : false
end
def primes_in_range max_number
range_array = *(2..max_number)
range_array.map{|number| number if prime?(number)}.compact
end
Voici un moyen de générer les nombres premiers jusqu’à un argument "max" à partir de zéro, sans utiliser Prime ni Math. Laissez-moi savoir ce que vous pensez.
def prime_test max
primes = []
(1..max).each {|num|
if
(2..num-1).all? {|denom| num%denom >0}
then
primes.Push(num)
end
}
puts primes
end
prime_test #enter max
Mise en œuvre du tamis d'Eratosthene (plus ou moins)
def primes(size)
arr=(0..size).to_a
arr[0]=nil
arr[1]=nil
max=size
(size/2+1).times do |n|
if(arr[n]!=nil) then
cnt=2*n
while cnt <= max do
arr[cnt]=nil
cnt+=n
end
end
end
arr.compact!
end
De plus voici un one-liner que j'aime beaucoup
def primes_c a
p=[];(2..a).each{|n| p.any?{|l|n%l==0}?nil:p.Push(n)};p
end
Bien sûr, ceux-ci trouveront les nombres premiers dans les premiers nombres n
et non les premiers nombres premiers n
, mais je pense qu'une adaptation ne demandera pas beaucoup d'effort.
Pas du tout lié à la question elle-même, mais à titre d'information:
Essayez avec cet extrait:
require 'prime'
for p in Prime::Generator23.new
# `p` brings subsequent prime numbers until the end of the days (or until your computer explodes)
# so here put your fabulous code
break if #.. I don't know, I suppose in some moment it should stop the loop
end
fp
Si vous en avez besoin, vous pouvez également utiliser un autre générateur plus complexe, tel que Prime::TrialDivisionGenerator
ou Prime::EratosthenesGenerator
. Plus d'informations
Ruby: Imprime N nombres premiers http://mishra-vishal.blogspot.in/2013/07/include-math-def-printnprimenumbernoofp.html
include Math
def print_n_prime_number(no_of_primes=nil)
no_of_primes = 100 if no_of_primes.nil?
puts "1 \n2"
count = 1
number = 3
while count < no_of_primes
sq_rt_of_num = Math.sqrt(number)
number_divisible_by = 2
while number_divisible_by <= sq_rt_of_num
break if(number % number_divisible_by == 0)
number_divisible_by = number_divisible_by + 1
end
if number_divisible_by > sq_rt_of_num
puts number
count = count+1
end
number = number + 2
end
end
print_n_prime_number