# $n$-perfect numbers

A positive integer $$\x\$$ is an $$\n\$$-perfect number if $$\\sigma(x) = nx\$$, where $$\\sigma(x)\$$ is the divisor sum function. For example, $$\120\$$ is a $$\3\$$-perfect number because its divisors sum to $$\360\$$:

$$360 = 3\times120 = 1+2+3+4+5+6+8+10+12+15+20+24+30+40+60+120$$

and

$$926073336514623897600 = 6\times154345556085770649600 = 1+2+3+4+5+6+7+8+9+10+11+12+\dots+51448518695256883200+77172778042885324800+154345556085770649600$$

so $$\154345556085770649600\$$ is a $$\6\$$-perfect number.

You are to take an integer $$\x\$$ as input and output a value $$\n\$$, such that $$\x\$$ is an $$\n\$$-perfect number. If no such $$\n\$$ exists, you may output any consistent value that isn't a positive integer. You will never receive an input outside the bounds of your language, but your algorithm must work for arbitrarily large $$\x\$$.

This is so the shortest code in bytes wins.

Mini challenge: Beat 5 bytes in Jelly

## Test cases

    x -> n
1 -> 1
2 -> 0
3 -> 0
4 -> 0
5 -> 0
6 -> 2
28 -> 2
120 -> 3
496 -> 2
500 -> 0
672 -> 3
30240 -> 4
154345556085770649600 -> 6

• – caird coinheringaahing Sep 13 at 21:42
• For inputs that produce no perfect numbers, is running forever without producing output valid? – xnor Sep 13 at 23:32
• @xnor Yeah, I don’t see a problem with that, go ahead – caird coinheringaahing Sep 13 at 23:44
• 'You will never receive an input outside the bounds of your language' - just to check: if the input is at the bounds of our language, we'll need to go beyond the bounds to calculate nx, right? Is this what you mean, or did you intend that we only need to handle nx within the bounds of our language...? – Dominic van Essen Sep 14 at 7:47
• @Shaggy Yeah, that’s perfectly fine – caird coinheringaahing Sep 14 at 11:23

# Husk, 4 bytes

¦¹ΣḊ


Try it online!

The last test case times out.

## Explanation

¦¹ΣḊ   Input is a number x.
Ḋ   List of divisors.
Σ    Sum.
¦      Division if divisible, 0 if not
¹     by x.


¦ is usually just a divisibility test, but here its return value is useful.

• Need to make a post for "Strangely convenient operators in golfing languages". – Razetime Sep 14 at 4:31

# Jelly, 5 bytes

R×iÆs


Try it online!

### Explanation:

      - Explanation (sample for input 6)
R     - Range ([1, 2, 3, 4, 5, 6])
×    - Multiply by input ([6, 12, 18, 24, 30, 36])
Æs - Divisor sum (12)
i   - Index of divisor sum in list, else 0 (2)

• Nice, I originally did this using R of Æs, which was 7, didn't think of applying it to x itself. – Jonathan Allan Sep 14 at 7:01
• Very nice! Almost identical to mine: ×€iÆs – caird coinheringaahing Sep 14 at 12:53

# Brachylog, 6 bytes

f+;?/ℕ


Try it online!

### How it works

f+;?/ℕ
f+     the sum of the factors
;?/ℕ divided by the input
ℕ is a natural number


Alternative version, I think is cooler, but longer:

f+~×[?,.]∧
f+          the sum of the factors
~×        unifies with the multiplication of
[?,.]   the input and the output
∧  return the output


# 05AB1E, 7 6 bytes

Ý*IÑOk


Try it online!

Explanation:

Ý*IÑOk>
Ý        0-Index inclusive range of input (6 -> [1, 2, 3, 4, 5, 6])
*       Multiply by input ([6, 12, 18, 24, 30, 36])
IÑO    Get input -> divisors -> sum (6 -> [1, 2, 3, 6] -> 12)
k   0-Index of divisor-sum in array or -1 if not found. ([6, >12<, 18, 24, 30, 36] -> 1)


