Related
While trying to solve the "paths on a grid" problem, I have written the code
def paths(n, k)
p = (1..n+k).to_a
p.combination(n).to_a.size
end
The code works fine, for instance if n == 8 and k == 2 the code returns 45 which is the correct number of paths.
However the code is very slow when using larger numbers and I'm struggling to figure out how to quicken the process.
Rather than building the array of combinations just to count it, just write the function that defines the number of combinations. I'm sure there are also gems that include this and many other combinatorics functions.
Note that I am using the gem Distribution for the Math.factorial method, but that is another easy one to write. Given that, though, I'd suggest taking #stefan's answer, as it's less overhead.
def n_choose_k(n, k)
Math.factorial(n) / (Math.factorial(k) * Math.factorial(n - k))
end
n_choose_k(10, 8)
# => 45
Note that the n and k here refer to slightly different things than in your method, but I am keeping them as it is highly standard nomenclature in combinatorics for this function.
def combinations(n, k)
return 1 if k == 0 or k == n
(k + 1 .. n).reduce(:*) / (1 .. n - k).reduce(:*)
end
combinations(8, 2) #=> 28
Explanation about the math part
The original equation is
combinations(n, k) = n! / k!(n - k)!
Since n! / k! = (1 * 2 * ... * n) / (1 * 2 * ... * k), for any k <= n there is a (1 * 2 * ... * k) factor both in the numerator and in the denominator, so we can cancel this factor. This makes the equation become
combinations(n, k) = (k + 1) * (k + 2) * ... * (n) / (n - k)!
which is exactly what I did in my Ruby code.
The answers that suggest computing full factorials will generate lots of unnecessary overhead when working with big numbers. You should use the method below for calculating the binomial coefficient: n!/(k!(n-k)!)
def n_choose_k(n, k)
return 0 if k > n
result = 1
1.upto(k) do |d|
result *= n
result /= d
n -= 1
end
result
end
This will perform the minimum operations needed. Note that incrementing d while decrementing n guarantees that there will be no rounding errors. For example, {n, n+1} is guaranteed to have at least one element divisible by two, {n, n+1, n+2} is guaranteed to have at least one element divisible by three and so on.
Your code can be rewritten as:
def paths(x, y)
# Choice of x or y for the second parameter is arbitrary
n_choose_k(x + y, x)
end
puts paths(8, 2) # 45
puts paths(2, 8) # 45
I assume that n and k in the original version were meant to be dimensions so i labeled them x and y instead. There's no need to generate an array here.
Edit: Here is a benchmark script...
require 'distribution'
def puts_time
$stderr.puts 'Completed in %f seconds' % (Time.now - $start_time)
$start_time = Time.now
end
def n_choose_k(n, k)
return 0 if k > n
result = 1
1.upto(k) do |d|
result *= n
result /= d
n -= 1
end
result
end
def n_choose_k_distribution(n, k)
Math.factorial(n) / (Math.factorial(k) * Math.factorial(n - k))
end
def n_choose_k_inject(n, k)
(1..n).inject(:*) / ((1..k).inject(:*) * (1..n-k).inject(:*))
end
def benchmark(&callback)
100.upto(300) do |n|
25.upto(75) do |k|
callback.call(n, k)
end
end
end
$start_time = Time.now
puts 'Distribution gem...'
benchmark { |n, k| n_choose_k_distribution(n, k) }
puts_time
puts 'Inject method...'
benchmark { |n, k| n_choose_k_inject(n, k) }
puts_time
puts 'Answer...'
benchmark { |n, k| n_choose_k(n, k) }
puts_time
Output on my system is:
Distribution gem...
Completed in 1.141804 seconds
Inject method...
Completed in 1.106018 seconds
Answer...
Completed in 0.150989 seconds
Since you're interested in the count rather than the actual combination sets, you should do this with a choose function. The mathematical definition involves evaluating three different factorials, but there's a lot of cancellation going on so you can speed it up by using ranges to avoid the calculations that will be cancelled anyway.
class Integer
def choose(k)
fail 'k > n' if k > self
fail 'args must be positive' if k < 0 or self < 1
return 1 if k == n || k == 0
mm = [self - k, k].minmax
(mm[1]+1..self).reduce(:*) / (2..mm[0]).reduce(:*)
end
end
p 8.choose 6 # => 28
To solve your paths problem, you could then define
def paths(n, k)
(n + k).choose(k)
end
p paths(8, 2) # => 45
The reduce/inject versions are nice. But since speed seemed to be a bit of an issue, I'd suggest the n_choose_k versions from #google-fail.
It is quite insightful and suggests a ~10-fold speed increase.
I would suggest that the iteration use the Lesser of k and ( n - k ).
N-choose-K and N-choose-(N-K) produce the same result (the factors in the denominator are simply reversed). So something like a 52-choose-51 could be done in one iteration.
I usually do the following:
class Integer
def !
(2..self).reduce(1, :*)
end
def choose(k)
self.! / (k.! * (self-k).!)
end
end
Benchmarking:
k = 5
Benchmark.bm do |x|
[10, 100, 1000, 10000, 100000].each do |n|
x.report("#{n}") { n.choose(k) }
end
end
On my machine I get:
user system total real
10 0.000008 0.000001 0.000009 ( 0.000006)
100 0.000027 0.000003 0.000030 ( 0.000031)
1000 0.000798 0.000094 0.000892 ( 0.000893)
10000 0.045911 0.013201 0.059112 ( 0.059260)
100000 4.885310 0.229735 5.115045 ( 5.119902)
Not the fastest thing on the planet, but it's okay for my uses. If it ever becomes a problem, then I can think about optimizing
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 writing Pascal's triangle in Ruby, but keep getting the error message:
pascalsTriangle.rb:3:in 'triangle': undefined method `each' for
4:Fixnum (NoMethodError) from pascalsTriangle.rb:18
def triangle(n)
for r in n:
lst=[1]
term=1
k=0
(0..r+1).step(1){ |index|
term=term*(r-k+1)/k
lst.append(term)
k+=1
}
print lst
end
end
triangle(4)
Why code C style in Ruby? :-)
Breaking the problem down would allow you to concentrate on one problem at a time and iterators would make the code more readable. I'm using the binomial theorem to calculate the values in the triangle. If you don't need a super large value from the triangle, this will be fast enough.
Calculating the 1000th line took 2.9 seconds on my virtual linux:
# factorial method
def fact(n)
(1..n).reduce(:*)
end
# binomial theorem, n choose k
def binomial(n,k)
return 1 if n-k <= 0
return 1 if k <= 0
fact(n) / ( fact(k) * fact( n - k ) )
end
def triangle(nth_line)
(0..nth_line).map { |e| binomial(nth_line, e) }
end
p triangle(5)
the final source code:
def triangle(n)
(0..n).each{|r|
lst=[1]
term=1
k=1
(0..r-1).step(1){|index|
term=term*(r-k+1)/k
lst.push term
k+=1
}
p lst
}
end
triangle(4)
changes:
you have syntax error on for r in n:.
a logical error on k=0 that causes Division by zero.
(0..r+1) is changed to (0..r-1)
there is no append method for array. changed to push
p is used instead of print
Factorial(num), takes a number and return the factorial of it.
find_num(n, k), is the mathmatical formula of pascales triangle. !n/
!k * !(n - k) ---- '!' = factorial of number
Lastly pascale(num), this iterates a new row of the triangle by
maping the index numbers or (k) for each row of (n).
If you want to truly understand how this works comment out the
pascale, and simply run numbers through find_num((row number),
(index number)). Then compare to a picture of the triangle to see
the magic for your self
-
def find_num(n, k)
result = factorial(n) / (factorial(k) * factorial(n - k))
end
def pascale(num)
i = 0
scale = 75
while i <= num
new_arr = []
(0..i).map {|x| new_arr << find_num(i, x)}
p new_arr.to_s.rjust(50 + scale)
i += 1
scale += 1
end
def factorial(num)
if num == 0
return 1
else
num *= factorial(num - 1)
end
end
end
pascale(12)
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)
I'm running through the problems on Project Euler to teach myself Ruby programming. I know there is a built-in function to do this, but I'm avoiding the built-in functions to help me learn.
So I have to write a method to determine if a number is a prime. The first method works, but the second doesn't. Can anyone explain why?
def is_prime n
for d in 2..(n - 1)
if (n % d) == 0
return false
end
end
true
end
def is_prime2 n
foundDivider = false
for d in 2..(n - 1)
foundDivider = ((n % d) == 0) or foundDivider
end
not foundDivider
end
It's because = is of higher precedence than or. See Ruby's operator precedence table below (highest to lowest precedence):
[ ] [ ]=
**
! ~ + -
* / %
+ -
>> <<
&
^ |
<= < > >=
<=> == === != =~ !~
&&
||
.. ...
? :
= %= { /= -= += |= &= >>= <<= *= &&= ||= **=
defined?
not
or and
if unless while until
begin/end
The problematic line is being parsed as...
(foundDivider = ((n % d) == 0)) or foundDivider
...which is certainly not what you mean. There are two possible solutions:
Force the precedence to be what you really mean...
foundDivider = (((n % d) == 0) or foundDivider)
...or use the || operator instead, which has higher precedence than =:
foundDivider = ((n % d) == 0) || foundDivider
Ruby comes with predefined classes such as Prime. All you have to do is to require that class into your project.
require 'prime'
Than, you can use some of the Prime methods such as first to get first x prime elements:
Prime.first(5) # Ret => [2, 3, 5, 6, 11]
Or you could do something like this:
Prime.each(100) do |prime|
p prime # Ret => [2, 3, 5, 7, 11, ..., 97]
end
I hope you find this useful.
def prime(n)
return false if n < 2
(2..n/2).none?{|i| n % i == 0}
end
A prime number is any number that has no positive divisors other than itself and 1.
def prime? n
(2..Math.sqrt(n)).none? {|f| n % f == 0}
end
The range of factors should start at 2 and end at the square root of n because every number is divisible by one and no number is divisible by two numbers greater than its square root.
Explanation: A non-prime number is the product of two numbers.
n = f1 * f2
n is always divisible by its square root so both f1 and f2 cannot be greater than the square root of n, otherwise f1 * f2 would be greater than n. Therefore, at least one factor is less than or at most equal to Math.sqrt(n). In the case of finding prime numbers its only necessary to find one factor so we should loop from 2 to the square root of n.
Find prime numbers from loop:
def get_prime_no_upto(number)
pre = [1]
start = 2
primes = (start..number).to_a
(start..number).each do |no|
(start..no).each do |num|
if ( no % num == 0) && num != no
primes.delete(no)
break
end
end
end
pre + primes
end
and use it as below:
puts get_prime_no_upto(100)
Cheers!
Here is code that will prompt you to enter a number for prime check:
puts "welcome to prime number check"
puts "enter number for check: "
n = gets
n = n.to_i
def prime(n)
puts "That's not an integer." unless n.is_a? Integer
is_prime = true
for i in 2..n-1
if n % i == 0
is_prime = false
end
end
if is_prime
puts "#{n} is prime!"
else
puts "#{n} is not prime."
end
end
prime(n)
Based on the answer by Darmouse but including edge cases
def prime? (n)
if n <= 1
false
elsif n == 2
true
else
(2..n/2).none? { |i| n % i == 0}
end
end
FYI - re: DarkMouses prime method above - I found it really helpful, but there are a few errors (I think!) that need explaining:
It should be parentheses rather than square brackets... Otherwise you get a TypeError
Range can't be coerced into Fixnum (TypeError)
Secondly, that first colon before 'false' would cause an error too. It's incorrect syntax, as far as I know. Get rid of it.
Lastly, I think you got it the wrong way round?? If you correct the errors I mentioned, it returns true if it ISN'T a prime, and false if it IS.
You can drop the ternary operator altogether I think, and just do:
def prime?(n)
(2..n/2).none?{|i| n % i == 0}
end
Obviously it doesn't cover the edge cases (0,1,2), but let's not split hairs.
...For those who enjoy hairsplitting, here is my full solution to this problem:
def prime?(n)
return false if n < 2
(2..Math.sqrt(n)).none? {|num| length % num == 0}
end
Hope I didn't miss anything :)
This is a little bit off topic according to the details, but correct for the title : using bash integration in ruby you could do :
def is_prime n
`factor #{n}`.split.count < 3
end
bash factor function returns a number plus all of his factors, so if the number is prime, there will be two words count.
This is usefull for code golf only.
I tried this and it worked:
def prime?(n)
return false if n < 2
return true if n == 3 || n == 2
if (2...n-1).any?{|i| n % i == 0}
false
else
true
end
end
def prime?(n)
if n <= 1
return false
else (2..n-1).to_a.all? do |integer|
n % integer != 0
end
end
end
From my prime? lab. Started with eliminating all integers less than or equal to 1.
def prime(n)
pn = [2]
if n < 2
return false
else
(2..n).each do |i|
not_prime = false
(2..Math.sqrt(i).ceil).each do |j|
not_prime = true if i % j == 0
end
pn.push(i) unless not_prime
end
end
return pn
end
p prime(30) gives
[2, 3, 5, 7, 11, 13, 17, 19, 23, 29]
It will return true if the number is prime.
def prime_number(number)
(2..(number-1)).each do |value|
if (number % value) == 0
return false
end
return true
end
end
puts prime_number(4)
class Object
private
def prime? num
if (2..3).include? num
return true
else
!num.even? and num % 3 != 0 and num > 1
end
end
end
prime? 1
prime? 2
prime? 9
prime? 17
** FOR A SIMPLE SHORTED METHOD**
FIRST INSTALL PRIME GEM
require 'prime'
`p prime.first(20)`
Now save that file as your desired name, this will generate the first 20 prime numbers Automatically!! :-)