Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 9 years ago.
Improve this question
In an effort to speed up my program, I'm trying to combine these two methods, but am having the hardest time doing it. Here are the methods:
def prime?(number, array)
array.each do |x|
if number % x == 0
return false
end
end
true
end
def sum_prime_2(number)
i = 0
prime = 1
output = [2]
while prime < number
if prime?(prime, output)
i += 1
output << prime if prime != 1
end
prime += 2
end
output.inject(:+)
end
And here is what I've come up with, but it's not quite working. I'd love any help.
def sum_prime(number)
i = 0
prime = 1
output = [2]
while prime < number
if output.each { |x| prime % x == 0 } == true # prime? method
output << prime if prime != 1
i += 1
end
prime += 2
end
output.inject(:+)
end
Here's a simplification of your current approach:
def sum_primes(limit)
primes = [2]
n = 3
while n < limit
primes << n if primes.all? { |p| n % p != 0 }
n += 2
end
primes.inject(:+)
end
But you can do better. For example, there's no need to check for divisibility by all prior primes -- only up to the square of n. Even better would be a sieve approach, particularly an incremental one.
I would actually use this code, rather than combining the two functions:
def prime?(number, array)
array.each do |x|
if number % x == 0
return false
end
return true if x * x > number
end
true
end
Doing a quick benchmark for sum_prime_2(100000) versus FMc's answer versus mine, the original code takes about 5.0 seconds, FMc's takes 6.5 seconds, but my version just 0.1 seconds.
Related
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I am answering the following question:
Q3: Write a method, is_prime?, that takes a number num and returns
true if it is prime and false otherwise.
You may wish to use the modulo operation: 5 % 2 returns the remainder
when dividing 5 by 2: 1. If num is divisible by i, then num % i == 0.
(You would not be expected to already know about modulo for the
challenge)
but I get no answer back. My final "puts" doesn't seem to be working. Here is my code:
# Q3 method is_prime?
def is_prime? (num)
i = 2
while i <= num
is_divisble = ((num%i) == 0)
if is_divisble
return false
end
i+=1
end
# is not divisible
return true
end
puts 'select a number greater than one and see if it\'s prime'
num = gets.chomp.to_i
puts is_prime?(num)
The code prints fine. However, it always prints true. Remedy: change while i <= num
to while i < num .
i <= num
It is your mistake :).
Your code will increment i until i == num so num%i will always be true at the end.
Just replace it with
i < num
Write a function that prints out all the factors for each of the numbers 1 through 100.
Really amateur coder but here's my attempt so far.
def factors_numbers(n1,n2)
(n1..n2).each do |n|
factors = []
factors << 1 ##every number has a factor of 1
factors << n ##every number is a factor of itself
i = 1
while i < n
new_number = n % (n-i)
if new_number == 0 #if 0, divisible and that means two numbers are factors
factors << new_number
factors << (n-i)
end
i += 1
end
return factors
end
end
Here is an improved version of your code:
def factors_numbers(n1,n2)
all_factors = {}
(n1..n2).each do |n|
factors = []
(1..Math.sqrt(n).floor).each do |i|
remainder = n % i
if remainder == 0 #if 0, divisible and that means two numbers are factors
factors << i
factors << n/i
end
end
factors = factors.sort.uniq
puts "Factors of #{n}: #{factors.join(',')}"
all_factors[n]=[factors]
end
return all_factors
end
Do you want unique factors? That is, in the range 1-100, should I get the number 1 a hundred times, or only once?
The easiest way to do this is by leveraging the "inject" Enumerable method.
def find_all_factors_between(n1,n2)
(n1..n2).inject([]) do |factors, num|
factors + (1..num).inject([]) { |arry, test| num % test == 0 ? arry + [test] : arry }
end
end
One final thing to note is that Ruby has implicit returns; that is, as long as the output of the last line of your method is your factors variable, you don't have to say return factors.
And my entry would be:
def find_all_factors_between(n1, n2)
factors = -> (n) { (1..n).select {|i| n % i == 0} }
(n1..n2).each { |n| puts "Factors of #{n}: #{factors.(n).join(', ')}" }
end
find_all_factors_between(1,100)
Well, if you wanted to do it with enumerables, there's always
def factor_numbers(rng)
factors = rng.map do |n|
(1..Math.sqrt(n).floor) # search numbers <= square root
.select { |d| n % d == 0 } # find factors <= square root
.flat_map { |x| [x, n / x] } # combine with factors >= square root
.sort # order from least to greatest
.uniq # remove dupes (basically the square root)
end
Hash[rng.zip(factors)] # rng = keys, factors = values
end
puts factor_numbers(1..100)
It's not the most efficient, but my point is just that many of the for/while constructs you'd see in languages like C or JavaScript can be expressed in other ways in Ruby.
(n1..n2).each{|x| print "#{x}: #{(1..x).select{|y| x % y == 0}}\n"}
That oughta do it :)
edit: Implemented Cary Swoveland's suggestion
def factor_nums(n1,n2)
all_factors = {}
(n1..n2).each do |n|
factors = []
(1..n).each do |i|
remainder = n % i
factors << i if remainder == 0
end
all_factors[n] = factors
end
return all_factors
end
I am learning Ruby and doing some math stuff. One of the things I want to do is generate prime numbers.
I want to generate the first ten prime numbers and the first ten only. I have no problem testing a number to see if it is a prime number or not, but was wondering what the best way is to do generate these numbers?
I am using the following method to determine if the number is prime:
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
In Ruby 1.9 there is a Prime class you can use to generate prime numbers, or to test if a number is prime:
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 implements the each method and includes the Enumerable module, so you can do all sorts of fun stuff like filtering, mapping, and so on.
If you'd like to do it yourself, then something like this could work:
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
Now to get the first 10 primes:
e = Enumerator.new do |y|
n = 2
loop do
y << n
n = n.next_prime
end
end
primes = e.take 10
require 'prime'
Prime.first(10) # => [2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
Check out Sieve of Eratosthenes. This is not Ruby specific but it is an algorithm to generate prime numbers. The idea behind this algorithm is that you have a list/array of numbers say
2..1000
You grab the first number, 2. Go through the list and eliminate everything that is divisible by 2. You will be left with everything that is not divisible by 2 other than 2 itself (e.g. [2,3,5,7,9,11...999]
Go to the next number, 3. And again, eliminate everything that you can divide by 3. Keep going until you reach the last number and you will get an array of prime numbers. Hope that helps.
http://en.wikipedia.org/wiki/Sieve_of_Eratosthenes
People already mentioned the Prime class, which definitely would be the way to go. Someone also showed you how to use an Enumerator and I wanted to contribute a version using a Fiber (it uses your Integer#is_prime? method):
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 }
# 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
Implemented the Sieve of Eratosthene (more or less)
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
Moreover here is a one-liner I like a lot
def primes_c a
p=[];(2..a).each{|n| p.any?{|l|n%l==0}?nil:p.push(n)};p
end
Of course those will find the primes in the first n numbers, not the first n primes, but I think an adaptation won't require much effort.
Here is a way to generate the prime numbers up to a "max" argument from scratch, without using Prime or Math. Let me know what you think.
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
I think this may be an expensive solution for very large max numbers but seems to work well otherwise:
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
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
With this, now 3.prime? returns true, and 6.prime? returns false.
Without going to the efforts to implement the sieve algorithm, time can still be saved quickly by only verifying divisibility until the square root, and skipping the odd numbers. Then, iterate through the numbers, checking for primeness.
Remember: human time > machine time.
I did this for a coding kata and used the Sieve of Eratosthenes.
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)
Ruby: Print N prime Numbers
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
Not related at all with the question itself, but FYI:
if someone doesn't want to keep generating prime numbers again and again (a.k.a. greedy resource saver)
or maybe you already know that you must to work with subsequent prime numbers in some way
other unknown and wonderful cases
Try with this snippet:
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
If you need it, you also could use another more complex generators as Prime::TrialDivisionGenerator or Prime::EratosthenesGenerator. More info
Here's a super compact method that generates an array of primes with a single line of code.
def get_prime(up_to)
(2..up_to).select { |num| (2...num).all? { |div| (num % div).positive? } }
end
def get_prime(number)
(2..number).each do |no|
if (2..no-1).all? {|num| no % num > 0}
puts no
end
end
end
get_prime(100)
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 8 years ago.
Improve this question
I have the following code...
#organisims.each do |organisim|
randomvalue = rand(10)
prediction = organisim.predict
if prediction == randomvalue
organisim.resources += 1
end
if prediction != randomvalue
organisim.resources -= 1
end
end
I am trying to alter the 'organisims' resources if the prediction it makes matches the randomly generated number. It seems to work fine, -1 if no match, +1 if there is a match.
The problem is that when I iterate this array (of organisims), processing their resources, I recieve duplicates in my output, such as
Cycle 100
Average resouces: 1500
Cycle 101
Average resouces: 1500
Then again,
Cycle 102
Average resouces: 1400
Cycle 103
Average resouces: 1400
Is this an issue with my code (I see no issues with it) or with the psudorandom number generator that Ruby uses?
Cheers as always
Martin
I think this may be an issue of the scope of your accumulator consider this example.
# example Organism class
class Organisim
attr_accessor :predict, :resources, :prediction
def initialize
#resources = 0
end
def predict
#prediction = rand(10)
#prediction
end
end
# initialize #organisims
#organisims = []
100.times do
#organisims << Organisim.new
end
puts "!!!! Starting Organisim Specific Run"
# iterate over array tracking organisim's resource
#organisims.each_with_index do |org, i|
# parrallel assignment
r, p = rand(10), org.predict
#ruby ternery operator
(p == r) ? org.resources += 1 : org.resources -= 1
puts "Run #{i} Prediction: #{org.prediction} Instance Resources: #{org.resources} Overall Resources: n/a"
end
puts "!!!! Cumulative Resource Run"
# resources scoped outside the iteration loop as accumulator
overall_resources = 0
# re-initialize #organisims
#organisims = []
100.times do
#organisims << Organisim.new
end
#organisims.each_with_index do |org, i|
# parrallel assignment
r, p = rand(10), org.predict
#ruby ternery operator
#track class level resource
(p == r) ? org.resources += 1 : org.resources -= 1
#iterate accumulator
(p == r) ? overall_resources += 1 : overall_resources -= 1
puts "Run #{i} Prediction: #{org.prediction} Instance Resources: #{org.resources} Overall Resources: #{overall_resources}"
end
The first iteration loop is like (I think) the one that you have in your question but you're changing the resource within the organisim object instance.
The second iteration your accumulator is outside the scope of your iteration so it grows and shrinks as the objects are acted upon. :-)
It's a prime number sieve, but not Eratosthenes's Sieve.
I feel that it's poorly written because I'm new to programming and Ruby in general. This is only the second program I've written in Ruby, but I'd like to optimize it as best as possible. The problem is I don't have a firm understanding of what I need to change to make it faster, except that I know the program path/data structures aren't ideal - I just don't have a concept to work from to MAKE them ideal
An ideal answer won't necessarily say "change X to Y", but it would be more helpful if it pointed me in the direction of a good resource for this kind of information, or a method by which I can derive information regarding efficiency of different pieces of the program.
count = 0
x = 0
$results = Array.new []
inpt = []
class PrimeFun
def initialize(x, y)
array1 = (x..y).to_a
array1.each do |n|
if PrimeFun.primelogic(n%60, n) == 1
array1.delete_if { |p| p % n == 0}
$results << n
elsif n == 2 || n == 3 || n == 5
$results << n
end
end
end
def self.primelogic(r, n)
#prime = case r
when 1, 13, 17, 29, 37, 41, 49, 53
formulaone(n)
when 7, 19, 31, 43
formulatwo(n)
when 11, 23, 47, 59
formulathree(n)
else -1
end
end
def self.formulaone(n)
#x = 1
#y = -1
until 4*(#x**2) >= n
#y = -#y if Math.sqrt(n-(4*(#x**2))).floor - Math.sqrt(n-(4*(#x**2))) == 0
#x += 1
end
#y
end
def self.formulatwo(n)
#x = 1
#y = -1
until 3*(#x**2) >= n
#y = -#y if Math.sqrt(n-(3*(#x**2))).floor - Math.sqrt(n-(3*(#x**2))) == 0
#x += 1
end
#y
end
def self.formulathree(n)
#x = 1
#y = -1
until 3*(#x**2) >= n
#y = -#y if Math.sqrt(((#x**2)+n)/3).floor - Math.sqrt(((#x**2)+n)/3) == 0 && #x > #y
#x += 1
end
#y
end
end
x = STDIN.gets.to_i
while count < x
inpt << STDIN.gets.chomp
count += 1
end
inpt.each do |n|
a = n.split(" ").map { |a| a.to_i }
PrimeFun.new(a[0], a[1])
$results << ""
end
puts $results
You should familiarize yourself with the Benchmark module included in the Ruby standard library to measure the running time of (different versions of) your methods. I have not run the below code suggestions through Benchmark myself, they are just some quick ideas off the top of my head on how to improve the speed and readability of your code - feel free to benchmark them and report back with the results! :-)
Profiling your code to find the bottlenecks is also a good idea - no point spending hours optimizing parts of your code that is not contributing a large amount to the total run time. Check out the ruby-prof gem for a good tool to help you with this.
Now for a quick look at your code and some suggestions for improvement.
Without considering the actual algorithm your are using, your first order of business should be to eliminate your code's tendency to recalculate the same values over and over multiple times.
Also, you seem to be using instance variables (#x, #y, etc.) where local variables will do the job nicely. Not to mention your use of class methods which are only being called from within instance methods of the same class. You should turn those into instance methods as well. (These are not really optimization hints, but suggestions on how to improve your Ruby code.)
Take this method as an example:
def self.formulaone(n)
#x = 1
#y = -1
until 4*(#x**2) >= n
#y = -#y if Math.sqrt(n-(4*(#x**2))).floor - Math.sqrt(n-(4*(#x**2))) == 0
#x += 1
end
#y
end
In the loop, you are calculating the expression 4*(#x**2) three times. One is enough, so store the result in a temporary local variable, fsq. You are also calculating the square root of the same number two times inside the loop. Again, store the value in a temporary variable root, and use that.
def formulaone_b(n)
x = 1
y = -1
until (fsq = 4*(x**2)) >= n
root = Math.sqrt(n - fsq)
y = -y if root.floor - root == 0
x += 1
end
y
end
That should be a good start.
Probably not an optimization, but you can make the code a bit cleaner by calculating the range for x beforehand, then iterate over it using each:
def formulaone_c(n)
y = -1
(1..Math.sqrt(n / 4)).each do |x|
root = Math.sqrt(n - 4*(x**2))
y = -y if root.floor == root # See below
end
y
end
In the above code I have also replaced the comparison root.floor - root == 0 with the simpler but equivalent comparison root.floor == root, removing one unnecessary substraction.
One more idea: instead of calculating n - 4*(x**2) for each iteration, you might just gain a tiny bit of speed by noticing that this value will decrease by x * 8 + 4 every step, so use a helper variable d to update the value of the former expression like this:
def formulaone_d(n)
y = -1
d = n - 4 # Value of n - 4*(x**2) when x = 1
(1..Math.sqrt(n / 4)).each do |x|
root = Math.sqrt(d)
y = -y if root.floor == root
d -= x * 8 + 4 # Value of n - 4*(x**2) after x increases
end
y
end
Correctness
First, your code is not correct:
def self.formulathree(n)
#x = 1
#y = -1
until 3*(#x**2) >= n
#y = -#y if Math.sqrt(((#x**2)+n)/3).floor - Math.sqrt(((#x**2)+n)/3) == 0 && #x > #y
#x += 1
end
#y
end
Whether or not #y is less than #x is immaterial, and it's always true, since #y = ±1 and when #x = 1, #y = -1 < 1.
What you are interested in is the number of representations
n = 3*a^2 - b^2
with integers a > b > 0. Now, a^2 = (n + b^2)/3, so you want
(n + b^2)/3 > b^2
n + b^2 > 3*b^2
n > 2*b^2
and not n > 3*b^2 (b stands for #x here). For example,
143 = 11* 13 = 3*7^2 - 2^2 = 3*8^2 - 7^2
but 3*7^2 = 147 > 143, so #x = 7 wouldn't be considered, so 143 would be deemed prime by formulathree and
179 = 3*9^2 - 8^2
would not be considered prime, although it is, since 3*8^2 = 192 > 179.
Another problem becomes apparent when you output each considered n in initialize for debugging.
array1 = (x..y).to_a
array1.each do |n|
if PrimeFun.primelogic(n%60, n) == 1
array1.delete_if { |p| p % n == 0}
array1.each is more or less
for(index = 0; index < array1.length; ++i)
but when you remove the multiples of n, you also remove n itself, so the element directly after moves to the index n had, and is skipped. You can fix that by deleting only multiples of n greater than n:
array1.delete_if { |p| p > n && p % n == 0 }
Performance
The big performance problem is the algorithm. If you call initialize(2,n), for every prime, you traverse the array and remove multiples by trial division. Each prime is divided by each smaller prime (except 2, 3 and 5) to see whether it shall be removed from the array. That is the infamous Turner "sieve" whose complexity is O((n/log n)^2), almost quadratic. Since you don't even remove multiples of 2,3 and 5 from the array unless these multiples have larger prime factors, the complexity might be even slightly worse.
Micro-optimisations simply aren't worth the effort before you pick a better algorithm.
The next problem is the determination of primality using formulaX. If you also removed multiples of 2, 3 and 5 from the array, the test wouldn't even be necessary, every considered number would be a known prime per trial division. Since you don't, checking the candidate for divisibility by 2, 3 or 5 would be much faster than primelogic.
primelogic uses the logic also used for the Atkin sieve to determine primality, but it tests every number in isolation, therefore testing each number n is O(√n). Computing the square root is far more complicated than a division, hence that takes longer than a prime test by trial division.