Ruby parallel sorting - ruby

I am trying to create a multithreaded version of a sorting algorithm. I do not understand why this algorithm always returns just Array[1] instead of the full array.
class Array
def quick_sort
return self if self.length <= 1
pivot = self[0]
if block_given?
less, greater_equals = self[1..-1].partition { yield(x, pivot) }
else
less, greater_equals = self[1..-1].partition { |x| x < pivot }
end
l = []
g = []
Process.fork {l = less.quick_sort }
Process.fork {g = greater_equals.quick_sort}
Process.waitall
return l + [pivot] + g
end
end

The local variables l and g are not passed beyond Process.fork. They are only valid within that block. For example,
Process.fork{a = 2}
Process.wait
a #=> NameError: undefined local variable or method `a' for main:Object
In your code, the l and g assignments done before Process.fork are still valid when you call return l + [pivot] + g.
By the way, if you had intended l and g to be passed from Process.fork, then your initialization of these variables prior to Process.fork is meaningless.

From you examples it looks like you are trying to use Process where you actually want to use a thread.
Process: no shared resources with itś caller (Parent)
Thread: shares memory with its Parent
Your example would work if you replaced the Process.fork with Threads:
l = []
g = []
left_thread = Thread.new {l = less.quick_sort }
right_thread = Thread.new {g = greater_equals.quick_sort}
left_thread.join
right_thread.join
return l. + [pivot] + g

Related

How to implement Java's Comparable module in Ruby

