From: Paul Lutus Date: 2006-11-26T19:10:08+09:00 Subject: Re: coding practise sempsteen wrote: > Yep, now i know that my Hash example is a different matter. > >> The fix: >> change 'has_answer' to store the answer (privately) after calculating it >> and 'answer' to simply retrieve that answer if it has been created. > > Where do you suggest to store the value for my amicable numbers example? Use my previously posted code as a starting point, the one that uses a precalculated hash of divisor sums. Create an instance of your class and accept a value for maximum number if the user offers one. Precalculate the sums of divisors as you initialize the class, up to this provided maximum number, or a default value. If the user provides an argument that is our of range of the precalculated values, just calculate additional values and add them to the existing hash, then return the result to the user. > > class Fixnum > def has_friend? > t1, t2 = 1, 1 > 2.upto(self / 2) {|i| t1 += i if self % i == 0} > 2.upto(t1 / 2) {|i| t2 += i if t1 % i == 0} > return self == t2 && self != t1 > end > def friend > t1, t2 = 1, 1 > 2.upto(self / 2) {|i| t1 += i if self % i == 0} > 2.upto(t1 / 2) {|i| t2 += i if t1 % i == 0} > return t1 if self == t2 && self != t1 > end > end > > 1.upto(1000) {|i| print i, "\t<->\t", i.friend, "\n" if i.has_friend?} Please abandon this code. It is extremely inefficient. > I want a "has_friend?" method and "friend" method. One for searching > for the existing of given number, other one is for getting the value > of the friend of that number. And i want those methods inside "Fixnum" > class structure, like as instance methods. No, you do not. You want to write a separate class for handling this specialized kind of problem, not part of Fixnum. And yo do not want to recalculate the entire divisor set over again for each entered argument. > when i call has_friend? method it will store its value to some kind of > variable, but return true or false and, when i call friend method it > will get the stored value. > But what must be that some kind of variable that holds the value? A hash table, as in my posted example. And you *do* *not* want to make this amicable detector capability part of Fixnum, any more than you would want to make a numerical integral solver part of Fixnum -- it's just not appropriate to be included in the class. --------------------------------------------- #!/usr/bin/ruby -w class Amicable def initialize(max = 1000) @max = 2 fill_hash(max) end def fill_hash(max) @hash ||= {} if(max > @max) 2.upto(max) do |i| sum = 1 2.upto(i/2) do |j| sum += j if (i % j) == 0 end @hash[i] = sum end @max = max end end def comp_amicable(n) fill_hash(n) q = @hash[n] return @hash[n] if n == @hash[q] && n != q return false end def has_friend?(n) return comp_amicable(n) != false end def friend(n) return comp_amicable(n) end end # test the class: max = 10000 amic = Amicable.new(max) 2.upto(max) do |i| j = amic.friend(i) puts "#{i} <-> #{j}" if j end --------------------------------------------- Output: 220 <-> 284 284 <-> 220 1184 <-> 1210 1210 <-> 1184 2620 <-> 2924 2924 <-> 2620 5020 <-> 5564 5564 <-> 5020 6232 <-> 6368 6368 <-> 6232 -- Paul Lutus http://www.arachnoid.com