29
\$\begingroup\$

Background:

The current Perfect Numbers challenge is rather flawed and complicated, since it asks you to output in a complex format involving the factors of the number. This is a purely repost of the challenge.

Challenge

Given a positive integer through any standard input format, distinguish between whether it is perfect or not.

A perfect number is a number that is equal to the sum of all its proper divisors (its positive divisors less than itself). For example, \$6\$ is a perfect number, since its divisors are \$1,2,3\$, which sum up to \$6\$, while \$12\$ is not a perfect number since its divisors ( \$1,2,3,4,6\$ ) sum up to \$16\$, not \$12\$.

Test Cases:

Imperfect:
1,12,13,18,20,1000,33550335

Perfect:
6,28,496,8128,33550336,8589869056

Rules

  • Your program doesn't have to complete the larger test cases, if there's memory or time constraints, but it should be theoretically able to if it were given more memory/time.
  • Output can be two distinct and consistent values through any allowed output format. If it isn't immediately obvious what represents Perfect/Imperfect, please make sure to specify in your answer.
\$\endgroup\$
  • \$\begingroup\$ Wait, so truthy is for values that aren't perfect, and falsey is for values that are? \$\endgroup\$ – Esolanging Fruit Mar 12 '19 at 2:57
  • 2
    \$\begingroup\$ @Tvde1 Proper divisors have to less than the number, otherwise no number other than 1 would be perfect, since every number is divisible by 1 and itself. The sum of proper divisors of 1 is 0 \$\endgroup\$ – Jo King Mar 12 '19 at 7:40
  • 3
    \$\begingroup\$ @Grimy Only if you can prove so. Good luck! (though I'm wondering how that would save bytes) \$\endgroup\$ – Jo King Mar 12 '19 at 9:15
  • 1
    \$\begingroup\$ So no, too bad. It would cut the size of an ECMA regex answer by a factor of about 3. \$\endgroup\$ – Grimmy Mar 12 '19 at 9:18
  • 3
    \$\begingroup\$ "Output can be two distinct and consistent values" - may we not use "truthy vs falsey" here (e.g. for Python using zero vs non zero; a list with content vs an empty list; and combinations thereof)? \$\endgroup\$ – Jonathan Allan Mar 12 '19 at 10:15

45 Answers 45

1
2
1
\$\begingroup\$

Bash, 56 bytes

Maybe a recursive function will be shorter? My Bash is certainly not strong.

s=0;for ((;v++<$1;)){ $[s+=($1%$v<1)*$v-1];};[ $s = $1 ]

A full program taking a command line argument which has a return code 0 if it was perfect and 1 otherwise.

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Haskell, 35 bytes

f x=x==sum[y|y<-[1..x-1],x`mod`y<1]

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Twig, 108 bytes

Yeah, I managed to get something longer than Java :/

This creates a macro that you import into your own template and call the method a

{%macro a(n,x=0)%}{%if n>1%}{%for i in 1..n-1%}{%set x=x+i*(n%i==0)%}{%endfor%}{{x==n}}{%endif%}{%endmacro%}

Returns 1 for perfect numbers, nothing for imperfect.

You can try it on https://twigfiddle.com/0or03v (testcases included)

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Husk, 5 bytes

=¹ΣhḊ

Yields 1 for a perfect argument and 0 otherwise.

Try it online!

How?

=¹ΣhḊ - Function: integer, n   e.g. 24
    Ḋ - divisors                    [1,2,3,4,6,8,12,24]
   h  - initial items               [1,2,3,4,6,8,12]
  Σ   - sum                         36
 ¹    - first argument              24
=     - equal?                      0
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Actually, 5 bytes

;÷Σ½=

Full program taking input from STDIN which prints 1 for perfect numbers and 0 otherwise.

Try it online!

How?

;÷Σ½= - full program, implicitly place input, n, onto the stack
;     - duplicate top of stack
 ÷    - divisors (including n)
  Σ   - sum
   ½  - halve
    = - equal?
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Factor, 57 bytes

: f ( x -- ? ) dup [1,b) [ dupd divisor? ] filter sum = ;

Try it online!

There is a shorter solution on the Rosetta Code that uses the divisors builtin:

: f ( n -- ? )  [ divisors sum ] [ 2 * ] bi = ;

but I wanted to come up with my own solution.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Racket, 54 bytes

(require math)(define(p n)(=(sum(divisors n))(* 2 n)))

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Kotlin, 38 bytes

{i->(1..i-1).filter{i%it==0}.sum()==i}

Expanded:

{ i -> (1..i - 1).filter { i % it == 0 }.sum() == i }

Explanation:

  {i->                      start lambda with parameter i
    (2..i-1)                create a range from 2 until i - 1 (potential divisors)
      .filter{i%it==0}      it's a divisor if remainder = 0; filter divisors
        .sum()              add all divisors
          ==i                compare to the original number
             }               end lambda

Try it online!

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

MathGolf, 5 4 bytes

─╡Σ=

Try it online!

Explanation

─       get divisors (includes the number itself)
 ╡      discard from right of list (removes the number itself)
  Σ     sum(list)
   =    pop(a, b), push(a==b)

Since MathGolf returns divisors rather than proper divisors, the solution is 1 byte longer than it would have been in that case.

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Qbasic, 53 bytes

INPUT n
FOR i=1TO n-1
IF n\i=n/i THEN s=s+i
NEXT
?n=s

Literally quite Basic... Prints -1 for perfect numbers, 0 otherwise.

REPL

| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

APL(NARS), chars 11, bytes 22

{⍵=2÷⍨11π⍵}

11π return the sum of all divisors, test:

  f←{⍵=2÷⍨11π⍵}
  f¨1 12 13 18 20 1000 33550335
0 0 0 0 0 0 0 
  f¨6 28 496 8128 33550336 8589869056
1 1 1 1 1 1 
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

MATL, 5 bytes

EGZ\s=

Try it out at MATL Online

Explanation

      % Implicitly grab the input as an integer
      %    STACK: { 6 }
E     % Multiply by two
      %    STACK: { 12 }
G     % Grab the input again
      %    STACK: { 12,  6 }
Z\    % Compute all divisors (including itself)
      %    STACK: { 12,  [1, 2, 3, 6] }
s     % Sum up these divisors
      %    STACK: { 12, 12 }
=     % Check that the two elements on the stack are equal
      %    STACK: { 1 }
      % Implicitly display the result
| improve this answer | |
\$\endgroup\$
1
\$\begingroup\$

Gaia, 4 bytes

dΣ⁻=

Try it online!

1 for perfect, 0 for imperfect.

d	| implicit input, n, push divisors
 Σ	| take the sum
  ⁻	| subtract n
   =	| equal to n?

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

MACHINE LANGUAGE(X86, 32 bit), 38 bytes

00000788  53                push ebx
00000789  8B442408          mov eax,[esp+0x8]
0000078D  31DB              xor ebx,ebx
0000078F  31C9              xor ecx,ecx
00000791  43                inc ebx
00000792  39C3              cmp ebx,eax
00000794  730E              jnc 0x7a4
00000796  31D2              xor edx,edx
00000798  50                push eax
00000799  F7F3              div ebx
0000079B  58                pop eax
0000079C  09D2              or edx,edx
0000079E  75F1              jnz 0x791
000007A0  01D9              add ecx,ebx
000007A2  EBED              jmp short 0x791
000007A4  29C8              sub eax,ecx
000007A6  0F94C0            setz al
000007A9  0FB6C0            movzx eax,al
000007AC  5B                pop ebx
000007AD  C3                ret
000007AE

Function lenght: 7AEh-788h=26h=38d; below assembly file that generate obj for linking:

; nasmw -fobj  this.asm
; bcc32 -v  file.c this.obj
section _DATA use32 public class=DATA
global _sumd
section _TEXT use32 public class=CODE

_sumd:    
      push    ebx
      mov     eax,  dword[esp+  8]
      xor     ebx,  ebx
      xor     ecx,  ecx
.1:   inc     ebx
      cmp     ebx,  eax
      jae     .2
      xor     edx,  edx
      push    eax
      div     ebx
      pop     eax
      or      edx,  edx
      jnz     .1
      add     ecx,  ebx
      jmp     short  .1
.2:   sub     eax,  ecx
      setz    al
      movzx   eax,  al
      pop     ebx
      ret

below the C file for link and test that function:

#include <stdio.h>
unsigned es[]={1,12,13,18,20,1000,33550335,6,28,496,8128,33550336,0};
int sumd(unsigned);

main(void)
{int  i;
 for(i=0;es[i];++i)
    printf("f(%u)=%u\n",es[i],sumd(es[i]));    
 return 0;
}

below the macro assembly file source of the .asm one:

; nasmw -fobj  this.asm
; bcc32 -v  file.c this.obj
section _DATA use32 public class=DATA
global  _sumd
section _TEXT use32 public class=CODE

_sumd:
<b  |a=^8|b^=b|c^=c
.1:  ++b |b>=a#.2|r^=r|<a|div b|>a|r|=r|jnz .1|c+=b|#.1
.2:  a-=c|setz al|movzx eax, al
>b
ret

below the 113 bytes golfing code of above:

_sumd:<b|a=^8|b^=b|c^=c|.1:++b|b>=a#.2|r^=r|<a|div b|>a|r|=r|jnz .1|c+=b|#.1|.2:a-=c|setz al|movzx eax, al|>b|ret

the results:

f(1)=0
f(12)=0
f(13)=0
f(18)=0
f(20)=0
f(1000)=0
f(33550335)=0
f(6)=1
f(28)=1
f(496)=1
f(8128)=1
f(33550336)=1

I got the trick of use push eax|div | pop eax from https://codegolf.stackexchange.com/a/181515/58988

| improve this answer | |
\$\endgroup\$
0
\$\begingroup\$

VDM-SL, 101 bytes

f(i)==s([x|x in set {1,...,i-1}&i mod x=0])=i;s:seq of nat+>nat
s(x)==if x=[]then 0 else hd x+s(tl x) 

Summing in VDM is not built in, so I need to define a function to do this across the sequences, this ends up taking up the majority of bytes

A full program to run might look like this:

functions 
f:nat+>bool
f(i)==s([x|x in set {1,...,i-1}&i mod x=0])=i;s:seq of nat+>nat
s(x)==if x=[]then 0 else hd x+s(tl x)
| improve this answer | |
\$\endgroup\$
1
2

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.