I'm trying to write quicksort in Ruby, but I get an error that says:
qsort.rb:43:in `<': comparison of Fixnum with nil failed (ArgumentError)
from qsort.rb:43:in `block in dist'
from qsort.rb:42:in `each'
from qsort.rb:42:in `dist'
from qsort.rb:32:in `sort'
from qsort.rb:34:in `sort'
from qsort.rb:53:in `<main>'
This is my code:
#!usr/bin/ruby
class QArray
#data = []
#pvalue
#less
#more
def initialize(arr = [])
#data = arr
#pvalue = #data[0] unless #data.empty?
end
#these methods are so I can treat a QArray like a regular array
def push(value)
#data.push value
end
def empty?
#data.empty?
end
def single?
return #data.size == 1
end
def print
puts #data
end
def sort
puts "starting the sort with an array of #{#data}"
dist unless #data.empty?
#less.sort unless #less.empty? || #less.single?
#more.sort unless #more.empty? || #more.single?
#data = #less + #more #combine the two arrays again
end
def dist
#distributes values into subarrays
#less = QArray.new
#more = QArray.new
#data.each {|e|
if (e < #pvalue)
#less.push e
else #includes both equals and greater than
#more.push e
end
}
end
end
arr = QArray.new ([1,5,6,7,9,23,43,2,4,6])
arr.sort
arr.print
I'm guessing that this is related to e being nil in the block. However, this shouldn't happen, because I check whether the array is empty before I call dist.
Why do I get this error, and what can I do to fix it?
You create new QArrays in dist.
You initialize #pvalue on QArray creation, but they're empty when created in dist.
In dist you then try to use #pvalue, which is nil, because you create the array empty and only then add values to it, never updating the uninitialized #pvalue value.
Unrelated, but what are those class instance variables at the top of QArray for?!
Related
I am trying to implement a merge sort algorithm. I have the following code:
def merge_sort(array)
if array.length < 2
return array
else
length = array.length
i = array[0..array.length/2-1]
j = array[array.length/2 .. -1]
first = merge_sort(i)
second = merge_sort(j)
sorted_array = []
until first.empty? || second.empty? do
if first[0] >= second[0]
sorted_array << second.shift
else
sorted_array << first.shift
end
end
end
end
I get a NoMethodError for NilClass with it.
From my understanding, the unless block should check for empty array, and stop execution before a Nil class ever occurs.
Why do I get this error?
If array.length < 2 then your merge_sort will return array. Otherwise, merge_sort will return whatever until some_condition do ... end evaluates to. It so happens that until evaluates to nil so your method behaves like this:
def merge_sort(array)
if array.length < 2
return array
else
# Do a bunch of stuff...
return nil
end
end
That means that first and second will be nil most of the time and there's your NoMethodError. Perhaps you want to return sorted_array after your until:
def merge_sort(array)
if array.length < 2
array
else
#...
sorted_array = []
until first.empty? || second.empty? do
#...
end
sorted_array # <------------------- sort of important
end
end
I created a sample ruby program to swap elements in an array
class Swap
def swp(a,b)
self[a],self[b] = self[b],self[a]
self
end
array = [1,2,3]
array.swp(1,2)
puts array
end
I am getting the following error
NoMethodError: private method `swp' called for [1, 2, 3]:Array
from (irb):77:in `<class:Swap>'
from (irb):71
from /home/rahulv/.rvm/gems/ruby-2.0.0-p481/gems/railties-3.2.16/lib/rails/commands/console.rb:47:in `start'
from /home/rahulv/.rvm/gems/ruby-2.0.0-p481/gems/railties-3.2.16/lib/rails/commands/console.rb:8:in `start'
from /home/rahulv/.rvm/gems/ruby-2.0.0-p481/gems/railties-3.2.16/lib/rails/commands.rb:41:in `<top (required)>'
from script/rails:6:in `require'
from script/rails:6:in `<main>'
Please help to fix it.
UPDATE
I tried the same program with dynamic array input like this:
class Swap
def swp(a,b)
self[a],self[b] = self[b],self[a]
self
end
end
puts "enter the array elements "
input = gets.chomp
ary = []
while input != 'fin'
ary << input.to_i
input = gets.chomp
end
puts ary
puts "enter the elements to be swapped"
a=gets
b=gets
s=Swap.new
ary = ary.s.swp(a,b)
puts ary
Now the output error is like this:
enter the array elements
1
2
3
4
5
fin
enter the positions to be swapped
1
2
NoMethodError: private method `s' called for [0, 1, 2, 3, 4, 5]:Array
from (irb):17:in `<class:Swap>'
from (irb):1
from /home/rahulv/.rvm/gems/ruby-2.0.0-p481/gems/railties-3.2.16/lib/rails/commands/console.rb:47:in `start'
array.class = Array, you should add swp method for Array class.
class Array
def swp(a,b)
self[a],self[b] = self[b],self[a]
self
end
end
array = [1,2,3]
array.swp(0,1) #The array index start from 0, not 1
puts array.inspect
=> [2, 1, 3]
Update:
class Array
def swp(a,b)
self[a],self[b] = self[b],self[a]
self
end
end
puts "enter the array elements "
ary = []
input = 0
while 1
input = gets.chomp
if input != 'fin'
ary << input.to_i
else
break
end
end
puts "enter the positions to be swapped"
a=gets.to_i
b=gets.to_i
ary.swp(a,b)
puts ary.inspect
I don't like editing classes like that, for example if there's another class in the ancestor tree that implements the actual swp method (for any reason) and you implemented yours, and you try to use the actual documented one, you'll find unexplained behaviour, and it might be uneasy to figure out why it's behaving like that, beacuse your method is hiding, it's more maintainable if you add your methods to the ancestry tree using a module and then including it to the class.
module Swappable
def swp(a, b)
# method goes here
end
end
Then in another file you would do
class Array
include Swappable
end
This way when you call Array.ancestors you'd see your module
Array.ancestors
=> [Array, Swappable, ....]
And when you try something like
Array.instance_method(:swp).owner
you'll get Swappable, while an open class editing would return Array
This is just my oppinion on this matter, you can pick whatever works for you.
You can try the following code blog for take input an array and swap with two positions.
Here I initialize Swap class with an input array and then pass two swap position.
Main Class
class Swap
def initialize(array)
#array = array#[1,2,3,4,5]
end
def swp(a,b)
#array[a],#array[b] = #array[b],#array[a]
#array
end
end
Take Input for array
puts "ArrayInput :: Enter numbers separated by spaces, press 'Enter' to finish:"
array = gets
array = array.split(" ")
Take Input for swap positions
puts "SwapInput:: For FirstPosition, press 'Enter' to finish:"
first_position = gets.to_i
puts "SwapInput:: For SecondPosition, press 'Enter' to finish:"
second_position = gets.to_i
Initialize Swap Class
swap = Swap.new(array)
array = swap.swp(first_position, second_position)
puts "Array after swap:"
puts array
I have the following implementation of a linked list in Ruby:
class Node
attr_accessor :data, :next
def initialize(data = nil)
#data = data
#next = nil
end
end
class LinkedList
def initialize(items)
#head = Node.new(items.shift)
items.inject(#head) { |last, data| #tail = last.next = Node.new(data) }
end
def iterate
return nil if #head.nil?
entry = #head
until entry.nil?
yield entry
entry = entry.next
end
end
def equal?(other_list)
#How do I check if all the data for all the elements in one list are the same in the other one?
end
end
I have tried using the .iterate like this:
def equals?(other_list)
other_list.iterate do |ol|
self.iterate do |sl|
if ol.data != sl.data
return false
end
end
end
return true
end
But this is doing a nested approach. I fail to see how to do it.
You can't do it easily with the methods you have defined currently, as there is no way to access a single next element. Also, it would be extremely useful if you implemented each instead of iterate, which then gives you the whole power of the Enumerable mixin.
class LinkedList
include Enumerable # THIS allows you to use `zip` :)
class Node # THIS because you didn't give us your Node
attr_accessor :next, :value
def initialize(value)
#value = value
#next = nil
end
end
def initialize(items)
#head = Node.new(items.shift)
items.inject(#head) { |last, data| #tail = last.next = Node.new(data) }
end
def each
return enum_for(__method__) unless block_given? # THIS allows block or blockless calls
return if #head.nil?
entry = #head
until entry.nil?
yield entry.value # THIS yields node values instead of nodes
entry = entry.next
end
end
def ==(other_list)
# and finally THIS - get pairs from self and other, and make sure all are equal
zip(other_list).all? { |a, b| a == b }
end
end
a = LinkedList.new([1, 2, 3])
b = LinkedList.new([1, 2, 3])
c = LinkedList.new([1, 2])
puts a == b # => true
puts a == c # => false
EDIT: I missed this on the first run through: equal? is supposed to be referential identity, i.e. two variables are equal? if they contain the reference to the same object. You should not redefine that method, even though it is possible. Rather, == is the general common-language meaning of "equal" as in "having the same value", so I changed it to that.
I think there is something wrong with your initialize method in LinkedList, regardless could this be what you need
...
def equal?(other_list)
other_index = 0
cur_index = 0
hash = Hash.new
other_list.iterate do |ol|
hash[ol.data.data] = other_index
other_index += 1
end
self.iterate do |node|
return false if hash[node.data.data] != cur_index
return false if !hash.has_key?(node.data.data)
cur_index += 1
end
return true
end
...
Assuming this is how you use your code
a = Node.new(1)
b = Node.new(2)
c = Node.new(3)
listA = [a,b,c]
aa = Node.new(1)
bb = Node.new(2)
cc = Node.new(3)
listB = [aa,bb,cc]
linkA = LinkedList.new(listA)
linkB = LinkedList.new(listB)
puts linkA.equal?(linkB)
Don't understand why #nums.pop won't work in the value method. It seems to tell me that it can't do that for nil, but if I just say #nums, it shows that there is indeed something in the array. So then why can't I pop it out?
class RPNCalculator
def initialize
#value = value
nums ||= []
#nums = nums
end
def push(num)
#nums << num
end
def plus
if #nums[-2] == nil || #nums[-1] == nil
raise "calculator is empty"
else
#value = #nums.pop + #nums.pop
#nums.push(#value)
end
end
def minus
if #nums[-2] == nil || #nums[-1] == nil
raise "calculator is empty"
else
#value = #nums[-2] - #nums[-1]
#nums.pop(2)
#nums.push(#value)
end
end
def divide
if #nums[-2] == nil || #nums[-1] == nil
raise "calculator is empty"
else
#value = #nums[-2].to_f / #nums[-1].to_f
#nums.pop(2)
#nums.push(#value)
end
end
def times
if #nums[-2] == nil || #nums[-1] == nil
raise "calculator is empty"
else
#value = #nums.pop.to_f * #nums.pop.to_f
#nums.push(#value)
end
end
def value
#nums #Don't understand why #nums.pop won't work here
end
def tokens(str)
str.split(" ").map { |char| (char.match(/\d/) ? char.to_i : char.to_sym)}
end
def evaluate(str)
tokens(str).each do |x|
if x == ":-"
minus
elsif x == ":+"
plus
elsif x == ":/"
divide
elsif x ==":*"
times
else
push(x)
end
end
value
end
end
Error relates to the following part of a spec:
it "adds two numbers" do
calculator.push(2)
calculator.push(3)
calculator.plus
calculator.value.should == 5
end
Error says either:
Failure/Error: calculator.value.should == 5
expected: 5
got: [5] <using ==>
OR if .pop is used
Failure/Error: #calculator = RPNCalculator.new
NoMethodError:
undefined method 'pop' for nil:NilClass
Your initialize method assigning #value = value calls the function at def value which returns #nums which has not yet been created in initialize since #nums is created afterwards with nums ||= []; #nums = nums therefore it's nil. This is why .pop won't work.
You've created #nums as an array with nums ||= [] and you're using it with push and pop so why are you checking for the value with value.should == 5 (Integer) when calling value returns an (Array). You would need to write it like value.first.should == 5 or value[0].should == 5 ... otherwise you should change value to return just the element you want
def value
#nums.pop # or #nums[0], or #nums.first or #nums.last however you plan on using it
end
The problem is #value = value in your initialize method. Fix that then you can add the .pop in value.
EDIT
Also your evaluation is calling methods before you've populated #nums with the values. Then the methods "raise" errors. You can't call minus after only one value has been pushed to #nums.
Here's how I would do the flow for splitting the string
# Multiplication and Division need to happen before addition and subtraction
mylist = "1+3*7".split(/([+|-])/)
=> ["1", "+", "3*7"]
# Compute multiplication and division
mylist = mylist.map {|x| !!(x =~ /[*|\/]/) ? eval(x) : x }
=> ["1", "+", 21]
# Do the rest of the addition
eval mylist.join
=> 22
I realize this isn't exactly how you're going about solving this... but I think splitting by order of mathematical sequence will be the right way to go. So first evaluate everything between (), then only multiplication and division, then all addition and subtraction.
EDIT I just looked into what a RPN Calculator is. So don't mind my splitting recommendation as it doesn't apply.
I need to populate a Hash with various values. Some of values are accessed often enough and another ones really seldom.
The issue is, I'm using some computation to get values and populating the Hash becomes really slow with multiple keys.
Using some sort of cache is not a option in my case.
I wonder how to make the Hash compute the value only when the key is firstly accessed and not when it is added?
This way, seldom used values wont slow down the filling process.
I'm looking for something that is "kinda async" or lazy access.
There are many different ways to approach this. I recommend using an instance of a class that you define instead of a Hash. For example, instead of...
# Example of slow code using regular Hash.
h = Hash.new
h[:foo] = some_long_computation
h[:bar] = another_long_computation
# Access value.
puts h[:foo]
... make your own class and define methods, like this...
class Config
def foo
some_long_computation
end
def bar
another_long_computation
end
end
config = Config.new
puts config.foo
If you want a simple way to cache the long computations or it absolutely must be a Hash, not your own class, you can now wrap the Config instance with a Hash.
config = Config.new
h = Hash.new {|h,k| h[k] = config.send(k) }
# Access foo.
puts h[:foo]
puts h[:foo] # Not computed again. Cached from previous access.
One issue with the above example is that h.keys will not include :bar because you haven't accessed it yet. So you couldn't, for example, iterate over all the keys or entries in h because they don't exist until they're actually accessed. Another potential issue is that your keys need to be valid Ruby identifiers, so arbitrary String keys with spaces won't work when defining them on Config.
If this matters to you, there are different ways to handle it. One way you can do it is to populate your hash with thunks and force the thunks when accessed.
class HashWithThunkValues < Hash
def [](key)
val = super
if val.respond_to?(:call)
# Force the thunk to get actual value.
val = val.call
# Cache the actual value so we never run long computation again.
self[key] = val
end
val
end
end
h = HashWithThunkValues.new
# Populate hash.
h[:foo] = ->{ some_long_computation }
h[:bar] = ->{ another_long_computation }
h["invalid Ruby name"] = ->{ a_third_computation } # Some key that's an invalid ruby identifier.
# Access hash.
puts h[:foo]
puts h[:foo] # Not computed again. Cached from previous access.
puts h.keys #=> [:foo, :bar, "invalid Ruby name"]
One caveat with this last example is that it won't work if your values are callable because it can't tell the difference between a thunk that needs to be forced and a value.
Again, there are ways to handle this. One way to do it would be to store a flag that marks whether a value has been evaluated. But this would require extra memory for every entry. A better way would be to define a new class to mark that a Hash value is an unevaluated thunk.
class Unevaluated < Proc
end
class HashWithThunkValues < Hash
def [](key)
val = super
# Only call if it's unevaluated.
if val.is_a?(Unevaluated)
# Force the thunk to get actual value.
val = val.call
# Cache the actual value so we never run long computation again.
self[key] = val
end
val
end
end
# Now you must populate like so.
h = HashWithThunkValues.new
h[:foo] = Unevaluated.new { some_long_computation }
h[:bar] = Unevaluated.new { another_long_computation }
h["invalid Ruby name"] = Unevaluated.new { a_third_computation } # Some key that's an invalid ruby identifier.
h[:some_proc] = Unevaluated.new { Proc.new {|x| x + 2 } }
The downside of this is that now you have to remember to use Unevaluted.new when populating your Hash. If you want all values to be lazy, you could override []= also. I don't think it would actually save much typing because you'd still need to use Proc.new, proc, lambda, or ->{} to create the block in the first place. But it might be worthwhile. If you did, it might look something like this.
class HashWithThunkValues < Hash
def []=(key, val)
super(key, val.respond_to?(:call) ? Unevaluated.new(&val) : val)
end
end
So here is the full code.
class HashWithThunkValues < Hash
# This can be scoped inside now since it's not used publicly.
class Unevaluated < Proc
end
def [](key)
val = super
# Only call if it's unevaluated.
if val.is_a?(Unevaluated)
# Force the thunk to get actual value.
val = val.call
# Cache the actual value so we never run long computation again.
self[key] = val
end
val
end
def []=(key, val)
super(key, val.respond_to?(:call) ? Unevaluated.new(&val) : val)
end
end
h = HashWithThunkValues.new
# Populate.
h[:foo] = ->{ some_long_computation }
h[:bar] = ->{ another_long_computation }
h["invalid Ruby name"] = ->{ a_third_computation } # Some key that's an invalid ruby identifier.
h[:some_proc] = ->{ Proc.new {|x| x + 2 } }
You can define your own indexer with something like this:
class MyHash
def initialize
#cache = {}
end
def [](key)
#cache[key] || (#cache[key] = compute(key))
end
def []=(key, value)
#cache[key] = value
end
def compute(key)
#cache[key] = 1
end
end
and use it as follows:
1.9.3p286 :014 > hash = MyHash.new
=> #<MyHash:0x007fa0dd03a158 #cache={}>
1.9.3p286 :019 > hash["test"]
=> 1
1.9.3p286 :020 > hash
=> #<MyHash:0x007fa0dd03a158 #cache={"test"=>1}>
you can use this:
class LazyHash < Hash
def [] key
(_ = (#self||{})[key]) ?
((self[key] = _.is_a?(Proc) ? _.call : _); #self.delete(key)) :
super
end
def lazy_update key, &proc
(#self ||= {})[key] = proc
self[key] = proc
end
end
Your lazy hash will behave exactly as a normal Hash, cause it is actually a real Hash.
See live demo here
*** UPDATE - answering to nested procs question ***
Yes, it would work, but it is cumbersome.
See updated answer.
Use lazy_update instead of []= to add "lazy" values to your hash.
This isn't strictly an answer to the body of your question, but Enumerable::Lazy will definitely be a part of Ruby 2.0. This will let you do lazy evaluation on iterator compositions:
lazy = [1, 2, 3].lazy.select(&:odd?)
# => #<Enumerable::Lazy: #<Enumerator::Generator:0x007fdf0b864c40>:each>
lazy.to_a
# => [40, 50]