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
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.
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.
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
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).
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?