I just used Sisyphus' method. This could probably be golfed down or even made more efficient, but I lack the 05AB1E knowledge to do so. Just thought I'd give it a shot to pass the time.

-1 Byte thanks to ovs

• Nice answer, but there is a small error in your explanation. k uses 0-based indexing, so it should be "0-Index of divisor-sum in array or -1 if not found. ([6, >12<, 18, 24, 30, 36] -> 1)" and "Increment (1 -> 2 / -1 -> 0)". And I'm not sure it can be made shorter. The to-the-point approaches (ÑOy/ÐïQ* or ÑODIÖ*I/) are both 8 bytes, so yours is already a byte shorter. I also like that your answer outputs in integers instead of decimals. :) – Kevin Cruijssen Sep 14 at 8:01
• Ah thanks! I thought it was 0-indexing at first, but had just mixed up my test-cases. Thanks for pointing it out. :) – Bismarck71 Sep 14 at 8:15
• I think you can use Ý instead of L and drop the increment at the end. – ovs Sep 14 at 9:25

# C (gcc), 47 bytes

s,i;f(x){for(i=s=x;--i;)s+=x%i?0:i;s/=s%x*s+x;}


Try it online!

Returns n or 0.

# APL (Dyalog Unicode), 16 15 13 bytes

Thanks to Bubbler for pointing out I can change the output format to save a couple of bytes

⍸×∘⍳⍨=1⊥∘∪⊢∨⍳


Try it online!

Outputs a singleton list of n when n exists, and an empty array otherwise. Finds the index of (⍸) where the sum of (1⊥) the divisors (∪⊢∨⍳) equals (=) a multiple of the input (×∘⍳⍨). I use ⍸ and = instead of just ⍳ to find the index because it returns an empty list when the element isn't there rather than the length of the list.

• lol, posted at the same time. – Razetime Sep 14 at 4:25
• Outputting singleton array is permitted by default, and an empty vector is a consistent value, so you can omit ⊃∘. – Bubbler Sep 14 at 4:51

# Whitespace, 153 bytes

[S S S N
_Push_0][S N
S _Duplicate_0][T   N
T   T   _Read_STDIN_as_integer][T   T   T   _Retrieve_input][S N
S _Duplicate_input][S N
S _Duplicate_input][N
S S N
_Create_Label_LOOP][S S S T N
_Push_1][T  S S T   _Subtract][S N
S _Duplicate][N
T   S S N
_If_0_Jump_to_Label_REACHED_ZERO][S T   S S T   S N
_Copy_0-based_2nd_input][S T    S S T   N
_Copy_0-based_1st_integer][T    S T T   _Modulo][N
T   S T N
_If_0_Jump_to_Label_ADD_TO_SUM][N
S N
N
_Jump_to_Label_LOOP][N
S S T   N
_Create_Label_ADD_TO_SUM][S N
T   _Swap_top_two][S T  S S T   N
_Copy_0-based_1st_integer][T    S S S _Add_top_two][S N
T   _Swap_top_two][N
S N
N
_Jump_to_Label_LOOP][N
S S S N
_Create_Label_REACHED_ZERO][S N
N
_Discard_top][S N
S _Duplicate_top][S T   S S T   S N
_Copy_0-based_2nd_input][T  S T T   _Modulo][N
T   S S S N
_If_0_Jump_to_Label_DIVISIBLE][S S S N
_Push_0][N
S N
S T
_Jump_to_Label_OUTPUT][N
S S S S N
_Create_Label_DIVISIBLE][S N
T   _Swap_top_two][T    S T S _Integer_divide_top_two][N
S S S T N
_Create_Label_OUTPUT][T N
S T _Output_as_integer]


Letters S (space), T (tab), and N (new-line) added as highlighting only.
[..._some_action] added as explanation only.

Try it online (with raw spaces, tabs and new-lines only).

Explanation in pseudo-code:

