37
\$\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\$
6
  • \$\begingroup\$ Why is 1 not a perfect number? 1 == 1. \$\endgroup\$
    – Tvde1
    Mar 12, 2019 at 7:36
  • 3
    \$\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, 2019 at 7:40
  • 5
    \$\begingroup\$ @Grimy Only if you can prove so. Good luck! (though I'm wondering how that would save bytes) \$\endgroup\$
    – Jo King
    Mar 12, 2019 at 9:15
  • 2
    \$\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, 2019 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\$ Mar 12, 2019 at 10:15

65 Answers 65

1 2
3
1
\$\begingroup\$

Raku, 24 bytes

{$_==sum grep $_%%*,^$_}

Try it online!

\$\endgroup\$
1
\$\begingroup\$

Desmos, 45 bytes


f(n)=\{\sum_{N=1}^nN\{\mod(n,N)=0,0\}=2n,0\}

\$f(n)\$ returns \$1\$ if \$n\$ is a perfect number, \$0\$ is \$n\$ is an imperfect number.

Try It On Desmos!

Try It On Desmos! - Prettified

\$\endgroup\$
1
\$\begingroup\$

Alice, 17 bytes

/O\B!d v
@I/-?+&<

Try it online!

Outputs 0 if the number is perfect, non 0 if imperfect

Flattened

/I\B!d&+?-/O@
/I\             Reads the input
   B            Get all the divisors in ascending order
    !           Remove the input number and save it on the tape
     d&+        Sum all the remaining divisors of the stack
        ?       Get the input from the tape
         -      Subtract from the sum
          /O@   Output and exit
\$\endgroup\$
1
\$\begingroup\$

APL (Dyalog/GNU), 18 bytes, ⎕IO=0

{⍵=+/(0=⍵|⍨⍳⍵)/⍳⍵}

Try it online! (The in-browser version of APL has too small a workspace to handle the larger test cases.)

Explanation:

  • {...} creates an anonymous function (dfn), whose argument becomes the parameter . We'll examine the expression inside the braces from right to left.
    1. ⍳N generates a vector of the first N numbers starting with the index origin. Since that is set to 0, it goes up to N-1. For this function to work we only need to go up to N/2, but only accepts integers, and making the division result an integer would take more characters.
    2. / with two vector operands produces a new vector with each element of the right vector repeated a number of times equal to the corresponding element of the left vector. In this case we're going to build a vector of N 0s and 1s with 1s only at the positions corresponding to the proper divisors of N; the result will therefore be a vector containing only those divisors.
    3. The expression inside parentheses builds the selector; going right to left again, we start with another ⍳⍵. (We could have built a DRYer version that didn't need to repeat that, but it would have taken more characters.)
    4. | is the divide-and-take-remainder operator (mod). By itself it takes its operands on the opposite order from e.g. C's %, but we are transposing it with to flip that, which removes the need for another pair of parentheses. ⍵|⍨⍳⍵ divides each number from 0 to ⍵-1 into and returns a vector of the remainders. (Fortunately for this use, 0|N just returns N rather than throwing a division-by-zero error.)
    5. 0= is what it looks like: a simple equality test with 0. Applied to a vector, it returns a vector with 1's wherever the original vector had a 0, and 0's everywhere else - exactly what we want for our selector.
    6. Having built our vector of the proper divisors, we then compute the sum of its elements with +/ (reduction via addition).
    7. Finally, ⍵= returns our desired result: 1 if the sum is equal to itself, 0 otheriwse.
\$\endgroup\$
1
\$\begingroup\$

Scala, 72 71 bytes

saved 1 byte thanks to the comment.

Try it online!

def f(n:Int):Boolean={val F=for(i<-1 until n if n%i<1)yield i;F.sum==n}
\$\endgroup\$
0
1 2
3

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

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