Permutational Primes Kata optimatization - ruby

I am solving the Permutational Primes Kata using Ruby. I manage to find out Brute-force solution but it exceeds the time limits. I need to optimize my code but I don't have any idea how to do this. The Kata.
require 'prime'
def permutational_primes(n_max, k_perms)
result_h = {}
result_keys = []
Prime.each(n_max) do |prime|
perms = prime.digits.permutation.to_a.map(&:join).map(&:to_i).uniq
prime_no_length = prime.to_s.length
perms = perms.delete_if { |el| el.to_s.length < prime_no_length }
# elimianate number greater than n_max
perms = perms.delete_if { |el| el > n_max }
next if (perms & result_keys).any?
perms = perms.delete_if { |el| !Prime.prime?(el) }
# minus one because we include
if perms.count - 1 == k_perms
result_h[prime] = perms
result_keys.append(prime)
end
end
return [0, 0, 0] if result_keys.empty?
[result_h.count, result_keys[0], result_keys[result_keys.count-1]]
end

Some low-hanging fruit:
Benchmarking is one way to understand what parts are more computationally expensive than others (likely Prime.prime?)
Find work that you're doing repeatedly or checks for information that you already know every Prime.each loop and cache it, trading memory for computation, e.g. Prime.prime?
All the common Enumerable methods create new Arrays. Instead, reuse existing arrays, e.g. map!

I have not yet thoroughly tested the following, but this general approach should speed things up considerably. There are two main elements that improved efficiency: use of the method Prime::each and maintaining a set of prime permutations already tested, to avoid unnecessary testing of duplicates.
require 'prime'
require 'set'
def permutational_primes(nMax, permutes)
skips = Set.new
enum = Prime.each
arr = []
while (prime = enum.next) < nMax
next if skips.include?(prime)
a = prime.digits.permutation.with_object([]) do |perm,a|
next if perm[-1].zero?
n = perm.reverse.join.to_i
if n < nMax && !skips.include?(n) && Prime.prime?(n)
skips << n
a << n
end
end
a.each { |n| skips << n }
next if a.size != permutes + 1
arr << a.min
end
[arr.size, arr.size.zero? ? 0 : arr.min, arr.size.zero? ? 0 : arr.max]
end
permutational_primes(1000, 3)
#=> [3, 149, 379]
This passes all tests but times out. I'm working on another optimization.
Explanation is under construction...

Related

Ruby - finding the first N palindromic prime using lazy evaluation

i think my code is correct - yet i do not return an array in time for N = 200. Error is "Terminated due to timeout"
what can i do to improve the performance of this code?
def is_palindrome? (n)
n.to_s==n.to_s.reverse
end
def is_prime? (n)
return false if n< 2
(2..Math.sqrt(n)).none? {|f| n % f == 0}
end
prime_palindrome =-> (n) do
1.upto(Float::INFINITY).lazy.select { |n| is_prime?(n) && is_palindrome(n) }.first(n)
end
n = gets.to_i
p prime_palindrome.call(n)
Ruby knows how to do this faster.
require 'prime'
Prime.each.lazy.
select { |p| p.to_s.then { |s| s == s.reverse } }.
take(200).to_a
Lazy enumerators (as used in #Amadan's answer) are useful but seem to have a reputation for being somewhat slow. I thought it might be interesting to do a simple benchmark here, comparing Amadan's answer with a straightforward calculation using a while loop.
require 'prime'
Lazy enumerator
def amadan(n)
Prime::EratosthenesSieve.instance.send(:initialize)
Prime.each.lazy.
select { |p| p.to_s.then { |s| s == s.reverse } }.
take(n).to_a
end
while loop
def cary(n)
Prime::EratosthenesSieve.instance.send(:initialize)
arr = []
enum = Prime.each
while n > 0
p = enum.next
s = p.to_s
if s == s.reverse
arr << p
n -= 1
end
end
arr
end
The first line of each method, Prime::EratosthenesSieve... is included to make the benchmark more realistic. See the discussion in the comments.
Benchmark
require 'fruity'
#
n = 200
compare(amadan: -> { amadan(n) }, cary: -> { cary(n) })
Running each test once. Test will take about 10 seconds.
cary is faster than amadan by 10.000000000000009% ± 1.0%
Results are similar for other values of `n`.

Efficient way to do addition on big array

I have an array with +20000 integer elements.
I want to create a new array where each element in the old array is added a modifying number. On a small sample array it would look like this:
old_array = [2,5,6,8]
modifying_number = 3
new_array = [5,8,9,11]
Is there any more efficient way than doing an iteration like this?
class Array
def addition_by(x)
collect { |n| n + x }
end
end
No. N iterations are the minimal complexity of this algorithm.
You can do it in place by modifying source array with collect!(if you for some reasons not need a source array). Complexity will be the same, additional big object will not created.
20k records is not much to worry about performance.
ary = Array.new(20000) { 1 }
ary.map! { |el| el + 1 }
would work totally fine.
I would just suggest to modify the initial array inplace instead of creating a new one (using method with bang), so it will definitely use less resources.
I guess it would mean implementing map in another way? This question deals with such a task. I've included benchmarks of the answers by #JörgWMittag and #uishra. Although it has to be said speed was not a requirement in the linked question so the answers cannot be criticised in that regard. I've also included #CarySwoveland's answer from this question.
require 'fruity'
require 'matrix'
class Array
#jörg_w_mittag
def new_map
return enum_for(__callee__) unless block_given?
inject([]) {|acc, el| acc << yield(el) }
end
#uishra
def my_map(&block)
result = []
each do |element|
result << block.call(element)
end
result
end
#cary_swoveland
def vec_map(k)
(Vector[*[k]*self.size] + Vector[*self]).to_a
end
end
arr = (1..30000).to_a
k = 3
10.times do
compare do
core_map { ar = arr.dup; ar.map { |n| n + k } }
jörg_w_mittag { ar = arr.dup; ar.new_map { |n| n + k } }
uishra { ar = arr.dup; ar.my_map { |n| n + k } }
cary_swoveland { ar = arr.dup; ar.vec_map k }
end
puts
end
A summary of the results/output:
Results on five occasions
#Running each test once. Test will take about 1 second.
#core_map is faster than jörg_w_mittag by 2x ± 1.0
#jörg_w_mittag is similar to uishra
#uishra is similar to cary_swoveland
Results on two occasions
#Running each test once. Test will take about 1 second.
#core_map is faster than jörg_w_mittag by 2x ± 0.1
#jörg_w_mittag is similar to uishra
#uishra is similar to cary_swoveland
Results on three occasions
#Running each test once. Test will take about 1 second.
#core_map is faster than uishra by 2x ± 1.0
#uishra is similar to jörg_w_mittag
#jörg_w_mittag is similar to cary_swoveland
require 'matrix'
class Array
def vec_map(k)
(Vector[*[k]*self.size] + Vector[*self]).to_a
end
end
[1,2,3].vec_map 4
#=> [5, 6, 7]

Ruby coding: List out all factors of numbers from 1-100

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

How do I generate the first n prime numbers?

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)