Integer input = STDIN as input
Integer sum = input
Integer i = input
Start LOOP:
i = i - 1
If(i == 0):
Jump to Label REACHED_ZERO
If(input % i == 0):
sum = sum + i
Go to next iteration of LOOP

Label REACHED_ZERO:
Integer output
If(sum % input == 0):
output = sum integer-divided by input
Else:
output = 0

Print output as integer to STDOUT


Example run: input = 6

Command    Explanation                       Stack         Heap   STDIN  STDOUT  STDERR

SSSN       Push 0                            [0]
SNS        Duplicate top (0)                 [0,0]
TNTT       Read STDIN as integer             [0]           {0:6}  6
TTT        Retrieve at address (0)           [6]           {0:6}
SNS        Duplicate top (6)                 [6,6]         {0:6}
SNS        Duplicate top (6)                 [6,6,6]       {0:6}
NSSN       Create Label LOOP                 [6,6,6]       {0:6}
SSSTN     Push 1                            [6,6,6,1]     {0:6}
TSST      Subtract top two (6-1)            [6,6,5]       {0:6}
SNS       Duplicate top (5)                 [6,6,5,5]     {0:6}
NTSSN     If 0: Jump to Label REACHED_ZERO  [6,6,5]       {0:6}
STSSTSN   Copy 0-based 2nd (6)              [6,6,5,6]     {0:6}
STSSTN    Copy 0-based 1st (5)              [6,6,5,6,5]   {0:6}
TSTT      Modulo top two (6%5)              [6,6,5,1]     {0:6}
NTSTN     If 0: Jump to Label ADD_TO_SUM    [6,6,5]       {0:6}
NSNN      Jump to Label LOOP                [6,6,5]       {0:6}

SSSTN     Push 1                            [6,6,5,1]     {0:6}
TSST      Subtract top two (5-1)            [6,6,4]       {0:6}
SNS       Duplicate top (4)                 [6,6,4,4]     {0:6}
NTSSN     If 0: Jump to Label REACHED_ZERO  [6,6,4]       {0:6}
STSSTSN   Copy 0-based 2nd (6)              [6,6,4,6]     {0:6}
STSSTN    Copy 0-based 1st (4)              [6,6,4,6,4]   {0:6}
TSTT      Modulo top two (6%4)              [6,6,4,2]     {0:6}
NTSTN     If 0: Jump to Label ADD_TO_SUM    [6,6,4]       {0:6}
NSNN      Jump to Label LOOP                [6,6,4]       {0:6}

SSSTN     Push 1                            [6,6,4,1]     {0:6}
TSST      Subtract top two (4-1)            [6,6,3]       {0:6}
SNS       Duplicate top (3)                 [6,6,3,3]     {0:6}
NTSSN     If 0: Jump to Label REACHED_ZERO  [6,6,3]       {0:6}
STSSTSN   Copy 0-based 2nd (6)              [6,6,3,6]     {0:6}
STSSTN    Copy 0-based 1st (3)              [6,6,3,6,3]   {0:6}
TSTT      Modulo top two (6%3)              [6,6,3,0]     {0:6}
NTSTN     If 0: Jump to Label ADD_TO_SUM    [6,6,3]       {0:6}
NSSTN     Create Label ADD_TO_SUM           [6,6,3]       {0:6}
SNT      Swap top two                      [6,3,6]       {0:6}
STSSTN   Copy 0-based 1st (3)              [6,3,6,3]     {0:6}
TSSS     Add top two (6+3)                 [6,3,9]       {0:6}
SNT      Swap top two                      [6,9,3]       {0:6}
NSNN     Jump to Label LOOP                [6,9,3]       {0:6}

