From: Paul Lutus Date: 2006-11-25T20:00:09+09:00 Subject: Re: coding practise sempsteen wrote: > Hi all, > First of all sorry for my english. > I'm a Ruby newbie, trying to learn the language from the book, "The > Pragmatic Programmer's Guide". I loved the language very much. Now i > have some question marks about some issues. > If you help me understand this concept i'll be very happy. > > 1-) What does "Hash#has_key?" actually do? It returns true if provided with a key that is present in the hash. > Why do we need such a method in spite of using the result of "Hash#[]" > method which will return nil for a non-present key. The method has_key? is faster than using the key to find and return a value, which is what Hash#[] must do. > 2-) If we go ahead by the same manner is this a correct way of writing > a program that finds amicable numbers: > > class Fixnum > def has_friend? > t1, t2 = 0, 0 > 1.upto(self / 2) {|i| t1 += i if self % i == 0} > 1.upto(t1 / 2) {|i| t2 += i if t1 % i == 0} For this section: > if self == t2 and self != t1 > return true > else > return false Use this: return self == t2 and self != t1 This produces the same result. Also, in each of your loops you are testing whether a particular number can be divided by one with no remainder. The answer is always yes, so for each calculated value skip this test (start with 2 not 1) and set the initial value equal to 1. An article about amicable numbers, with some facts that may improve your method of calculating them: http://en.wikipedia.org/wiki/Amicable_number About the general topic, it is more efficient to compile an array of divisor sums and compare in that fashion than to test each number separately as you are doing. Like this: ----------------------------------------------- #!/usr/bin/ruby -w hash = {} max = 10000 2.upto(max) do |i| sum = 1 2.upto(i/2) do |j| sum += j if (i % j) == 0 end hash[i] = sum end hash.keys.sort.each do |i| a = hash[i] b = hash[a] puts "#{a} <-> #{b}" if a != b && b == i end ----------------------------------------------- Output: 284 <-> 220 220 <-> 284 1210 <-> 1184 1184 <-> 1210 2924 <-> 2620 2620 <-> 2924 5564 <-> 5020 5020 <-> 5564 6368 <-> 6232 6232 <-> 6368 -- Paul Lutus http://www.arachnoid.com