Perfect numbers

From Rosetta Code
Revision as of 17:51, 15 April 2011 by rosettacode>Balrog (→‎{{header|Go}}: incorrect)
Task
Perfect numbers
You are encouraged to solve this task according to the task description, using any language you may know.

Write a function which says whether a number is perfect.

A perfect number is a positive integer that is the sum of its proper positive divisors excluding the number itself. Equivalently, a perfect number is a number that is half the sum of all of its positive divisors (including itself).

Note: The faster Lucas-Lehmer test is used to find primes of the form 2n-1, all known perfect numbers can be derived from these primes using the formula (2n - 1) × 2n - 1. It is not known if there are any odd perfect numbers.

See also

Ada

<lang ada>function Is_Perfect(N : Positive) return Boolean is

  Sum : Natural := 0;

begin

  for I in 1..N - 1 loop
     if N mod I = 0 then
        Sum := Sum + I;
     end if;
  end loop;
  return Sum = N;

end Is_Perfect;</lang>

ALGOL 68

Works with: ALGOL 68 version Revision 1 - no extensions to language used
Works with: ALGOL 68G version Any - tested with release 1.18.0-9h.tiny
Works with: ELLA ALGOL 68 version Any (with appropriate job cards) - tested with release 1.8-8d

<lang algol68>PROC is perfect = (INT candidate)BOOL: (

 INT sum :=1;
 FOR f1 FROM 2 TO ENTIER ( sqrt(candidate)*(1+2*small real) ) WHILE
   IF candidate MOD f1 = 0 THEN
     sum +:= f1;
     INT f2 = candidate OVER f1;
     IF f2 > f1 THEN
       sum +:= f2
     FI
   FI;
  1. WHILE # sum <= candidate DO
   SKIP 
 OD;
 sum=candidate

);

test:(

 FOR i FROM 2 TO 33550336 DO
   IF is perfect(i) THEN print((i, new line)) FI
 OD

)</lang> Output:

         +6
        +28
       +496
      +8128
  +33550336

AutoHotkey

This will find the first 8 perfect numbers. <lang autohotkey>Loop, 30 {

 If isMersennePrime(A_Index + 1)
   res .= "Perfect number: " perfectNum(A_Index + 1) "`n"

}

MsgBox % res

perfectNum(N) {

 Return 2**(N - 1) * (2**N - 1)

}

isMersennePrime(N) {

 If (isPrime(N)) && (isPrime(2**N - 1))
   Return true

}

isPrime(N) {

 Loop, % Floor(Sqrt(N))
   If (A_Index > 1 && !Mod(N, A_Index))
     Return false
 Return true

}</lang>

AWK

<lang awk>$ awk 'func perf(n){s=0;for(i=1;i<n;i++)if(n%i==0)s+=i;return(s==n)} BEGIN{for(i=1;i<10000;i++)if(perf(i))print i}' 6 28 496 8128</lang>

BASIC

Works with: QuickBasic version 4.5

<lang qbasic>FUNCTION perf(n) sum = 0 for i = 1 to n - 1 IF n MOD i = 0 THEN sum = sum + i END IF NEXT i IF sum = n THEN perf = 1 ELSE perf = 0 END IF END FUNCTION</lang>

C

Translation of: D

<lang c>#include "stdio.h"

  1. include "math.h"

int perfect(int n) {

   int max = (int)sqrt((double)n) + 1;
   int tot = 1;
   int i;
   for (i = 2; i < max; i++)
       if ( (n % i) == 0 ) {
           tot += i;
           int q = n / i;
           if (q > i)
               tot += q;
       }
   return tot == n;

}

int main() {

   int n;
   for (n = 2; n < 33550337; n++)
       if (perfect(n))
           printf("%d\n", n);
   return 0;

}</lang>

C#

Translation of: C++

<lang csharp> static void Main(string[] args) { Console.WriteLine("Perfect numbers from 1 to 33550337:");

for (int x = 0; x < 33550337; x++) { if (IsPerfect(x)) Console.WriteLine(x + " is perfect."); }

Console.ReadLine(); }

static bool IsPerfect(int num) { int sum = 0; for (int i = 1; i < num; i++) { if (num % i == 0) sum += i; }

return sum == num ; } </lang>

Version using Lambdas, will only work from version 3 of C# on

