In this example, the fiber is resumed once more to create one more output unexpectedly. The target is to print all the permutation of one array of numbers by iterating through all the possibilities with recursion and print out the result in a fiber.
class Fiber
def self.wrap
if block_given?
f=Fiber.new do |*args|
yield *args
end
return lambda{|*args| f.resume(*args) if f.alive? }
end
end
end
class FiberIterator
def initialize
#fiber_wrap=Fiber.wrap do
yield
end
end
def each
while value=#fiber_wrap.call
yield value
end
end
end
def perm(a)
FiberIterator.new{ permgen(a,a.size) }
end
def permgen (a, n)
if n == 0 then
Fiber.yield a
else
n.times do |i|
a[n-1], a[i] = a[i], a[n-1]
permgen(a, n - 1)
a[n-1], a[i] = a[i], a[n-1]
end
end
end
def printResult (a)
p a
end
it=perm([1,2,3,4])
for a in it
printResult(a)
end
The result will include an additional 3 after print out all the permutations have been printed. Could anyone help with this?
The reason is that n.times returns n:
1.times { } # => 1
and the return value from permgen is being caught and evaluated as part of it and thus printed out. Too tired atm to go through and fully understand what's yielded or resumed where and when to try and explain how it's getting caught up and printed as if it was a permutation, but you can fix the code by just changing permgen to:
def permgen (a, n)
if n == 0 then
Fiber.yield a
else
n.times do |i|
a[n-1], a[i] = a[i], a[n-1]
permgen(a, n - 1)
a[n-1], a[i] = a[i], a[n-1]
end
nil # << This is all I added
end
end
As a side note, when I ran your code it was printing a 4 not a 3 at the end, based this answer on that being a typo or the result of a different array or playing around with different sized permutations.
Related
i'm starting in ruby and i don't know why this is happening.
this is my code.
def buble_sort(a)
i = 0
print a.size()
while i < a.size() do
if a[i] > a[i+1] then
temp = a[i]
a[i] = temp
a[i+1] = a[i]
end
i = i + 1
end
return a
end
puts "Amount of elements in your array"
n = gets.chomp.to_i
a = []
n.times do |num|
puts "input your element #{num}"
a <<gets.chomp.to_i
end
puts a
a = buble_sort(a)
puts "Array sorted #{a}"
And the output give me this error:
4burbuja.rb:6:in >': comparison of Fixnum with nil failed (ArgumentError)
from burbuja.rb:6:inbuble_sort'
from burbuja.rb:24:in `'
I understand that you are learning ruby and want to implement your own bubble sort. a.sort is easy but doesn't teach you anything. I'm glad you are learning by doing! There is a flaw in your bubble sort method. You are incrementing i and using it as an index for your array on each iteration. It could take many iterations to complete, in the worst case it will take n**2 (n squared) iterations which will clearly be more than the elements in your array. However if your code worked as I expect you expected it to run it would only make one pass on the array.
This is a classic ruby bubble sort. (with your having the user fill the array from console)
Notice that we continue to process the ENTIRE array multiple times until we no longer need to swap any values.
def bubble_sort(array)
n = array.length
puts "Sorting your array of #{n} items"
loop do #will loop forever till we break
#When we go through the entire array
#and don't have to swap then the array
#is sorted
swapped = false
(n-1).times do |i|
print "*" #just to illustrate how many iterations occur
if array[i] > array[i+1]
array[i], array[i+1] = array[i+1], array[i] #swap these values, no pesky temp variable
swapped = true
end
end
break if not swapped #we are done exit the loop
end
array #return the sorted array
end
puts "Amount of elements in your array"
n = gets.chomp.to_i
a = []
n.times do |num|
puts "input your element #{num}"
a <<gets.chomp.to_i
end
puts a
a = bubble_sort(a)
puts "Array sorted #{a}"
Here is an example of it being run via console
Cyclops% ruby sort_test.rb
Amount of elements in your array
6
input your element 0
5465463
input your element 1
3421
input your element 2
432143
input your element 3
234123
input your element 4
645
input your element 5
1
5465463
3421
432143
234123
645
1
Sorting your array of 6 items
******************************
Array sorted [1, 645, 3421, 234123, 432143, 5465463]
Cyclops%
I'm trying to do array practice problems and I'm working on insertion sort right now. I'm wondering whether this code is clear and readable. To me it looks kind of confusing, if anyone has a cleaner way(easier to understand) to implement this can you help me please?
def insertion_sort(arr)
(1...arr.length).each do |i| #iterate through array go through every element
j=i-1 #to check all elements behind i
while(j>=0&&arr[i]<arr[j]) #while not out bounds and current element is less than previous
temp=arr[i] #3 lines to switch arr[i] and arr[j]
arr[i]=arr[j]
arr[j]=temp
i=j #keep track of where i is
j-=1 #decrease j by 1 to check the previous element
end
end
return arr
end
This isn't necessary in ruby:
temp=arr[i] #3 lines to switch arr[i] and arr[j]
arr[i]=arr[j]
arr[j]=temp
because you can do multiple assignment like this:
a,b = 1,2
which is the same as:
a = 1
b = 2
which means you can switch the values of variables like this:
a,b = b,a
or in your case:
arr[i],arr[j] = arr[j],arr[i]
This probably has its own issues, but you can see a couple simplifications here to hopefully make the code more readable.
class Array
def swap(a, b)
self[a], self[b] = self[b], self[a]
end
end
def insertion_sort(arr)
(1...arr.size).each do |i|
i.downto(1).each do |j|
break if arr[j] >= arr[j - 1]
arr.swap(j, j - 1)
end
end
arr
end
Easy implementation of Insertion sort in ruby.
def insertion(arr)
for i in (1...(arr.size))
if arr[i-1] > arr[i]
i.downto(1) do |el|
if arr[el] < arr[el-1]
arr[el-1], arr[el] = arr[el], arr[el-1]
end
end
end
end
arr
end
arr = %w(3 7 4 9 5 2 6 1 0)
p insertion(arr)
I'm getting "true"
def is_prime(n)
if (2..(n**0.5)).each {|i| n % i != 0}
puts "true"
else
puts "false"
end
end
is_prime(14)
Cary Swoveland hit the main problem, but there are some other tweaks that might make it cleaner/more useful.
def is_prime?(n)
(2..(n**0.5)).all? {|i| n % i != 0}
end
p is_prime? 14 # false
p is_prime? 17 # true
Note the addition of the question mark in the method name. The method now returns a usable result instead of printing.
If you wanted to enhance performance you could test separately for evenness and then iterate over only the odd numbers 3 to sqrt(n), stepping by 2's to cut the amount of work in half:
def is_prime?(n)
if n.odd?
3.step(Math.sqrt(n).to_i, 2).all? {|i| n % i != 0}
else
false
end
end
The part I don't understand is how to make this yield so that the elements in the array have the calculation, (which is specified in the block), done to them if block_given?, prior to their being added together.
For example, the calculation could be |x| x+3 (to add 3 to each of the elements), but I want this to work for any sort of manipulation of the elements, such as |x| x**3 or |x| x*5, so that the elements inmy_ary ([1,2,3]) are changed as specified by the calculation.
So essentially I'm asking what I need to do to the part of my code that reads yield array.each{|x|} if block_given? . what I was trying to do here is say that each element in the array should have whatever is stated in the block done to the element, so that it is changed.
What I am passing to the this is something along the lines of my_ary.sum(2) {|x| x **4}.
class MyArray
attr_reader :ary
def init(ary)
#ary = ary
end
def sum(init_val = 0)
yield ary.each{|x|} if block_given?
(#ary.inject(0){|x,y|x+y}) + init_val
end
end
class MyArray
attr_reader :ary
def initialize(ary)
#ary = ary
end
def sum n, &block
new_ary = #ary.collect &block # ary after executing block
ary_sum = new_ary.inject(0){|sum, x| sum+=x} # sum all elements of the array
return ary_sum + n
end
end
def nsum n, &block, here & saves the block (code between {} or do; end) to instance of Proc. It's basically your block of code saved to variable.
#ary.collect &block here, collect want block not proc so & change proc to the block. collect execute block for each element, and return new array.
inject - yields element to the block, add it to sum, and it is returned as sum variable. On the next iteration (next yielding to the block) sum will be last value of previous iteration.
[1,2,3].inject(0){|s, x| s+=x}
# sum = 0; x = 1;
# sum = 1; x = 2
# sum = 3; x = 3
# sum = 6
# inject returns 6 because there is no elements in the array
I have a simple method that finds prime numbers, puts them in an array and then sums them up. What are some possible steps to speed it up?
def prime?(number, array)
array.each do |x|
if number % x == 0
return false
end
end
true
end
def sum_prime(number)
i = 0
prime = 1
output = [2]
while prime < number
if prime?(prime, output)
i += 1
output << prime if prime != 1
p prime
end
prime += 2
end
output.inject(:+)
end
sum_prime(200000)
is array#each ok? Can I concatinate differently for faster results?
This should work. It uses others' suggestions:
require 'prime'
def sum_prime(limit)
Prime.each(limit).inject(0) {|sum, num| sum + num}
end
puts sum_prime(200000)