Sieve of Eratosthenes in Ruby

前端 未结 5 1905
眼角桃花
眼角桃花 2020-12-14 20:10

Rather than scraping a Ruby version of this algorithm off the net I wanted to create my own based on its description here. However I cannot figure out two things

<         


        
相关标签:
5条回答
  • 2020-12-14 20:32

    The following seems to work. I took out the floating point arithmetic and squared instead of square rooting. I also replaced the deletion loop with a "select" call.

    while primes[index]**2 <= primes.last
          prime = primes[index]
          primes = primes.select { |x| x == prime || x%prime != 0 }
          index += 1
    end
    

    Edit: I think I figured out how you're trying to do this. The following seems to work, and seems to be more in line with your original approach.

    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
    
    0 讨论(0)
  • 2020-12-14 20:35

    There's a faster implementation at 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
    

    I think it can be improved on slightly thus:

    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
    

    ...largely because of the faster array initialisation, I think, but it's marginal. (I added #compact to both to eliminate the unwanted nils)

    0 讨论(0)
  • 2020-12-14 20:36

    This is a reference for those who are interested. The code is from this site.

    This code uses Sieve of Eratosthenes as well.

    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
    

    And here is another one.

    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)
    
    0 讨论(0)
  • 2020-12-14 20:38

    This is a pretty straightforward implementation of the Wikipedia article pseudocode, using a bit array.

    #!/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
    
    0 讨论(0)
  • 2020-12-14 20:48

    or

    x = []
    Prime.each(123) do |p|
      x << p
    end
    

    There may be a way to use inject here but the inception thing hurts my head today.

    0 讨论(0)
提交回复
热议问题