Here's the error statement:
EvoWithout.rb:53:in `block (2 levels) in ': undefined method `+' for nil:NilClass (NoMethodError)
Here's line 53:
if behavior[i,0] > Thrsh && s == 0 then animal[i,0]+= 5 end
Here's the relevant code:
situation= Matrix[ [1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0],
[1,0,0,0,0,1,1,1,1,1,1,0,0,0,0,1],
[1,0,0,1,0,1,1,0,0,1,1,0,1,0,0,1],
[1,1,1,1,0,0,0,0,0,0,0,0,1,1,1,1],
[1,0,0,1,1,0,1,0,1,0,1,0,1,0,0,1] ]
# Build brain with $Behavmax rows of 0,1's
brain = Matrix.build(10,16) { 1 }
for i in (0..$Behavmax)
for j in (0..$Stimmax)
if rand(4) < 1.1 then brain[i,j] = 0 end
end # j
end #i
stimulus=Matrix.column_vector([0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0])
behavior=Matrix.row_vector([0,0,0,0,0,0,0,0,0,0])
animal=Matrix.row_vector([20,20,20,20,20,20,20,20,20,20]) # to hold value of fitness
# BEGIN MAIN PROGRAM
# Noise=20
# Go through once presenting 1 situation after another
for s in (0..4)
for j in (0..$Stimmax)
stimulus[j,0] = situation[s,j]
end # for j
# GENERATE BEHAVIOR
behavior=brain*stimulus
for i in (0..$Behavmax) #fire iff stimulus pattern matches detector
if behavior[i,0] > Thrsh && s == 0 then animal[i,0]+= 5 end
#if behavior[i,0] > Thrsh && s != 0 then print "Behavior#{i}=#{behavior[i,0]} and s=#{s} " end
end # for i
puts
end # for s
An important skill to learn is to read error messages and warnings. In your title, you ask:
Why am I getting a “no method” error for a simple matrix add operation in Ruby?
But, that's not what the error message is saying!
You don't get a NoMethodError for a matrix add operation (Matrix#+). If you were, the error message would say something like:
EvoWithout.rb:53:in `block (2 levels) in ': undefined method `+' for animal:Matrix (NoMethodError)
Note that the error message would say (bold emphasis mine) "undefined method `+' for animal:Matrix" (which would be wrong, because Matrix#+ exists). However, that's not what your error message is saying. Your error message says (bold emphasis mine):
undefined method `+' for nil:NilClass
Which is correct, because NilClass does, in fact, not have a + method, and neither do its superclasses Object, Kernel, and BasicObject.
So, you are looking in the wrong place: your problem is not with the matrix add operation, your problem is that your matrix index operation returns nil.
And the reason for that is rather simple: you animal matrix contains only a single row, but you are iterating over $Behavmax + 1 rows. So, as soon as $Behavmax is greater than zero, you will index into the second row of animal, which doesn't exist. Therefore, it will return nil, and your addition will fail.
Remember that a ω= b for any operator ω and arbitrary expressions a and b is equivalent to a = a ω b with a only evaluated once, so
animal[i,0]+= 5
is roughly equivalent to:
__temp__ = animal[i, 0]
animal[i, 0] = __temp__ + 5
And if i is anything other than 0, __temp__ will be nil, because there is only one row in animal.
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.
The code below is giving me an ArgumentError and I can't figure out the problem.
The challenge comes from the Advent of Code, day 3.
require 'set'
x, y = 0
visited = Set.new
def move(dir)
case move
when ">"
x += 1
when "<"
x -= 1
when "^"
y += 1
when "v"
y -= 1
end
end
def visit(x,y)
unless visited.include?([x,y])
visited << [x,y]
end
end
a_file = File.open("day3a_directions.txt", "r")
a_file.each_line("\n") do |line|
line.each_char do |dir|
move(dir)
visit(x,y)
end
end
puts visited.length
This is the error I'm getting:
day3a.rb:6:in `move': wrong number of arguments (0 for 1) (ArgumentError)
from tmp.rb:7:in `move'
from tmp.rb:28:in `block (2 levels) in <main>'
from tmp.rb:27:in `each_char'
from tmp.rb:27:in `block in <main>'
from tmp.rb:26:in `each_line'
from tmp.rb:26:in `<main>'
You have a typo in your code in the definition of move, here:
def move(dir)
case move
when ">"
...
Should be:
def move(dir)
case dir
when ">"
...
Also, I might add that you're circumventing the whole point of Set by checking if an element exists before adding it. This is built into the class already.
I wrote a code for Simple Tree Matching for matching two DOM nodes. It is showing some error. I am not able to figure it out.
I am posting the code and the error trace.
def tree_match(node1,node2)
# ------- Implementation of Simple Tree matching algorithm.
if node1.name!=node2.name
puts 'in base case'
return 0
elsif node1.children.empty? or node2.children.empty?
return 0
else
dp = Array.new(node1.children.size) {Array.new(node2.children.size,0)}
i=1
j=0
j = j+1
node1.children.each do |child1|
node2.children.each do |child2|
Line 180th. main error is in the code segment below.
dp[i][j] = [dp[i-1][j],dp[i][j-1],(dp[i-1][j-1] + tree_match(child1,child2))].max
j = j + 1
end
i = i+1
end
return 1+dp[dp[0].size-1][dp[1].size-1]
end
end
ERROR:
in block (2 levels) in tree_match': undefined method[]' for nil:NilClass (NoMethodError)
from /usr/local/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:187:in block in each'
from /usr/local/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:186:inupto'
from /usr/local/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:186:in each'
from /<>/DomTreeParser.rb:179:inblock in tree_match'
from /usr/local/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:187:in block in each'
from /usr/local/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:186:inupto'
from /usr/local/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:186:in each'
from /<path>/DomTreeParser.rb:178:intree_match'
from /<>/DomTreeParser.rb:180:in block (2 levels) in tree_match'
from /usr/local/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:187:inblock in each'
from /usr/local/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:186:in upto'
from /usr/local/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:186:ineach'
from /<>/DomTreeParser.rb:179:in block in tree_match'
from /usr/local/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:187:inblock in each'
from /usr/local/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:186:in upto'
from /usr/local/lib/ruby/gems/2.0.0/gems/nokogiri-1.6.6.2/lib/nokogiri/xml/node_set.rb:186:ineach'
from /<>/DomTreeParser.rb:178:in tree_match'
from testDriver.rb:11:in'
EDIT: nil class error is on line 180. I have marked it.
You move past the boundaries of the array you created. Here
dp = Array.new(node1.children.size) {Array.new(node2.children.size,0)}
you initailize an array with node1.children.size, then iterate over each of them (node1.children) and try to assign
dp[i][j] = ... in each step.
Since you start with i, j = 1, 1, here's what happens on the last step of the loop:
dp[i] returns nil because i == node1.children.size and indexes are numerated starting from 0. That's why you get
undefined method[] for nil:NilClass
when you call dp[i][j]
Can't really suggest a best course here since I don't see the entire code, but initializing a bigger Array should do the trick. Oh, and be sure to check out each_with_index
I was helping a friend out with a ruby assignment, and I ran into some peculiar behavior. We've refactored it to use a Hash and increment the counts directly through that, so this code is obsolete, but for my own sanity, I need to know why nil values show up in the packets array. The strangest thing is that it doesn't always happen, it only happens on some executions.
I should note that the purpose of the code is essentially to tally the number of times in a row that the random value is below p.
count = 0
p = 0.1
packets = []
counts = []
10000.times do
if rand.round(1) <= p
count += 1
elsif count > 0
packets << count
count = 0
end
end
packets.each do |train|
counts[train] = counts.fetch(train, 0) + train
end
counts.each_with_index do |value, index|
puts "Train Length: #{index} Count: #{value}"
end
The packets array should only ever contain numerical values, but it winds up with multiple nil's. What could be causing this?
Are you certain that your packets array is getting nils? There's basically no way that could happen with the code you posted. Dump out the packets array to be sure.
However, I do observe that the code sometimes fails with the following error:
NoMethodError: undefined method `+' for nil:NilClass
from (irb):16:in `block in irb_binding'
from (irb):15:in `each'
from (irb):15
from /usr/bin/irb:12:in `<main>'
from the line
counts[train] = counts.fetch(train, 0) + train
This error means that counts.fetch(train, 0) was nil (if train was nil, you'd get a coercion error instead). This can happen if, for example, you set counts[3] before counts[2] is set, and later access counts[2] (because Ruby will fill the array elements you "skipped over" with nils).
If you are actually getting nils in packets, then you may have demons in your Ruby.