Ruby #select, but only select a certain number

Whats the best way in Ruby to do something like my_array.select(n){ |elem| ... }, where the n means "I only want n elements returned, and stop evaluating after that number is reached"?
This should do the trick:
my_array.select(n) { |elem| elem.meets_condition? }.take(n)
However, this will still evaluate all items.
If you have a lazy enumerator, you could do this in a more efficient manner.
https://github.com/ruby/ruby/pull/100 shows an attempt at enabling this feature.
You can easily implement lazy_select:
module Enumerable
def lazy_select
Enumerator.new do |yielder|
each do |e|
yielder.yield(e) if yield(e)
end
end
end
end
Then things like
(1..10000000000).to_enum.lazy_select{|e| e % 3 == 0}.take(3)
# => [3, 6, 9]
execute instantly.
Looks like there's no avoiding a traditional loop if you're using stock 1.8.7 or 1.9.2...
result = []
num_want = 4
i = 0
while (elem = my_array[i]) && my_array.length < num_want
result << elem if elem.some_condition
i += 1
end
You could make an Enumerable-like extension which has your desired selectn semantics:
module SelectN
def selectn(n)
out = []
each do |e|
break if n <= 0
if yield e
out << e
n -= 1
end
end
out
end
end
a = (0..9).to_a
a.select{ |e| e%3 == 0 } # [0, 3, 6, 9]
a.extend SelectN
a.selectn(1) { |e| e%3 == 0 } # [0]
a.selectn(3) { |e| e%3 == 0 } # [0, 3, 6]
# for convenience, you could inject this behavior into all Arrays
# the usual caveats about monkey-patching std library behavior applies
class Array; include SelectN; end
(0..9).to_a.selectn(2) { |e| e%3 == 0 } # [0,3]
(0..9).to_a.selectn(99) { |e| e%3 == 0 } # [0,3, 6, 9]
Why not flip this around and do the #take before the #select:
my_array.take(n).select { |elem| ... }
That will ensure you only do your computation for n number of items.
EDIT:
Enumerable::Lazy is known to be slower, but if your computation is known to be more computationally expensive than the lazy slowness, you can use the Ruby 2.0 feature:
my_array.lazy.select { |elem| ... }.take(n)
See: http://blog.railsware.com/2012/03/13/ruby-2-0-enumerablelazy/
I guess broken loop can be done in old-fashioned loop style with break or something like this:
n = 5
[1,2,3,4,5,6,7].take_while { |e| n -= 1; n >= 0 && e < 7 }
In functional language this would be recursion, but without TCO it doesn't make much sense in Ruby.
UPDATE
take_while was stupid idea as dbenhur pointed out, so I don't know anything better than a loop.

Resources