SSSTN     Push 1                            [6,9,3,1]     {0:6}
TSST      Subtract top two (3-1)            [6,9,2]       {0:6}
SNS       Duplicate top (2)                 [6,9,2,2]     {0:6}
NTSSN     If 0: Jump to Label REACHED_ZERO  [6,9,2]       {0:6}
STSSTSN   Copy 0-based 2nd (6)              [6,9,2,6]     {0:6}
STSSTN    Copy 0-based 1st (5)              [6,9,2,6,2]   {0:6}
TSTT      Modulo top two (6%5)              [6,9,2,0]     {0:6}
NTSTN     If 0: Jump to Label ADD_TO_SUM    [6,9,2]       {0:6}
SNT      Swap top two                      [6,2,9]       {0:6}
STSSTN   Copy 0-based 1st (2)              [6,2,9,2]     {0:6}
TSSS     Add top two (9+2)                 [6,2,11]      {0:6}
SNT      Swap top two                      [6,11,2]      {0:6}
NSNN     Jump to Label LOOP                [6,11,2]      {0:6}

SSSTN     Push 1                            [6,11,2,1]    {0:6}
TSST      Subtract top two (2-1)            [6,11,1]      {0:6}
SNS       Duplicate top (1)                 [6,11,1,1]    {0:6}
NTSSN     If 0: Jump to Label REACHED_ZERO  [6,11,1]      {0:6}
STSSTSN   Copy 0-based 2nd (6)              [6,11,1,6]    {0:6}
STSSTN    Copy 0-based 1st (1)              [6,11,1,6,1]  {0:6}
TSTT      Modulo top two (6%1)              [6,11,1,0]    {0:6}
NTSTN     If 0: Jump to Label ADD_TO_SUM    [6,11,1]      {0:6}
SNT      Swap top two                      [6,1,11]      {0:6}
STSSTN   Copy 0-based 1st (1)              [6,1,11,1]    {0:6}
TSSS     Add top two (11+1)                [6,1,12]      {0:6}
SNT      Swap top two                      [6,12,1]      {0:6}
NSNN     Jump to Label LOOP                [6,12,1]      {0:6}

SSSTN     Push 1                            [6,12,1,1]    {0:6}
TSST      Subtract top two (1-1)            [6,12,0]      {0:6}
SNS       Duplicate top (1)                 [6,12,0,0]    {0:6}
NTSSN     If 0: Jump to Label REACHED_ZERO  [6,12,0]      {0:6}
NSSSN     Create Label REACHED_ZERO         [6,12,0]      {0:6}
SNN      Discard top (0)                   [6,12]        {0:6}
SNS      Duplicate top (12)                [6,12,12]     {0:6}
STSSTSN  Copy 0-based 2nd (6)              [6,12,12,6]   {0:6}
TSTT     Modulo top two (12%6)             [6,12,0]      {0:6}
NTSSSN   If 0: Jump to Label DIVISIBLE     [6,12]        {0:6}
NSSSSN   Create Label DIVISIBLE            [6,12]        {0:6}
SNT     Swap top two                      [12,6]        {0:6}
TSTS    Integer-divide top two (12/6)     [2]           {0:6}
NSSSTN  Create Label OUTPUT               [2]           {0:6}
TNST   Output top as integer (2)         []            {0:6}         2
error


Stops with an error after printing the result, because no exit is defined.

# Pyth, 15 bytes

&!%Jsf!%QTSQQ/J


Try it online!

## Explanation

&!%Jsf!%QTSQQ/J
J              # set J to
s             # sum of
f    SQ      # filtering the range [1, input] with
!%QT        # lambda T: not (input % T)    (divisibility test)
# implicit print the
&                 # short-circuiting and of
!%J        Q     # not (J % input)
/J   # and J / input


# JavaScript (ES6), 41 bytes

Returns 0 if there's no solution.

x=>(g=k=>x=k&&k*!(x%k)/x+g(k-1))(x)%1?0:x


Try it online!

# Jelly, 6 bytes

Æs0:%?


A monadic Link accepting a positive integer which yields a non-negative integer.

Try it online! Or see the test-suite.

### How?

Æs0:%? - Link: x
Æs     - divisor sum
? - if...
%  - ...condition: has a remainder when divided
0    - ...then: zero
:  - ...else: integeger divide


# APL (Dyalog Unicode), 19 18 bytes

⊢(÷⍨×0=|)1⊥∘⍸0=⍳|⊢


Try it online!