<lang csharp> static void Main(string[] args) { Console.WriteLine("Perfect numbers from 1 to 33550337:");

for (int x = 0; x < 33550337; x++) { if (IsPerfect(x)) Console.WriteLine(x + " is perfect."); }

Console.ReadLine(); }

static bool IsPerfect(int num) { return Enumerable.Range(1, num - 1).Sum(n => num % n == 0 ? n : 0 ) == num; } </lang>

C++

Works with: gcc

<lang cpp>#include <iostream> using namespace std ;

bool is_perfect( int ) ;

int main( ) {

  cout << "Perfect numbers from 1 to 33550337:\n" ;
  for ( int num = 1 ; num < 33550337 ; num++ ) { 
     if ( is_perfect( num ) ) 
        cout << num << '\n' ;
  }   
  return 0 ; 

}

bool is_perfect( int number ) {

  int sum = 0 ; 
  for ( int i = 1 ; i < number ; i++ ) 
     if ( number % i == 0 ) 
        sum += i ; 
  return sum == number ; 

}</lang>

Clojure

<lang lisp>(defn proper-divisors [n]

 (if (< n 4)
   '(1)
   (cons 1 (filter #(zero? (rem n %)) (range 2 (inc (quot n 2))))))

) (defn perfect? [n]

 (== (reduce + (proper-divisors n)) n)

)</lang>

Common Lisp

Translation of: Haskell

<lang lisp>(defun perfectp (n)

 (= n (loop for i from 1 below n when (= 0 (mod n i)) sum i)))</lang>

D

Based on the Algol version: <lang d>pure bool isPerfectNumber(int n) {

   if (n < 2) {
       return false;
   }
   int max = cast(int) sqrt(cast(real) n) + 1;
   int sum = 1;

   for (int i = 2; i < max; i++) {
       if (n % i == 0) {
           sum += i;
           int q = n / i;
           if (q > i) {
               sum += q;
           }
       }
   }

   return sum == n;

}

void main() {

   for (int n; n < 10000; n++) {
       if (isPerfectNumber(n)) {
           writeln(n);
       }
   }

}</lang> <lang d>unittest {

   assert(equal(filter!(isPerfectNumber)(iota(1,10000)), [6,28,496,8128]));

}</lang>

E

<lang e>pragma.enable("accumulator") def isPerfectNumber(x :int) {

 var sum := 0
 for d ? (x % d <=> 0) in 1..!x {
   sum += d
   if (sum > x) { return false }
 }
 return sum <=> x

}</lang>

Erlang

<lang erlang>is_perfect(X) ->

   X == lists:sum([N || N <- lists:seq(1,X-1), X rem N == 0]).</lang>

FALSE

<lang false>[0\1[\$@$@-][\$@$@$@$@\/*=[@\$@+@@]?1+]#%=]p: 45p;!." "28p;!. { 0 -1 }</lang>

Factor

<lang factor>USING: kernel math math.primes.factors sequences ; IN: rosettacode.perfect-numbers

perfect? ( n -- ? ) [ divisors sum ] [ 2 * ] bi = ;</lang>

Forth

<lang forth>: perfect? ( n -- ? )

 1
 over 2/ 1+ 2 ?do
   over i mod 0= if i + then
 loop
 = ;</lang>

Fortran

Works with: Fortran version 90 and later

<lang fortran>FUNCTION isPerfect(n)

 LOGICAL :: isPerfect
 INTEGER, INTENT(IN) :: n
 INTEGER :: i, factorsum
 isPerfect = .FALSE.
 factorsum = 1
 DO i = 2, INT(SQRT(REAL(n)))
    IF(MOD(n, i) == 0) factorsum = factorsum + i + (n / i)
 END DO
 IF (factorsum == n) isPerfect = .TRUE.

END FUNCTION isPerfect</lang>

GAP

<lang gap>Filtered([1 .. 10000], n -> Sum(DivisorsInt(n)) = 2*n);

  1. [ 6, 28, 496, 8128 ]</lang>

Go

This example is incorrect. It does not accomplish the given task. Please fix the code and remove this message.
 {Show {IsPerfect 33550336}}</lang>

PARI/GP

Uses built-in method. Faster tests would use the LL test for evens and myriad results on OPNs otherwise. <lang>isPerfect(n)=sigma(n,-1)==2</lang>

Perl

<lang perl>sub perf {

   my $n = shift;
   my $sum = 0;
   foreach my $i (1..$n-1) {
       if ($n % $i == 0) {
           $sum += $i;
       }
   }
   return $sum == $n;

}</lang> Functional style: <lang perl>use List::Util qw(sum);

sub perf {

   my $n = shift;
   $n == sum(0, grep {$n % $_ == 0} 1..$n-1);

}</lang>

Perl 6

<lang perl6>sub perf($n) { $n == [+] grep $n %% *, 1 ..^ $n }</lang>

PHP

Translation of: C++

<lang php>function is_perfect($number) {

   $sum = 0;
   for($i = 1; $i < $number; $i++)
   {
       if($number % $i == 0)
           $sum += $i;
   }
   return $sum == $number;

}

echo "Perfect numbers from 1 to 33550337:" . PHP_EOL; for($num = 1; $num < 33550337; $num++) {

   if(is_perfect($num))
       echo $num . PHP_EOL;

}</lang>

PicoLisp

<lang PicoLisp>(de perfect (N)

  (let C 0
     (for I (/ N 2)
        (and (=0 (% N I)) (inc 'C I)) )
     (= C N) ) )</lang>

PowerShell

<lang powershell>Function IsPerfect($n) { $sum=0

for($i=1;$i-lt$n;$i++)
{
 if($n%$i -eq 0)
 {
 $sum += $i
 }
}

return $sum -eq $n }

Returns "True" if the given number is perfect and "False" if it's not.</lang>

Prolog

Works with SWI-Prolog

<lang Prolog>tt_divisors(X, N, TT) :- Q is X / N, ( 0 is X mod N -> (Q = N -> TT1 is N + TT;

                            TT1 is N + Q + TT); 
           TT = TT1),

( sqrt(X) > N + 1 -> N1 is N+1, tt_divisors(X, N1, TT1); TT1 = X).

perfect(X) :- tt_divisors(X, 2, 1).

perfect_numbers(N, L) :- numlist(2, N, LN), include(perfect, LN, L). </lang>


PureBasic

<lang PureBasic>Procedure is_Perfect_number(n)

 Protected summa, i=1, result=#False
 Repeat  
   If Not n%i
     summa+i
   EndIf
   i+1
 Until i>=n
 If summa=n
   result=#True
 EndIf
 ProcedureReturn result

EndProcedure</lang>

Python

<lang python>def perf(n):

   sum = 0
   for i in xrange(1, n):
       if n % i == 0:
           sum += i
   return sum == n</lang>

Functional style: <lang python>perf = lambda n: n == sum(i for i in xrange(1, n) if n % i == 0)</lang>

R

<lang R>is.perf <- function(n){ if (n==0|n==1) return(FALSE) s <- seq (1,n-1) x <- n %% s m <- data.frame(s,x) out <- with(m, s[x==0]) return(sum(out)==n) }

  1. Usage - Warning High Memory Usage

is.perf(28) sapply(c(6,28,496,8128,33550336),is.perf)</lang>

REBOL

<lang rebol> perfect?: func [n [integer!] /local sum] [

   sum: 0
   repeat i (n - 1) [
       if zero? remainder n i [
           sum: sum + i
       ]
   ]
   sum = n

] </lang>

REXX

version 1

<lang rexx> /*REXX program to test if a number is perfect. */

arg low high . if high== & low== then high=10000 if low== then low=1 if high== then high=low

 do j=low to high
 if isperfect(j) then say j 'is a perfect number.'
 end

exit

/*─────────────────────────────────────ISPERFECT subroutine─────────────*/ isperfect: procedure; parse arg x /*get the number to be tested. */ if x=6 then return 1 /*handle this special case. */ if x//2==1 | x<28 then return 0 /*if odd or less then 28, nope. */

sum=3+x%2 /*we know the following factors: */

                                      /*  1                            */
                                      /*  2      (because it's even.)  */
                                      /*  x/2        "     "     "     */


 do j=3 to x%2                        /*starting at 3,  find factors.  */
 if j*j>x then leave                  /*if past the sqrt of X, stop.   */
 if x//j==0 then do                   /*J divides X evenly, so ...     */
                 sum=sum+j+x%j        /*... add it and the other factor*/
                 end
 end

return sum==x /*if the sum matches X, perfect! */ </lang> Output (using the defaults):

6 is a perfect number.
28 is a perfect number.
496 is a perfect number.
8128 is a perfect number.

version 2

<lang rexx> /*REXX program to test if a number is perfect. */

arg low high . if high== & low== then high=34000000 if low== then low=1 if high== then high=low w=length(high)

 do j=low to high
 if isperfect(j) then say right(j,w) 'is a perfect number.'
 end

exit


/*─────────────────────────────────────ISPERFECT subroutine─────────────*/ isperfect: procedure; parse arg x /*get the number to be tested. */ if x=6 then return 1 /*handle this special case. */ if x//2==1 | x<28 then return 0 /*if odd or less then 28, nope. */

                                      /*we know that perfect numbers   */
                                      /*can be expressed as:           */
                                      /*  [2**n - 1]  *  [2** (n-1) ]  */
 do k=3                               /*start at a power of three.     */
 ?=(2**k-1)*2**(k-1)                  /*compute expression for a power.*/
 if ?<x then iterate                  /*Too low?  Then keep on truckin'*/
 if ?>x then return 0                 /*Too high?  Number isn't perfect*/
 if ?==x then leave                   /*this number is just right.     */
 end

sum=3+x%2 /*we know the following factors: */

                                      /*  1      ('cause Mama said so.)*/
                                      /*  2      (because it's even.)  */
                                      /*  x/2        "     "     "     */
 do j=3 to x%2                        /*starting at 3,  find factors.  */
 if j*j>x then leave                  /*if past the sqrt of X, stop.   */
 if x//j==0 then do                   /*J divides X evenly, so ...     */
                 sum=sum+j+x%j        /*... add it and the other factor*/
                 end
 end

return sum==x /*if the sum matches X, perfect! */ </lang> Output (using the defaults):

       6 is a perfect number.
      28 is a perfect number.
     496 is a perfect number.
    8128 is a perfect number.
33550336 is a perfect number.

Ruby

<lang ruby>def perf(n)

   sum = 0
   for i in 1...n
       if n % i == 0
           sum += i
       end
   end
   return sum == n

end</lang> Functional style: <lang ruby>def perf(n)

   n == (1...n).select {|i| n % i == 0}.inject(0) {|sum, i| sum + i}

end</lang>

Scala

<lang scala>def perfectInt(input: Int) = ((2 to sqrt(input).toInt).collect {case x if input % x == 0 => x + input / x}).sum == input - 1</lang>

Scheme

<lang scheme>(define (perf n)

 (let loop ((i 1)
            (sum 0))
   (cond ((= i n)
          (= sum n))
         ((= 0 (modulo n i))
          (loop (+ i 1) (+ sum i)))
         (else
          (loop (+ i 1) sum)))))</lang>

Slate

<lang slate>n@(Integer traits) isPerfect [

 (((2 to: n // 2 + 1) select: [| :m | (n rem: m) isZero])
   inject: 1 into: #+ `er) = n

].</lang>

Smalltalk

<lang smalltalk>Integer extend [

 "Translation of the C version; this is faster..."
 isPerfectC [ |tot| tot := 1.
    (2 to: (self sqrt) + 1) do: [ :i |
       (self rem: i) = 0
       ifTrue: [ |q|
                 tot := tot + i.
                 q := self // i. 
                 q > i ifTrue: [ tot := tot + q ]
       ]
    ].
    ^ tot = self
 ]
 "... but this seems more idiomatic"
 isPerfect [
    ^ ( ( ( 2 to: self // 2 + 1) select: [ :a | (self rem: a) = 0 ] )
        inject: 1 into: [ :a :b | a + b ] ) = self
 ]

].</lang>

<lang smalltalk>1 to: 9000 do: [ :p | (p isPerfect) ifTrue: [ p printNl ] ]</lang>

Tcl

<lang tcl>proc perfect n {

   set sum 0
   for {set i 1} {$i <= $n} {incr i} {
       if {$n % $i == 0} {incr sum $i}
   }
   expr {$sum == 2*$n}

}</lang>

Ursala

<lang Ursala>#import std

  1. import nat

is_perfect = ~&itB&& ^(~&,~&t+ iota); ^E/~&l sum:-0+ ~| not remainder</lang> This test program applies the function to a list of the first five hundred natural numbers and deletes the imperfect ones. <lang Ursala>#cast %nL

examples = is_perfect*~ iota 500</lang> output:

<6,28,496>