غربال إراتوستينس في روبي
-
04-07-2019 - |
سؤال
بدلا من تجريف روبي نسخة من هذه الخوارزمية من صافي أردت أن تخلق بلدي على الوصف هنا.ولكن أنا لا يمكن معرفة شيئين
def primeSieve(n)
primes = Array.new
for i in 0..n-2
primes[i] = i+2
end
index = 0
while Math.sqrt(primes.last).ceil > primes[index]
(primes[index] ** 2).step(primes.length - 1, primes[index])
{|x| x % primes[index] == 0 ? primes.delete(x) : ""}
index += 1
end
primes
end
- لماذا لا تكرار إلى نهاية المصفوفة ؟
- وفقا الوصف في الرابط أعلاه يجب أن يكون حلقة مقسمة من عند squareroot من آخر عنصر في المصفوفة هو أكبر من رئيس الوزراء الحالي - الألغام لا هذا واحد من قبل.
أنا متأكدة من أنها قد تفعل شيئا مع عملية الحذف تعديل طول المصفوفة.على سبيل المثال بلدي وظيفة حاليا ينتج 2,3,5,7,9,10 عندما أدخل n=10 التي من الواضح أنها غير صحيحة.أي اقتراحات بشأن كيف يمكن أن تذهب حول alterating هذا أن تجعل من العمل مثل أنه من المفترض أن ؟
المحلول
التالية يبدو للعمل.أخذت من حساب النقطة العائمة و المربعة بدلا من مربع تأصيل.أنا أيضا استبدال حذف حلقة مع "حدد" الاتصال.
while primes[index]**2 <= primes.last
prime = primes[index]
primes = primes.select { |x| x == prime || x%prime != 0 }
index += 1
end
تحرير:أعتقد أنني عرفت كيف كنت تحاول أن تفعل هذا.التالية يبدو للعمل ، ويبدو أن يكون أكثر انسجاما مع النهج الأصلي.
while Math.sqrt(primes.last).ceil >= primes[index]
(primes[index] * 2).step(primes.last, primes[index]) do
|x|
primes.delete(x)
end
index += 1
end
نصائح أخرى
هناك أسرع في تنفيذ www.scriptol.org:
def sieve_upto(top)
sieve = []
for i in 2 .. top
sieve[i] = i
end
for i in 2 .. Math.sqrt(top)
next unless sieve[i]
(i*i).step(top, i) do |j|
sieve[j] = nil
end
end
sieve.compact
end
أعتقد أنه يمكن أن يكون تحسنت قليلا على النحو التالي:
def better_sieve_upto(n)
s = (0..n).to_a
s[0] = s[1] = nil
s.each do |p|
next unless p
break if p * p > n
(p*p).step(n, p) { |m| s[m] = nil }
end
s.compact
end
...إلى حد كبير لأنه من أسرع مجموعة initialisation, أعتقد, لكنه هامشية.(أضفت #compact
إلى كل لإزالة غير المرغوب فيها nil
s)
هذا هو بسيط جدا تنفيذ مقالة ويكيبيديا شبة الكود, باستخدام بت مجموعة.
#!/usr/bin/env ruby -w
require 'rubygems'
require 'bitarray'
def eratosthenes(n)
a = BitArray.new(n+1)
(4..n).step(2) { |i|
a[i] = 1
}
(3..(Math.sqrt(n))).each { |i|
if(a[i] == 0)
((i*i)..n).step(2*i) { |j|
a[j] = 1
}
end
}
a
end
def primes(n)
primes = Array.new
eratosthenes(n).each_with_index { |isPrime, idx|
primes << idx if isPrime == 0
}
primes[2..-1]
end
هذا هو إشارة لأولئك الذين يهتمون.رمز من هذا الموقع.
هذا الرمز يستخدم غربال إراتوستينس كذلك.
n = 1000000
ns = (n**0.5).to_i + 1
is_prime = [false, false] + [true]*(n-1)
2.upto(ns) do |i|
next if !is_prime[i]
(i*i).step(n, i) do |j|
is_prime[j] = false
end
end
count = 0
list = (0..n).map do |i|
count += 1 if is_prime[i]
count
end
while gets
puts list[$_.to_i]
end
و هنا آخر واحد.
def eratosthenes(n)
nums = [nil, nil, *2..n]
(2..Math.sqrt(n)).each do |i|
(i**2..n).step(i){|m| nums[m] = nil} if nums[i]
end
nums.compact
end
p eratosthenes(100)
أو
x = []
Prime.each(123) do |p|
x << p
end
قد يكون هناك طريقة لاستخدام حقن هنا ولكن بداية شيء يؤلم رأسي اليوم.