Conversion to train by Jo King.(-3 bytes)

-1 more byte from Jo King after changing the check condition.

# Older answer, 22 bytes

{(⊢×⌊=⊢)⍵÷⍨+/⍸0=⍵|⍨⍳⍵}


## Explanation

{(⊢×⌊=⊢)⍵÷⍨+/⍸0=⍵|⍨⍳⍵} ⍵ → input
⍳⍵  range 1-⍵
⍵|⍨    mod ⍵
0=       check which ones are divisors
⍸         get the indices (factors)
+/          sum the factors
⍵÷⍨            divide by ⍵
(⊢×⌊=⊢)               Inner tacit fn:
⌊=⊢                Floor equals right? (integer test, returns 0 or 1)
⊢×                   times right

• interesting, I'll add it in – Razetime Sep 14 at 4:28

# Haskell, 51 46 bytes

a!b=0^mod a b*div a b
f n=sum(map(n!)[1..n])!n


Try it online!

# Wolfram Language (Mathematica), 30 bytes

Tr@Divisors@#/#/._Rational->0&


Try it online!

-6 bytes from @att

• “If no such $n$ exists, you may output any consistent value that isn’t a positive integer” Those aren’t consistent values. – caird coinheringaahing Sep 13 at 23:27
• @cairdcoinheringaahing fixed to zero – J42161217 Sep 13 at 23:32
• 30 bytes – att Sep 14 at 3:23

# Charcoal, 23 20 bytes

ＮθＩ⌕Ｅ⊕θ×θιΣΦ⊕θ∧ι¬﹪θι


Try it online! Link is to verbose version of code. Port of @Sisyphus's algorithm but using @ovs's comment to deal with 0-indexing. Outputs -1 for nonexistence. Explanation:

Ｎθ                      Input x as a number
θ          x
⊕           Incremented
Φ            Filter over implicit range
ι        Current index
∧         Logical AND
θ     x
﹪      Modulo
ι    Current index
¬       Logical NOT
Σ             Take the sum
θ                 x
⊕                  Incremented
Ｅ                   Map over implicit range
θ               x
×                Multiplied by
ι              Current index
⌕                    Find the index
Ｉ                     Cast to string
Implicitly print


Unfortunately for Charcoal the sum of [] is not zero, which means that I can't save a byte by removing the two increments of x and incrementing the result instead.

Previous 23-byte solution:

Ｎθ≔ΣΦ⊕θ∧ι¬﹪θιη¿¬﹪ηθＩ÷ηθ


Try it online! Link is to verbose version of code. Explanation:

Ｎθ


Input x.

≔ΣΦ⊕θ∧ι¬﹪θιη


Create a list from 1..x, filter out numbers that don't divide x, and take the sum.

¿¬﹪ηθＩ÷ηθ


If x divides the sum then print the quotient.

# R, 4241 39 bytes

Edit: -1 byte (and, inspired by this, -2 more bytes) thanks to Robin Ryder

function(x)(d=sum(1:x*!x%%1:x))/x*!d%%x


Try it online!

Commented:

perfect_n=
function(x)
(d=            # d is the divisor sum, calculated as...
sum(          # sum of...
1:x*         # the values of 1..x that have...
!           # zero values for...
x%%1:x)    # x MOD 1..x
)
)/x            # output d/x...
*!d%%x      # but only if it's an integer
# (so d MOD x == 0)