I'm currently going over Robert Sedgewick's Algorithms book. In the book for the implementation of a Priority Queue there is the use of the Comparable module. While going over the top k frequent elements leetcode problem I noticed that there would be an error in my Ruby implementation.
def top_k_frequent(nums, k)
ans = []
h = Hash.new(0)
nums.each do |num|
h[num] += 1
end
heap = Heap.new
h.each do |k,v|
heap.insert({k => v})
end
k.times do
a = heap.del_max
ans.push(a.keys[0])
end
ans
end
class Heap
def initialize
#n = 0
#pq = []
end
def insert(v)
#pq[#n += 1] = v
swim(#n)
end
def swim(k)
while k > 1 && less((k / 2).floor, k)
swap((k / 2).floor, k)
k = k/2
end
end
def swap(i, j)
temp = #pq[i]
#pq[i] = #pq[j]
#pq[j] = temp
end
def less(i, j)
#pq[i].values[0] < #pq[j].values[0]
end
def del_max
max = #pq[1]
swap(1, #n)
#n -= 1
#pq[#n + 1] = nil
sink(1)
max
end
def sink(k)
while 2 * k <= #n
j = 2 * k
if !#pq[j + 1].nil?
j += 1 if j > 1 && #pq[j].values[0] < #pq[j + 1].values[0]
end
break if !less(k, j)
swap(k, j)
k = j
end
end
end
Above is the Java Priority Queue implementation.
Ruby's comparable operator is <=> which will return one of -1, 0, 1 and nil (nil mean could not compare).
In order to compare two objects , both need to implement a method def <=>(other). This is not on Object, so is not available on any objects that don't implement it or extend from a class that does implement it. Numbers and Strings, for example, do have an implementation. Hashes do not.
I think in your case, the issue is slightly different.
When you call queue.insert(my_hash) what you're expecting is for the algorithm to break up my_hash and build from that. Instead, the algorithm takes the hash as a single, atomic object and inserts that.
If you add something like:
class Tuple
attr_accessor :key, :value
def initialize(key, value)
#key = key
#value = value
end
def <=>(other)
return nil unless other.is_a?(Tuple)
value <=> other.value
end
end
then this will allow you to do something like:
hsh = { 1 => 3, 2 => 2, 3 => 1}
tuples = hsh.map { |k, v| Tuple.new(k, v) }
tuples.each { |tuple| my_heap.insert(tuple) }
you will have all of your data in the heap.
When you retrieve an item, it will be a tuple, so you can just call item.key and item.value to access the data.

How to implement a merge sort for a linked list in Ruby

I want to implement a merge sort for a single linked list in Ruby.
This code is running without any error but doesn't output as expected.
class Node
attr_accessor :data, :next
def initialize(value)
#data = value
#next = nil
end
end
Merge sort method:
def mergesort(head)
return head if !head || !head.next
a, b = frontbacksplit(head)
mergesort(a)
mergesort(b)
c = sortedmerge(a, b) #something is going wrong here
end
This method is used to divide the list into two sublists:
def frontbacksplit(head)
slow = head
fast = head.next
until fast.nil?
fast = fast.next
unless fast.nil?
slow = slow.next
fast = fast.next
end
end
a = head
b = slow.next
slow.next = nil
[a, b]
end
There may be a mistake in this method:
def sortedmerge(a, b)
result = nil
if a.nil?
return b
elsif b.nil?
return a
end
if a.data <= b.data
result = a
result.next = sortedmerge(a.next, b)
else
result = b
result.next = sortedmerge(a, b.next)
end
result
end
The problem is in the mergesort method. The original implemantation is defined as:
void MergeSort(Node** headRef)
{
...
MergeSort(&a);
MergeSort(&b);
*headRef = SortedMerge(a, b);
}
This means it is changing the the contents of a and b.
Since Ruby does not have such call by reference semantics, you simply forgot to assign the result back into a and b in the Ruby version to duplicate this behavior.
The fix:
def mergesort(head)
...
a = mergesort(a)
b = mergesort(b)
sortedmerge(a, b)
end

When and how to adopt a method into a class?

Below is some code I wrote to solve a problem for a course I'm taking. The solution that I have works just fine, however the question called for using a class implementation, meaning we are to adopt whatever solution we come up with into a class. In the first block below is the method that I wrote, and in the second block is the class implementation of the method, they both do pretty much the same thing. However, I am failing to see the benefit of the class adaptation. Also I don't particularly know how much is too much or too little for a single class method to do on it's own. Do I compartmentalize everything? Or do I keep operations that pertain to a certain thing packaged in a single method?
def cipher(coded_message)
input = coded_message.downcase.split("")
cipher = {}
alphabet_array = %w(a b c d e f g h i j k l m n o p q r s t u v w x y z)
alphabet_array.each_with_index {|e,i| cipher[e] = alphabet_array[i-4]}
(0..9).to_a.each{|e| cipher[e.to_s] = e}
%w[# # $ % ^ & *].each{|e| cipher[e] = " "}
%w[. , ! ? ; : -].each{|e| cipher[e] = e}
input.map! {|e| e = cipher[e]}
input = input.join("")
if input.match(/\d+/)
input.gsub!(/\d+/) { |num| num.to_i / 100 }
end
return input
end
class Cipher
def initialize(shift=4,exaggerate=100)
#shift = shift
#exaggerate = exaggerate
end
def create_cipher
#cipher = {}
#alphabet_array = ('a'..'z').to_a
#alphabet_array.each_with_index {|e,i| #cipher[e] = #alphabet_array[i - #shift]}
(0..9).to_a.each{|e| #cipher[e.to_s] = e}
%w[# # $ % ^ & *].each{|e| #cipher[e] = " "}
%w[. , ! ? ; : -].each{|e| #cipher[e] = e}
end
def decode(input=nil)
#input = input
create_cipher
#input = #input.downcase.split("")
#input.map! {|e| e = #cipher[e]}
#input = #input.join("")
if #input.match(/\d+/)
#input.gsub!(/\d+/) { |num| num.to_i / #exaggerate }
end
return #input
end
end
I would argue that the biggest benefit of moving that code from a method into a class is testability and maintainablity. It is easier to test in isolation and that new class will probably be stable for a long period of time.

Ruby Pascal's triangle generator with memoization

I am attempting to memoize my implementation of a Pascal's triangle generator, as a Ruby learning experiment. I have the following working code:
module PascalMemo
#cache = {}
def PascalMemo::get(r,c)
if #cache[[r,c]].nil? then
if c == 0 || c == r then
#cache[[r,c]] = 1
else
#cache[[r,c]] = PascalMemo::get(r - 1, c) + PascalMemo::get(r - 1, c - 1)
end
end
#cache[[r,c]]
end
end
def pascal_memo (r,c)
PascalMemo::get(r,c)
end
Can this be made more concise? Specifically, can I create a globally-scoped function with a local closure more simply than this?
def pascal_memo
cache = [[1]]
get = lambda { |r, c|
( cache[r] or cache[r] = [1] + [nil] * (r - 1) + [1] )[c] or
cache[r][c] = get.(r - 1, c) + get.(r - 1, c - 1)
}
end
p = pascal_memo
p.( 10, 7 ) #=> 120
Please note that the above construct does achieve memoization, it is not just a simple recursive method.
Can this be made more concise?
It seems pretty clear, IMO, and moduleing is usually a good instinct.
can I create a globally-scoped function with a local closure more simply than this?
Another option would be a recursive lambda:
memo = {}
pascal_memo = lambda do |r, c|
if memo[[r,c]].nil?
if c == 0 || c == r
memo[[r,c]] = 1
else
memo[[r,c]] = pascal_memo[r - 1, c] + pascal_memo[r - 1, c - 1]
end
end
memo[[r,c]]
end
pascal_memo[10, 2]
# => 45
I have found a way to accomplish what I want that is slightly more satisfactory, since it produces a function rather than a lambda:
class << self
cache = {}
define_method :pascal_memo do |r,c|
cache[[r,c]] or
(if c == 0 or c == r then cache[[r,c]] = 1 else nil end) or
cache[[r,c]] = pascal_memo(r-1,c) + pascal_memo(r-1,c-1)
end
end
This opens up the metaclass/singleton class for the main object, then uses define_method to add a new method that closes over the cache variable, which then falls out of scope for everything except the pascal_memo method.

more ruby way of doing project euler #2

I'm trying to learn Ruby, and am going through some of the Project Euler problems. I solved problem number two as such:
def fib(n)
return n if n < 2
vals = [0, 1]
n.times do
vals.push(vals[-1]+vals[-2])
end
return vals.last
end
i = 1
s = 0
while((v = fib(i)) < 4_000_000)
s+=v if v%2==0
i+=1
end
puts s
While that works, it seems not very ruby-ish—I couldn't come up with any good purely Ruby answer like I could with the first one ( puts (0..999).inject{ |sum, n| n%3==0||n%5==0 ? sum : sum+n }).
For a nice solution, why don't you create a Fibonacci number generator, like Prime or the Triangular example I gave here.
From this, you can use the nice Enumerable methods to handle the problem. You might want to wonder if there is any pattern to the even Fibonacci numbers too.
Edit your question to post your solution...
Note: there are more efficient ways than enumerating them, but they require more math, won't be as clear as this and would only shine if the 4 million was much higher.
As demas' has posted a solution, here's a cleaned up version:
class Fibo
class << self
include Enumerable
def each
return to_enum unless block_given?
a = 0; b = 1
loop do
a, b = b, a + b
yield a
end
end
end
end
puts Fibo.take_while { |i| i < 4000000 }.
select(&:even?).
inject(:+)
My version based on Marc-André Lafortune's answer:
class Some
#a = 1
#b = 2
class << self
include Enumerable
def each
1.upto(Float::INFINITY) do |i|
#a, #b = #b, #a + #b
yield #b
end
end
end
end
puts Some.take_while { |i| i < 4000000 }.select { |n| n%2 ==0 }
.inject(0) { |sum, item| sum + item } + 2
def fib
first, second, sum = 1,2,0
while second < 4000000
sum += second if second.even?
first, second = second, first + second
end
puts sum
end
You don't need return vals.last. You can just do vals.last, because Ruby will return the last expression (I think that's the correct term) by default.
fibs = [0,1]
begin
fibs.push(fibs[-1]+fibs[-2])
end while not fibs[-1]+fibs[-2]>4000000
puts fibs.inject{ |sum, n| n%2==0 ? sum+n : sum }
Here's what I got. I really don't see a need to wrap this in a class. You could in a larger program surely, but in a single small script I find that to just create additional instructions for the interpreter. You could select even, instead of rejecting odd but its pretty much the same thing.
fib = Enumerator.new do |y|
a = b = 1
loop do
y << a
a, b = b, a + b
end
end
puts fib.take_while{|i| i < 4000000}
.reject{|x| x.odd?}
.inject(:+)
That's my approach. I know it can be less lines of code, but maybe you can take something from it.
class Fib
def first
#p0 = 0
#p1 = 1
1
end
def next
r =
if #p1 == 1
2
else
#p0 + #p1
end
#p0 = #p1
#p1 = r
r
end
end
c = Fib.new
f = c.first
r = 0
while (f=c.next) < 4_000_000
r += f if f%2==0
end
puts r
I am new to Ruby, but here is the answer I came up with.
x=1
y=2
array = [1,2]
dar = []
begin
z = x + y
if z % 2 == 0
a = z
dar << a
end
x = y
y = z
array << z
end while z < 4000000
dar.inject {:+}
puts "#{dar.sum}"
def fib_nums(num)
array = [1, 2]
sum = 0
until array[-2] > num
array.push(array[-1] + array[-2])
end
array.each{|x| sum += x if x.even?}
sum
end

Resources