From: sempsteen Date: 2006-11-25T22:20:34+09:00 Subject: Re: coding practise Thanks for your replies Gareth and Paul. I've improved return statement as you suggested Paul. this didn't worked: return self == t2 and self != t1 but this: return (self == t2 and self != t1) and this: self == t2 and self != t1 worked. I've also set the sums' initial values to 1 and start the loops from 2 which is more reasonable. Paul, i understood your code. Amicable numbers was just an example. I actually want to know where to use the method pairs like: has_key? [], has_friend?, friend has_sth?, give_that ... When we call "has_friend?" method it does the same job as "friend" method except that it returns true or false not the amicable number. When we call "Hash#has_key?" method it does the same job as "Hash#[]" method except that it returns true or false, not the value of the given Hash index. So if they both do the same job why do i need to search for an existing value and then call another method that gives the value like: hsh = {'id' => 10, 'lang' => 'Ruby'} puts hsh['id'] if hsh.has_key?('id') I can write it like this: puts hsh['id'] if hsh['id'] != nil I hope i could explain it. On 11/25/06, Paul Lutus wrote: > 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 > >