I'm just playing with some pure Ruby to gain better understanding and trying to find the primes of a number, without just using the Prime gem, which I'm aware of but I wrote this all for understanding, not to solve a problem per se.
I've written the following code:
class LargestPrimeFactor
# goal: find largest prime factor of 10 to start
attr_accessor :factors_list, :prime_factors, :idx, :below_n, :half_num
def initialize(below_n)
@below_n = below_n
@half_num = (below_n/2).floor
@idx = 2
@factors_list = []
@prime_factors = []
end
def prime_checker
sorted_list = factors_list.sort
sorted_list_length = sorted_list.length
puts "Sorted list of factors so far: #{sorted_list}"
sorted_list.combination(2) do |el, others|
if !prime_factors.include?(el) && others % el == 0
prime_factors << el
end
end
puts "Prime checker returned: #{prime_factors}"
end
def factors
congruent = (below_n % idx == 0)
not_listed = !factors_list.include?(idx)
number_candidate = idx
factors_list_length = factors_list.length
if congruent && not_listed && number_candidate
factors_list << number_candidate
puts "#{idx}"
puts "#{below_n}"
puts "why nil? #{below_n.divmod(idx)[0]}"
tmp = below_n.divmod(idx)[0]
idx = tmp #return number of times it divides in
puts "idx now: #{idx}"
elsif factors_list_length > 0 && factors_list[-1] - idx < 0
primes = prime_checker
puts "Prime factors: #{primes}"
puts "COMPLETE"
else
idx = 1
end
end
def find_primes
(1..half_num).each do |el|
factors
end
end
end
p = LargestPrimeFactor.new(below_n=10)
p.find_primes
But, when I run ruby largest_prime_factor.rb
I get the following output error:
2
10
why nil? 5
idx now: 5
Traceback (most recent call last):
5: from largest_prime_factor.rb:65:in `<main>'
4: from largest_prime_factor.rb:56:in `find_primes'
3: from largest_prime_factor.rb:56:in `each'
2: from largest_prime_factor.rb:57:in `block in find_primes'
1: from largest_prime_factor.rb:46:in `factors'
largest_prime_factor.rb:46:in `-': nil can't be coerced into Integer (TypeError)
I'm confused in that I thought the idx
would be set to 5
at line 46 at that point, but I'm interpreting this as it being nil
somehow. What am I missing about how this variable is being accessed and set within this method?
Thanks!
CodePudding user response:
Silvio Mayolo doesn't explain error
Problem with changing instance variable -- is just one of the problem. But reason is another
For example this code:
class Foo
attr_accessor :bar
def initialize
@bar = 0
end
def baz
p x
10.times do
if bar < 6
@bar = 1
end
end
end
end
Foo.new.baz
will raise
undefined local variable or method `x'
but this code:
class Foo
attr_accessor :bar
def initialize
@bar = 0
end
def baz
10.times do
if bar < 6
x = 1
@bar = 1
else
p x
end
end
end
end
Foo.new.baz
will print
nil
nil
nil
nil
So factors_list[-1] - idx < 0
in your code raises error. Local variable idx
is is declared, but not initialized, because those if
branch is not executed
I am very surprised why your question is downvoted. The feeling that readers have not figured out the question, as well as Silvio Mayolo
CodePudding user response:
You've declared a reader but not a writer for @idx
, so while idx
works and returns the instance variable @idx
, you can't write to it.
Either write to the instance variable directly (@idx = 5
), or make a writer (attr_accessor :idx
) and write to self.idx
(self.idx = 5
). Note that, in the latter case, an explicit self
is required so that, again, you don't accidentally make a new local variable with the same name.
Your idx = 1
line will also need to be updated similarly, and any other place where you try to write to an accessor.