Ruby undefined method `-' for nil:NilClass (NoMethodError) - ruby

I am working on a project and have encounter an error which I am not familiar with. When I run my code, I received 'undefined method `-' for nil:NilClass (NoMethodError)' which after some research means that target_floors[j] is nil. Why is this happening and how to I solve it?
def retrieve_floor(n, target_floors)
smallestDifference = n
toReturn = 0
for i in 1..n
tempDiff = 0
for j in 0..target_floors.length
difference = target_floors[j] - i
if difference > 0
tempDiff += difference
else
tempDiff += difference.abs
end
end
if tempDiff < smallestDifference
smallestDifference = tempDiff
toReturn = i
end
end
return toReturn
end

Ranges of the form first..last include the endpoints, so you are iterating one beyond the end of the array.
You could instead use 0...target_floors.length (which includes the 0 but excludes the end) but a better and more rubyish approach would be to use each to iterate over the array, rather than working with indices.

Related

An integer I pass as an argument becomes a method

I am trying to write a function. Here is the code.
def get_sum(a,b)
if a == b do
return a
end
else
total = 0
for num in a...b
total += num
end
return total
end
end
I get this error:
undefined method `b' for main:Object (NoMethodError)
Can anyone tell me why I get this?
No do for ifs
if a == b
return a
end
Note that you can do the same thing so
def get_sum(a, b)
return a if a == b
(a...b).inject(:+)
end
It is because you have a block do ... end after b. Neither the keyword if nor the syntax sugar form ... == ... accepts a block. The only possibility left to interpret your code syntactically is to interpret b as a method that takes this do ... end block, and that is how it is parsed.

longest_palindrome, expected 0, got nil, where should if-else statement?

Taking on the CodeWar Challenge. Struggling to fix my code so that if the length of the string input is 0, it would show 0 instead of nil.
Code is below: (suggestions?)
def longest_palindrome(string)
i = 0
a = []
while !string[i..-1].empty?
j = -1
while !string[i..j].empty?
s = string[i..j]
if s.reverse == s
a << s.length
if s.length == nil
a.max = 0
end
end
j -= 1
end
i += 1
end
a.max
end
First, I'd like to point out a couple of issues with the code you posted.
The body of the innermost if statement is never executed because
0 != nil
This means that even if s.length evaluates to zero
s.length == nil
will still be false.
Another issue I'd like to point out is that
a.max = 0
will throw an error that looks like this:
undefined method max=' for []:Array (repl):17:inlongest_palindrome'
(repl):1:in `initialize'
You can't set the max value directly. The reason you never run into this error with the code you posted is because of the first issue I outlined above.
Now to answer your question. There are a lot of ways to do what you are asking. For example, you could just check whether the input string is empty
at the beginning of the code and immediately return 0 if it is therefore
never executing the while loops at all. Maybe with something like
return 0 if string.empty?
at the beginning of the code.
But from your question, I think what you are looking is something more like the following:
def longest_palindrome(string)
i = 0
a = []
while !string[i..-1].empty?
j = -1
while !string[i..j].empty?
s = string[i..j]
if s.reverse == s
a << s.length
end
j -= 1
end
i += 1
end
a.max.to_i
end
Of interest here is the second last line which makes sure a.max is converted
to an integer using the to_i method. Calling this method on nil converts it to 0.
Also, please note I have changed the code to fix the issues I had highlighted earlier.

while loop less than symbol '<' raising error in Ruby (RubyMine)

I am adding all numbers that are multiples of 3 and 5 less-than 1000.
This is my error:
in `multiple_sum': undefined method `<' for nil:NilClass (NoMethodError)
Here is my code:
def multiple_sum(n)
five_total, three_total, three_subtract = 0
while five_total < n
five_total += five_total+5
end
while three_total < n
if (three_total+3)%5 == 0
three_subtract += three_total+3
end
three_total += three_total+3
end
puts (three_total-three_subtract) + five_total
end
multiple_sum(1000)
Is there a problem with my while loop condition?
You're probably looking for chained assignment: five_total = three_total = three_subtract = 0.
Nope. You are just not setting a value for all the variables listed:
five_total, three_total, three_subtract = 0
That code assigns zero to the first variable, five_total only. three_total and three_subtract are set to nil.
You should set them too:
five_total, three_total, three_subtract = 0, 0, 0

