From: sempsteen Date: 2006-11-26T19:53:31+09:00 Subject: Re: coding practise Thanks Paul. I knew that my code was inefficient. That's the reason why i'm here. I thought, because i'm dealing with numbers i can define handling methods inside Fixnum (neglecting Bignum). Now i will write it again in a different class as your code by myself. On 11/26/06, Paul Lutus wrote: > 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 > >