• 41 bytes – Robin Ryder Sep 14 at 9:27
• Really good (and as usual, when I see it I think 'why didn't I think of that?'). Thanks for the golfing lesson! – Dominic van Essen Sep 14 at 9:52

# Scala, 54 53 bytes

x=>{val s=1 to x filter(x%_<1)sum;s/x*(1-(s%x).sign)}


Try it in Scastie

Sums every divisor of x from 1 to x, inclusive. If that sum is divisible by x, it returns that divided by x, otherwise it returns 0.

# Retina, 51 bytes

.+
*
|""Lw^(.+)(?=\1*$) ^$-1;
L$^(.+);(\1)+$
$#2  Try it online! Link includes less slower test cases. Explanation: .+ *  Convert the input to unary. |""Lw^(.+)(?=\1*$)


List all of the factors without delimiting them, thus summing them.

^
$-1;  Retrieve the original unary value. L$^(.+);(\1)+#2


Count how many times it divides the sum. (Or output nothing if it does not.)

# Octave, 36 34 bytes

@(x)~mod(s=~mod(x,r=1:x)*r',x)*s/x


Anonymous function that takes a floating-point or integer number as input. The last test case fails due to memory limitations.

### Explanation

@(x)~mod(s=~mod(x,r=1:x)*r',x)*s/x

@(x)                                 % anonymous function with input x
1:x              % row vector [1 2 ... x]
r=                 % call that r
mod(x,     )             % x modulo [1 2 ... x]. Gives a row vector
~                         % negate each element. Gives 1 for divisors
r'          % column vector [1; 2; ... ; x]
*            % matrix-multiply. Gives the sum of divisors
s=                          % call that s
mod(                  ,x)       % sum of divisors modulo x
~                                % negate. Gives 1 if x divides sum of divisors
s/x   % sum of divisors divided by x
*      % multiply


# Python 3.8 (pre-release), 62 bytes

lambda x:(a:=sum(x/i*(x%i<1)for i in range(1,x+1)))%x<1and a/x


Try it online!

# MathGolf, 7 bytes

─Σk‼÷/*


Try it online.

Explanation:

─       # Get the divisors of the (implicit) input-integer
Σ      # Sum those divisors
k     # Push the input-integer again
‼    # Apply the following two commands separately to the stack:
÷   #  Check if the divisor-sum is divisible by the input (1 if truthy; 0 if falsey)
/   #  Integer-divide the divisor-sum by the input
*  # Multiply the two together
# (after which the entire stack joined together is output implicitly as result)


# Rockstar, 141135 131 bytes

Outputs nothing if no n exists.

listen to N
X's0
T's0
while N-X
let X be+1
let D be N/X
turn up D
let T be+D is N/X and X

let D be T/N
turn up D
if D is T/N
say D


Try it here (Code will need to be pasted in)

• Wow...This has to be the shortest Rockstar program I've ever seen. – user Sep 14 at 16:33
• You might wanna have a look at some of my others, @user! ;) – Shaggy Sep 14 at 16:36

# Icon, 67 bytes

procedure f(n)
s:=0
n%(i:=1to n)=0&s+:=i&\z
return(0=s%n&s/n)|0
end


Try it online!

# Japt-æ, 7 bytes

Outputs undefined if no n is found.

*N¶Îâ x


Try it

# Factor, 84 bytes

: f ( n -- n ) dup [1,b] [ dupd mod 0 = ] filter sum swap /mod 0 > [ drop 0 ] when ;


Try it online!

# Prolog, 117 bytes

s(X,D,S):-D<1,!,S is 0;E is D-1,(0 is X mod D,!,s(X,E,T),S is T+D;s(X,E,S)).
f(X,N):-s(X,X,S),0 is S mod X,N is S//X.


Try it online! (Please don't modify it directly, it would change my version too)

If anyone could figure out why this shorter version (96 bytes) isn't working, I'd be really grateful.

s(X,D,S):-D<1,!,S is 0;E is D-1,(0 is X mod D,!,s(X,E,T),S is T+D;s(X,E,S)).
f(X,N):-s(X,X,N*X).


Version with print debugging

# GolfScript, 22 bytes

~:x),{.x\%!*+}*.x%!*x/


Try it online!

~:x                     # Store the input in x
),                   # Make an array from 0 to x
{       }*         # For each number in the array, execute this block
.                 # Copy current number
x\%!             # The copy becomes 1 if it is a divisor of x and 0 if it isn't
*+           # Multiply and add
.        # Copy the sum of the divisors
x%!     # The copy becomes 1 if it is a divisor of x and 0 if it isn't
*    # Multiply
x/  # Divide by x