ruby quicksort error

below is my quicksort implementation in ruby(using the first element as pivot). But there's an error I cannot figure out why
def quicksort(items)
return items if items.nil? or items.length <= 1
first=items[0]
left,right=parti(items,0,items.length)
quicksort(left) + [first] + quicksort(right)
end
def parti(s,l,r)
p=s[l]
i=l+1
(l+1..r).each do |x|
if s[x] < p
s[x],s[i] = s[i],s[x]
i+=1
end
end
s[l],s[i-1] = s[i-1],s[l]
return [s[0..i-2],s[i..r]]
end
The error:
putarray.rb:38:in `block in parti': undefined method `<' for nil:NilClass (NoM
hodError)
from inputarray.rb:37:in `each'
from inputarray.rb:37:in `parti'
from inputarray.rb:22:in `quicksort'
from inputarray.rb:47:in `<main>'
it says in
if s[x] < p
s[x] is NilClass.
UPDATE: It turns out
left,right=parti(items,0,items.length) should be
left,right=parti(items,0,items.length-1)
But after this change, an error
inputarray.rb:37: stack level too deep (SystemStackError)
point to
(l+1..r).each do |x|
Didn't find any good explanation on the internet.
Keep in mind that in Ruby, array index starts from 0, not 1.
Therefore items.length will return the value of 1 greater than the maximum index in the array.
Try right=parti(items,0,items.length-1) instead of right=parti(items,0,items.length).

Monte Carlo Simulation in Ruby

Hey I have a problem with my simulation.
I am a Ruby-Starter and don't know what's wrong in my code. That is only the part with the simulation:
def mean
mean = self.reduce(:+)/self.length.to_f
return mean
end
def randn
begin
rg1 = (rand*2)-1
rg2 = (rand*2)-1
q = rg1**2 + rg2**2
end while (q == 0 || q > 1)
p = Math.sqrt((-2*Math.log(q))/q)
rn1 = rg1 * p
rn2 = rg2 * p
return rn1, rn2
end
monte_carlo = 10
ren1_sim = Array.new
ren2_sim = Array.new
monte_carlo.times {
(1..20).each{ |i|
(1..250).each { |j|
r = randn()
ren1= * Math.exp(mu_ren1 + sigma_ren1 * r[0])
# ren1 is an array with prices, mu_ren1 and sigma_ren1 are individual values
ren2= * Math.exp(mu_ren2 + chol_21 * r[0] + chol_22 * r[1])
# chol_21 and chol_22 are also individual values
ren1_sim.push(ren1)
ren2_sim.push(ren2)
}
}
}
puts ren1_sim.mean
puts ren2_sim.mean
I don't get an error without the last two puts, but when I want to calculate the average of the arrays ren1_sim and rent_sim I get the error:
undefined method 'mean' for #<Array:0x2acf318> (NoMethodError)
Do you know how to fix that?
You're trying to invoke mean on an Array, which is not a method of Array. Perhaps you meant to use Statsample::Vector, which is Statsample's extension of Array, and does have mean?
ren1_sim = Statsample::Vector.new
ren2_sim = Statsample::Vector.new
You can also call to_vector on an Array instance to get a Statsample::Vector.
You've defined a mean method at the top of your file, but that just creates a method on the top level object, and you're trying to call it on an individual array. You could either change that code to
def mean(array)
array.reduce(:+)/array.length.to_f
end
and then change your usage of it later on to mean(ren1_sim)
or change your code so that you are adding the method to array, i.e.
class Array
def mean
self.reduce(:+)/self.length.to_f
end
end
have a look at this post to calculate the average of a array
How do I create an average from a Ruby array?

Resources