tags:

views:

440

answers:

3

How can I accomplish writing a program to generate all perfect numbers between 1 and 100. A perfect number is a positive integer that is equal to the sum of its proper divisors. For example, 6(=1+2+3) is a perfect number.

I am a beginner and am stuck on this. I just stared learning some prolog which seems very powerful but hard to catch right away. Please help.

Thanks Frank

+1  A: 

I'm not sure if this is what you were looking for, but you could always just print out "6, 28"...

Clueless
Your name is your program?
tharkun
........... ;-)
arno
Oh come on, I always use the preprocessor in my head to do my programming whenever I can. I rather like the elegance of this one. :)
Clueless
In TDD, this would be great. Dev1: You need to find all perfect numbers up to 100. Dev2: Codes return "6, 28, ..." Dev2: Better change the test to "Find all perfect numbers between numbers n and m"
ck
In spite of the "elegance" proposed here, at least there are not that many perfect numbers..at least that's what we may think considering that numbers just dont end :).
JonH
6, 28, 496, 8128, 33550336, 8589869056, 137438691328, 2305843008139952128 would cover all integers through 64 bits, and run in O(1) time. I think thats a pretty fair program :) http://www.research.att.com/~njas/sequences/A000396
Clueless
It's still not a program, its an output. I could cout the first 5000 prime numbers when asked for 1000 and still fail as it is not a solution to the problem. It is more of a problem then a solution.
JonH
A: 

Well looks like you need to loop up until n/2 that is 1/2 of n. Divide the number and if there is no remainder then you can include it in the total, once you have exhausted 1/2 of n then you check if your total added = the number you are testing.

For instance:

#include "stdafx.h"
#include "iostream"
#include "math.h"
using namespace std;

int main(void)
{
    int total=0;

    for(int i = 1; i<=100; i++)
    {
        for( int j=1; j<=i/2; j++)
        {
            if (!(i%j))
            {
                total+=j;
            }
        }
        if (i==total)
        {
            cout << i << " is perfect";
        }
        //it works
        total=0;
    }

    return 0;
}
JonH
By the way it could be optimized folks I know, but it does the job in readable code :)
JonH
BTW this was done in C++, you could do it in C#, VB.net or any other language just follow the logic behind it. First loop up until and including 100 because you stated you are looking for any perfect number up till 100. Then the second loop is used as a divisor and reaches up till i/2 that is 1/2 of your n. If there is no remainder !(i%j) that means it divides evenly and you can include it in your sum. Otherwise keep looping. Once you kick out of the loop, that is j=i/2 then you simply check if your accumulated total = your original n (i). If they are equal its a perfect number!
JonH
+3  A: 

So I suspect Frank is looking for an answer in Prolog, and yes it does smell rather homeworky...

For fun I decided to write up my answer. It took me about 50 lines.

So here is the outline of what my predicates look like. Maybe it will help get you thinking the Prolog way.

  is_divisor(+Num,+Factor)

  divisors(+Num,-Factors)
  divisors(+Num,+N,-Factors)

  sum(+List,-Total)
  sum(+List,+Sofar,-Total)

  is_perfect(+N)

  perfect(+N,-List)

The + and - are not really part of the parameter names. They are a documentation clue about what the author expects to be instantiated.(NB) "+Foo" means you expect Foo to have a value when the predicate is called. "-Foo" means you expect to Foo to be a variable when the predicate is called, and give it a value by the time it finishes. (kind of like input and output, if it helps to think that way)

Whenever you see a pair of predicates like sum/2 and sum/3, odds are the sum/2 one is like a wrapper to the sum/3 one which is doing something like an accumulator.

I didn't bother to make it print them out nicely. You can just query it directly in the Prolog command line:

?- perfect(100,L).
L = [28, 6] ;
fail.

Another thing that might be helpful, that I find with Prolog predicates, is that there are generally two kinds. One is one that simply checks if something is true. For this kind of predicate, you want everything else to fail. These don't tend to need to be recursive.

Others will want to go through a range (of numbers or a list) and always return a result, even if it is 0 or []. For these types of predicates you need to use recursion and think about your base case.

HTH.

NB: This is called "mode", and you can actually specify them and the compiler/interpreter will enforce them, but I personally just use them in documentation. Also tried to find a page with info about Prolog mode, but I can't find a good link. :(

pfctdayelise