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 decision-problem 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.
68 Answers 68
Brachylog, 4 bytes
fk+?
The predicate succeeds for perfect inputs and fails for imperfect inputs, printing true. or false. if run as a complete program (except on the last test case which takes more than a minute on TIO).
The input's
f factors
k without the last element
+ sum to
? the input.
-
4\$\begingroup\$ I like how the code says
fk:x \$\endgroup\$Ismael Miguel– Ismael Miguel2019年03月13日 01:38:16 +00:00Commented Mar 13, 2019 at 1:38
Neim, 3 bytes
VsE
(I don't actually know how to run all of the test cases at once, since I started learning Neim about fifteen minutes ago, but I did check them individually.)
Prints 0 for imperfect, 1 for perfect.
V Pop an int from the stack and push its proper divisors,
implicitly reading the int from a line of input as the otherwise absent top of the stack.
s Pop a list from the stack and push the sum of the values it contains.
E Pop two ints from the stack and push 1 if they are equal, 0 if they are not;
implicitly reading the same line of input that was already read as the second int, I guess?
Implicitly print the contents of the stack, or something like that.
-
4\$\begingroup\$ "I guess?"; "or something like that.". When you're not even sure what you've written yourself, haha. ;) But yes, that's indeed how it works. I don't know Neim, but using the input implicitly like that and outputting implicitly at the end implicitly, is similar in 05AB1E. \$\endgroup\$Kevin Cruijssen– Kevin Cruijssen2019年03月13日 12:26:45 +00:00Commented Mar 13, 2019 at 12:26
-
\$\begingroup\$ How is
E1 byte? Does Neim use only 128 such non-standart characters? \$\endgroup\$kajacx– kajacx2019年03月13日 13:39:06 +00:00Commented Mar 13, 2019 at 13:39 -
5\$\begingroup\$ @kajacx Neim has its own code page. Therefore, each of the 256 characters present in the codepage can be encoded using 1 byte. \$\endgroup\$Mr. Xcoder– Mr. Xcoder2019年03月13日 17:23:26 +00:00Commented Mar 13, 2019 at 17:23
R, (削除) 33 (削除ここまで) 29 bytes
!2*(n=scan())-(x=1:n)%*%!n%%x
Returns TRUE for perfect numbers and FALSE for imperfect ones.
-
\$\begingroup\$ What do the 2 !s in a row get you? \$\endgroup\$Chthonyx– Chthonyx2019年03月12日 03:16:45 +00:00Commented Mar 12, 2019 at 3:16
-
\$\begingroup\$ @CTHall I misread the spec; they originally mapped
0(perfect) toFALSEand nonzero toTRUEbut I removed one of them to reverse the mapping. It's a useful golfing trick to cast fromnumerictological, often in conjunction withwhichor[. \$\endgroup\$Giuseppe– Giuseppe2019年03月12日 03:37:42 +00:00Commented Mar 12, 2019 at 3:37
Japt -!, 4 bytes
\â¬x
-----------------
Implicit Input U
\ Equal to
x Sum of
â Factors of U
¬ Without itself
For some reason ¦ doesnt work on tio so I need to use the -! flag and \ instead
-
\$\begingroup\$ That's not a TIO issue;
Udoesn't get auto-inserted before!. \$\endgroup\$Shaggy– Shaggy2019年03月12日 09:31:44 +00:00Commented Mar 12, 2019 at 9:31
Python 3, 46 bytes
lambda x:sum(i for i in range(1,x)if x%i<1)==x
Brute force, sums the factors and checks for equality.
-
2\$\begingroup\$ Using the comprehension condition as a mask for your iteration variable would save a byte. \$\endgroup\$Jonathan Frech– Jonathan Frech2019年03月12日 04:04:04 +00:00Commented Mar 12, 2019 at 4:04
-
\$\begingroup\$ Since you can return truthy for an imperfect number,
lambda x:sum(i for i in range(1,x)if x%i<1)^xshould work as well. \$\endgroup\$nedla2004– nedla20042019年03月12日 13:13:20 +00:00Commented Mar 12, 2019 at 13:13
Python, 45 bytes
lambda n:sum(d*(n%d<1)for d in range(1,n))==n
True for perfect; False for others (switch this with == -> !=)
(削除) 44 42 (削除ここまで) 41 bytes (-2 thanks to ovs) if we may output using "truthy vs falsey":
f=lambda n,i=1:i/n or-~f(n,i+1)-(n%i<1)*i
(falsey (0)) for perfect; truthy (a non-zero integer) otherwise
-
-
\$\begingroup\$ @ovs ah, nicely done. \$\endgroup\$Jonathan Allan– Jonathan Allan2019年03月12日 12:06:24 +00:00Commented Mar 12, 2019 at 12:06
-
\$\begingroup\$ @ovs ..and another saved from that - thanks! \$\endgroup\$Jonathan Allan– Jonathan Allan2019年03月12日 12:16:16 +00:00Commented Mar 12, 2019 at 12:16
Octave, 25 bytes
@(n)~mod(n,t=1:n)*t'==2*n
Explanation
@(n)~mod(n,t=1:n)*t'==2*n
@(n) % Define anonymous function with input n
1:n % Row vector [1,2,...,n]
t= % Store in variable t
mod(n, ) % n modulo [1,2,...,n], element-wise. Gives 0 for divisors
~ % Logical negate. Gives 1 for divisors
t' % t transposed. Gives column vector [1;2;...;n]
* % Matrix multiply
2*n % Input times 2
== % Equal? This is the output value
C# (Visual C# Interactive Compiler), 46 bytes
n=>Enumerable.Range(1,n).Sum(x=>n%x<1?x:0)^n*2
Returns 0 if perfect, otherwise returns a positive number. I don't know if outputting different types of integers are allowed in place of two distinct truthy and falsy values, and couldn't find any discussion on meta about it. If this is invalid, I will remove it.
C# (Visual C# Interactive Compiler), (削除) 49 (削除ここまで) 47 bytes
n=>Enumerable.Range(1,n).Sum(x=>n%x<1?x:0)==n*2
Labyrinth, 80 bytes
?::`}:("(!@
perfect:
{:{:;%"}
+puts; "
}zero: "
}else{(:
"negI" _~
""""""{{{"!@
The Latin characters perfect puts zero else neg I are actually just comments*.
i.e. if the input is perfect a 0 is printed, otherwise -1 is.
?::`}:("(!@ ?::`}:("(!@
: BEWARE :
{:{:;%"} {:{:;%"}
+ ; " +LAIR; "
} : " } OF : "
} {(: }MINO{(:
" " _~ "TAUR" _~
""""""{{{"!@ """"""{{{"!@
How?
Takes as an input a positive integer n and places an accumulator variable of -n onto the auxiliary stack, then performs a divisibility test for each integer from n-1 down to, and including, 1, adding any which do divide n to the accumulator. Once this is complete if the accumulator variable is non-zero a -1 is output, otherwise a 0 is.
The ?::`}:( is only executed once, at the beginning of execution:
?::`}:( Main,Aux
? - take an integer from STDIN and place it onto Main [[n],[]]
: - duplicate top of Main [[n,n],[]]
: - duplicate top of Main [[n,n,n],[]]
` - negate top of Main [[n,n,-n],[]]
} - place top of Main onto Aux [[n,n],[-n]]
: - duplicate top of Main [[n,n,n],[-n]]
( - decrement top of Main [[n,n,n-1],[-n]]
The next instruction, ", is a no-op, but we have three neighbouring instructions so we branch according to the value at the top of Main, zero takes us forward, while non-zero takes us right.
If the input was 1 we go forward because the top of Main is zero:
(!@ Main,Aux
( - decrement top of Main [[1,1,-1],[-1]]
! - print top of Main, a -1
@ - exit the labyrinth
But if the input was greater than 1 we turn right because the top of Main is non-zero:
:} Main,Aux
: - duplicate top of Main [[n,n,n-1,n-1],[-n]]
} - place top of Main onto Aux [[n,n,n-1],[-n,n-1]]
At this point we have a three-neighbour branch, but we know n-1 is non-zero, so we turn right...
"% Main,Aux
" - no-op [[n,n,n-1],[-n,n-1]]
% - place modulo result onto Main [[n,n%(n-1)],[-n,n-1]]
- ...i.e we've got our first divisibility indicator n%(n-1), an
- accumulator, a=-n, and our potential divisor p=n-1:
- [[n,n%(n-1)],[a,p]]
We are now at another three-neighbour branch at %.
If the result of % was non-zero we go left to decrement our potential divisor, p=p-1, and leave the accumulator, a, as it is:
;:{(:""}" Main,Aux
; - drop top of Main [[n],[a,p]]
: - duplicate top of Main [[n,n],[a,p]]
{ - place top of Aux onto Main [[n,n,p],[a]]
- three-neighbour branch but n-1 is non-zero so we turn left
( - decrement top of Main [[n,n,p-1],[a]]
: - duplicate top of Main [[n,n,p-1,p-1],[a]]
"" - no-ops [[n,n,p-1,p-1],[a]]
} - place top of Main onto Aux [[n,n,p-1],[a,p-1]]
" - no-op [[n,n,p-1],[a,p-1]]
% - place modulo result onto Main [[n,n%(p-1)],[a,p-1]]
- ...and we branch again according to the divisibility
- of n by our new potential divisor, p-1
...but if the result of % was zero (for the first pass only when n=2) we go straight on to BOTH add the divisor to our accumulator, a=a+p, AND decrement our potential divisor, p=p-1:
;:{:{+}}""""""""{(:""} Main,Aux
; - drop top of Main [[n],[a,p]]
: - duplicate top of Main [[n,n],[a,p]]
{ - place top of Aux onto Main [[n,n,p],[a]]
: - duplicate top of Main [[n,n,p,p],[a]]
{ - place top of Aux onto Main [[n,n,p,p,a],[]]
+ - perform addition [[n,n,p,a+p],[]]
} - place top of Main onto Aux [[n,n,p],[a+p]]
} - place top of Main onto Aux [[n,n],[a+p,p]]
""""""" - no-ops [[n,n],[a+p,p]]
- a branch, but n is non-zero so we turn left
" - no-op [[n,n],[a+p,p]]
{ - place top of Aux onto Main [[n,n,p],[a+p]]
- we branch, but p is non-zero so we turn right
( - decrement top of Main [[n,n,p-1],[a+p]]
: - duplicate top of Main [[n,n,p-1,p-1],[a+p]]
"" - no-ops [[n,n,p-1,p-1],[a+p]]
} - place top of Main onto Aux [[n,n,p-1],[a+p,p-1]]
At this point if p-1 is still non-zero we turn left:
"% Main,Aux
" - no-op [[n,n,p-1],[a+p,p-1]]
% - modulo [[n,n%(p-1)],[a+p,p-1]]
- ...and we branch again according to the divisibility
- of n by our new potential divisor, p-1
...but if p-1 hit zero we go straight up to the : on the second line of the labyrinth (you've seen all the instructions before, so I'm leaving their descriptions out and just giving their effect):
:":}"":({):""}"%;:{:{+}}"""""""{{{ Main,Aux
: - [[n,n,0,0],[a,0]]
" - [[n,n,0,0],[a,0]]
- top of Main is zero so we go straight
- ...but we hit the wall and so turn around
: - [[n,n,0,0,0],[a,0]]
} - [[n,n,0,0],[a,0,0]]
- top of Main is zero so we go straight
"" - [[n,n,0,0],[a,0,0]]
: - [[n,n,0,0,0],[a,0,0]]
( - [[n,n,0,0,-1],[a,0,0]]
{ - [[n,n,0,0,-1,0],[a,0]]
- top of Main is zero so we go straight
- ...but we hit the wall and so turn around
( - [[n,n,0,0,-1,-1],[a,0]]
: - [[n,n,0,0,-1,-1,-1],[a,0]]
"" - [[n,n,0,0,-1,-1,-1],[a,0]]
} - [[n,n,0,0,-1,-1],[a,0,-1]]
- top of Main is non-zero so we turn left
" - [[n,n,0,0,-1,-1],[a,0,-1]]
% - (-1)%(-1)=0 [[n,n,0,0,0],[a,0,-1]]
; - [[n,n,0,0],[a,0,-1]]
: - [[n,n,0,0,0],[a,0,-1]]
{ - [[n,n,0,0,0,-1],[a,0]]
: - [[n,n,0,0,0,-1,-1],[a,0]]
{ - [[n,n,0,0,0,-1,-1,0],[a]]
+ - [[n,n,0,0,0,-1,-1],[a]]
} - [[n,n,0,0,0,-1],[a,-1]]
} - [[n,n,0,0,0],[a,-1,-1]]
""""""" - [[n,n,0,0,0],[a,-1,-1]]
- top of Main is zero so we go straight
{ - [[n,n,0,0,0,-1],[a,-1]]
{ - [[n,n,0,0,0,-1,-1],[a]]
{ - [[n,n,0,0,0,-1,-1,a],[]]
Now this { has three neighbouring instructions, so...
...if a is zero, which it will be for perfect n, then we go straight:
"!@ Main,Aux
" - [[n,n,0,0,0,-1,-1,a],[]]
- top of Main is a, which is zero, so we go straight
! - print top of Main, which is a, which is a 0
@ - exit the labyrinth
...if a is non-zero, which it will be for non-perfect n, then we turn left:
_~"!@ Main,Aux
_ - place a zero onto Main [[n,n,0,0,0,-1,-1,a,0],[]]
~ - bitwise NOT top of Main (=-1-x) [[n,n,0,0,0,-1,-1,a,-1],[]]
" - [[n,n,0,0,0,-1,-1,a,-1],[]]
- top of Main is NEGATIVE so we turn left
! - print top of Main, which is -1
@ - exit the labyrinth
JavaScript, 38 bytes
n=>eval("for(i=s=n;i--;)n%i||!(s-=i)")
(Last testcase timeout on TIO.)
-
\$\begingroup\$ @Arnauld Just forgot to remove the
f=after converting from a recursive function. \$\endgroup\$tsh– tsh2019年03月12日 10:07:24 +00:00Commented Mar 12, 2019 at 10:07 -
\$\begingroup\$ Just out of curiosity, why not going with a recursive version? (It would be 34 bytes.) \$\endgroup\$Arnauld– Arnauld2019年03月12日 10:09:39 +00:00Commented Mar 12, 2019 at 10:09
-
\$\begingroup\$ @Arnauld because recursive version would simply failed for larger testcase due to stack overflow. Maybe I need some environments default to strict mode to make it work. \$\endgroup\$tsh– tsh2019年03月12日 10:17:27 +00:00Commented Mar 12, 2019 at 10:17
-
2\$\begingroup\$ Fair enough, but your program doesn't have to complete the larger test cases (which I think is the default rule, anyway). \$\endgroup\$Arnauld– Arnauld2019年03月12日 10:22:50 +00:00Commented Mar 12, 2019 at 10:22
-
TI-BASIC (TI-84), (削除) 30 (削除ここまで) 23 bytes
:2Ans=sum(seq(Ans/Xnot(remainder(Ans,X)),X,1,Ans,1
(削除) Horribly inefficient, but it works. (削除ここまで)
Reducing the bytecount sped up the program by a lot.
Input is in Ans.
Output is in Ans and is automatically printed out when the program completes.
Explanation:
(TI-BASIC doesn't have comments, so just assume that ; makes a comment)
:2Ans=sum(seq(Ans/Xnot(remainder(Ans,X)),X,1,Ans ;Full program
2Ans ;double the input
seq( ;generate a list
X, ;using the variable X,
1, ;starting at 1,
Ans ;and ending at the input
;with an implied increment of 1
Ans/X ;from the input divided by X
not( ), ;multiplied by the negated result of
remainder(Ans,X) ;the input modulo X
;(result: 0 or 1)
sum( ;sum up the elements in the list
= ;equal?
Example:
6
6
prgmCDGF2
1
7
7
prgmCDGF2
0
Note: The byte count of a program is evaluated using the value in [MEM]>[2]>[7] (36 bytes) then subtracting the length of the program's name, CDGF2, (5 bytes) and an extra 8 bytes used for storing the program:
36 - 5 - 8 = 23 bytes
Java (JDK), 54 bytes
n->{int s=0,d=0;for(;++d<n;)s+=n%d<1?d:0;return s==n;}
Though for a strict number by number matching, the following will return the same values, but is only 40 bytes.
n->n==6|n==28|n==496|n==8128|n==33550336
-
\$\begingroup\$ The rules say
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.\$\endgroup\$Jo King– Jo King2019年03月13日 14:28:09 +00:00Commented Mar 13, 2019 at 14:28 -
\$\begingroup\$ @JoKing Does that mean that I can't use a Java
intat all, but rather aBigInteger? Because Java hasBigIntegers, but it won't ever have anintthat's more than 31 bits as signed, which can't hold any other value than those represented here... \$\endgroup\$Olivier Grégoire– Olivier Grégoire2019年03月13日 14:30:23 +00:00Commented Mar 13, 2019 at 14:30 -
\$\begingroup\$ no, but if the program should still work if the
inttype was unbounded \$\endgroup\$Jo King– Jo King2019年03月13日 21:16:42 +00:00Commented Mar 13, 2019 at 21:16 -
1\$\begingroup\$ @JoKing Ok, I switched the two solutions again to have the computation first. \$\endgroup\$Olivier Grégoire– Olivier Grégoire2019年03月13日 22:35:31 +00:00Commented Mar 13, 2019 at 22:35
x86 Assembly, (削除) 45 (削除ここまで) 43 Bytes.
6A 00 31 C9 31 D2 41 39 C1 7D 0B 50 F7 F9 58 85
D2 75 F1 51 EB EE 31 D2 59 01 CA 85 C9 75 F9 39
D0 75 05 31 C0 40 EB 02 31 C0 C3
Explaination (Intel Syntax):
PUSH 0ドル ; Terminator for later
XOR ECX, ECX ; Clear ECX
.factor:
XOR EDX, EDX ; Clear EDX
INC ECX
CMP ECX, EAX ; divisor >= input number?
JGE .factordone ; if so, exit loop.
PUSH EAX ; backup EAX
IDIV ECX ; divide EDX:EAX by ECX, store result in EAX and remainder in EDX
POP EAX ; restore EAX
TEST EDX, EDX ; remainder == 0?
JNZ .factor ; if not, jump back to loop start
PUSH ECX ; push factor
JMP .factor ; jump back to loop start
.factordone:
XOR EDX, EDX ; clear EDX
.sum:
POP ECX ; pop divisor
ADD EDX, ECX ; sum into EDX
TEST ECX, ECX ; divisor == 0?
JNZ .sum ; if not, loop.
CMP EAX, EDX ; input number == sum?
JNE .noteq ; if not, skip to .noteq
XOR EAX, EAX ; clear EAX
INC EAX ; increment EAX (sets to 1)
JMP .return ; skip to .return
.noteq:
XOR EAX, EAX ; clear EAX
.return:
RETN
Input should be provided in EAX.
Function sets EAX to 1 for perfect and to 0 for imperfect.
EDIT: Reduced Byte-Count by two by replacing MOV EAX, 1ドル with XOR EAX, EAX and INC EAX
-
1\$\begingroup\$ I use a macro assembly so I don't know for sure but the comment"; divisor > input number" for me would be "; divisor >= input number" \$\endgroup\$user58988– user589882019年03月14日 16:54:36 +00:00Commented Mar 14, 2019 at 16:54
-
\$\begingroup\$ Assembly has easy operations one could reduce instructions length puts all in a line, use indentation and comment every 10 20 asm instructions.... \$\endgroup\$user58988– user589882019年03月14日 16:58:37 +00:00Commented Mar 14, 2019 at 16:58
-
\$\begingroup\$ @RosLuP I've fixed the comment in the code (thanks), but I don't know what you mean with your second comment. \$\endgroup\$Fayti1703– Fayti17032019年03月14日 19:23:48 +00:00Commented Mar 14, 2019 at 19:23
Regex (Perl/PCRE+(?^=)RME ), (削除) 44 (削除ここまで) 41 bytes
((2円x+?|^x\B)(?^=2円+$))++$(?^!(2円x+)3円+$)
This was a port of my 48 byte .NET regex below, using lookinto instead of variable-length lookbehind. This makes it far faster, and able to scan all numbers from 0 to 9000 in about 7 seconds on my PC. It also enables somes golfs that aren't possible in the .NET version.
# No anchor needed, because 2円 cannot be initially captured if
# matching is started anywhere besides the beginning.
# Sum as many divisors of N as we can (using the current position as the sum),
# without skipping any of them:
(
(
2円x+? # 2円 = the smallest number larger than the previous value of 2円
# for which the following is true; add 2円 to the running total
# sum of divisors.
|
^x # This must always be the first step. Add 1 to the sum of
# divisors, thus setting 2円 = 1 so the next iteration can keep
# going.
\B # Exclude 1 as a divisor if N == 1. We don't have to do this for
# N > 1, because this loop will never be able to add N to the
# already summed divisors (as 1 will always be one of them).
)
(?^=2円+$) # Assert that 2円 is a divisor of N
)++ # Iterate the above at least once, with a possessive quantifier
# to lock in the match (i.e. prevent any iteration from being
# backtracked into).
$ # Require that the sum equal N exactly. If this fails, the loop
# won't be able to find a match by backtracking, because
# everything inside the loop is done atomically.
# Assert that there are no more proper divisors of N that haven't already been summed:
(?^! # Lookinto – Assert that the following cannot match:
(2円x+) # 3円 = any number greater than 2円
3円+$ # Assert 3円 is a proper divisor of N
)
Regex (Perl/PCRE+(?^=)RME ), 45 bytes
^(?=(x(?=(x*))(?^=(?(?=2円+$)(3円?+2円))))+$)3円$
This is a port of the largest-to-smallest 47 byte .NET regex below, using lookinto instead of variable-length lookbehind.
Regex (Perl/PCRE+(?^=)RME ), 47 bytes
^(?=((?^0=(x*))(?^=(?(?=2円+$)(3円?+2円)))x)+$)3円$
This is a port of the smallest-to-largest 47 byte .NET regex below, using lookinto instead of variable-length lookbehind. This one is less conducive to being ported, and I had to use (?^0=), lookinto accessing the in-progress current match. I've not decided how to finalize the current behavior of this, so it's likely this version will not work with a future version of lookinto.
Regex (.NET), 47 bytes
^(?=((?<=(?=(?(3円+$)((?>2円?)3円)))(^x*))x)+$)2円$
^(?=(x(?=(x*$)(?<=(?(^2円+)(2円(?>3円?))))))+$)3円$
This is based on my 44 byte abundant numbers regex, with is in turn based on Martin Ender's 45 byte abundant numbers regex. It was trivial to adapt to matching perfect numbers; just two small changes were needed, with a third change made for aesthetic purposes.
# For the purpose of these comments, the input number will be referred to as N.
^(?= # Attempt to add up all the divisors of N.
(x # Cycle through all positive values of tail that are less than N,
# testing each one to see if it is a divisor of N. Start at N-1.
(?= # Do the below operations in a lookahead, so that upon popping back
# out of it our position will remaing the same as it is here.
(x*$) # 2円 = tail, a potential divisor; go to end to that the following
# lookbehind can operate on N as a whole.
(?<= # Switch to right-to-left evaluation so that we can operate both
# on N and the potential divisor 2円. This requires variable-length
# lookbehind, a .NET feature. Please read these comments in the
# order indicated, from [Step 1] to [Step 4].
(?(^2円+) # [Step 1] If 2円 is a divisor of N, then...
( # [Step 2] Add it to 3,円 the running total sum of divisors:
# 3円 = 3円 + 2円
2円 # [Step 4] Iff we run out of space here, i.e. iff the sum would
# exceed N at this point, the match will fail, and the
# summing of divisors will be halted. It can't backtrack,
# because everything in the loop is done atomically.
(?>3円?) # [Step 3] Since 3円 is a nested backref, it will fail to match on
# the first iteration. The "?" accounts for this, making
# it add zero to itself on the first iteration. This must
# be done before adding 2,円 to ensure there is enough room
# for the "?" not to cause the match to become zero-length
# even if 3円 has a value.
)
)
)
)
)+ # Using "+" instead of "*" here is an aesthetic choice, to make it
# clear we don't want to match zero. It doesn't actually make a
# difference (besides making the regex ever so slightly more
# efficient) because 3円 would be unset anyway for N=0.
$ # We can only reach this point if all proper divisors of N, all the
# way down to 2円 = 1, been successfully summed into 3円.
)
3円$ # Require the sum of divisors to be exactly equal to N.
Regex (.NET), 48 bytes
((?=.*(1円x+$)(?<=^2円+))2円|^x\B)+$(?<!^3円+(x+2円))
This is based on my 43 byte abundant numbers regex. It was interesting and somewhat tricky to adapt into a fully golfed perfect numbers regex.
# No anchor needed, because 1円 cannot be initially captured if
# matching is started anywhere besides the beginning.
# Sum as many divisors of N as we can (using the current position as the sum),
# without skipping any of them:
(
(?= # Atomic lookahead:
.*(1円x+$) # 2円 = the smallest number larger than the previous value of 1円
# (which is identical to the previous value of 2円) for which the
# following is true. We can avoid using "x+?" because the ".*"
# before this implicitly forces values to be tested in increasing
# order from the smallest.
(?<=^2円+) # Assert that 2円 is a divisor of N
)
2円 # Add 2円 to the running total sum of divisors
|
^x # This must always be the first step. Add 1 to the sum of divisors,
# thus setting 1円 = 1 so the next iteration can keep going
\B # Exclude 1 as a divisor if N == 1. We don't have to do this for
# N > 1, because this loop will never be able to add N to the
# already summed divisors (as 1 will always be one of them).
)+$ # Require that the sum equal N exactly. If this fails, the loop
# won't be able to find a match by backtracking, because everything
# inside the loop is done atomically.
# Assert that there are no more proper divisors of N that haven't already been summed:
(?<! # Assert that the following, evaluated right-to-left, cannot match:
^3円+ # [Step 2] is a proper divisor of N
(x+2円) # [Step 1] Any value of 3円 > 2円
)
Regex (Perl / PCRE2 v10.35+), (削除) 64 (削除ここまで) (削除) 60 (削除ここまで) 57 bytes
This is a port of the 41 byte regex, emulating variable-length lookbehind using a recursive subroutine call.
(?=((2円x+?|^x\B)((?<=(?=^2円+$|(?3)).)))++$)(?!(2円x+)4円+$)
Try it online! - Perl
Attempt This Online! - PCRE2 v10.40+
# No anchor needed, because 2円 cannot be initially captured if
# matching is started anywhere besides the beginning.
(?=
# Sum as many divisors of N as we can (using the current position as the sum),
# without skipping any of them:
(
(
2円x+? # 2円 = the smallest number larger than the previous value of 2円
# for which the following is true; add 2円 to the running total
# sum of divisors.
|
^x # This must always be the first step. Add 1 to the sum of
# divisors, thus setting 2円 = 1 so the next iteration can keep
# going.
\B # Exclude 1 as a divisor if N == 1. We don't have to do this for
# N > 1, because this loop will never be able to add N to the
# already summed divisors (as 1 will always be one of them).
)
((?<= # Define subroutine (?3); lookbehind
(?= # Circumvent the constant-width limitation of lookbehinds
# in PCRE by using a lookahead inside the lookbehind
^2円+$ # This is the payload of the emulated variable-length
# lookbehind: Assert that 2円 is a divisor of N
|
(?3) # Recursive call - this is the only alternative that can
# match until we reach the beginning of the string
)
. # Go back one character at a time, trying the above
# lookahead for a match each time
))
)++ # Iterate the above at least once, with a possessive quantifier
# to lock in the match (i.e. prevent any iteration from being
# backtracked into).
$ # Require that the sum equal N exactly. If this fails, the loop
# won't be able to find a match by backtracking, because
# everything inside the loop is done atomically.
)
# Assert that there are no more proper divisors of N that haven't already been summed:
(?! # Assert that the following cannot match:
(2円x+) # 4円 = any number greater than 2円
4円+$ # Assert 4円 is a proper divisor of N
)
It isn't practical to directly port the 47 byte regex to PCRE, because it changes the value of a capture group inside the lookbehind, and upon the return of any subroutine in PCRE, all capture groups are reset to the values they had upon entering the subroutine. It is possible, however, and I did this for the corresponding Abundant numbers regex by changing the main loop from iteration into recursion.
Regex (ECMAScript), 53 bytes – Even perfect numbers
If it is ever proved that there are no odd perfect numbers, the following would be a robust answer, but for now it is noncompeting, as it only matches even perfect numbers. It was written by Grimmy on 2019年03月15日.
^(?=(x(x*?))(1円1円)+$)((x*)(?=5円$))+(?!(xx+)6円+$)1円2円$
This uses the fact that every even perfect number is of the form \2ドル^{n-1} (2^n-1)\$ where \2ドル^n-1\$ is prime. For \2ドル^n-1\$ to be prime, it is necessary that \$n\$ itself be prime, so the regex does not need to do a \$log_2\$ test on \2ドル^n\$ to verify \$n\$ is prime. (I have used \$n\$ here instead of \$p\$ to make that clear.)
^ # N = tail = input
(?=(x(x*?))(1円1円)+$) # Assert that the largest odd divisor of N is >= 3 (due to
# having a "+" here instead of "*"; this is not necessary, but
# speeds up the regex's non-match when N is a a power of 2);
# 1円 = N / {largest odd divisor of N}
# == {largest power of 2 divisor of N}; 2円 = 1円 - 1
((x*)(?=5円$))+ # tail = N / {largest power of 2 divisor of N}
# == {largest odd divisor of N}
(?!(xx+)6円+$) # Assert tail is prime
1円2円$ # Assert tail == 1円*2 - 1; if this fails to match, it will
# backtrack into the "((x*)(?=5円$))+" loop (effectively
# multiplying by 2 repeatedly), but this will always fail
# to match because every subsequent match attempt will be
# an even number, and "1円2円$" can only be odd.
C (gcc), 41 bytes
f(n,i,s){for(i=s=n;--i;s-=n%i?0:i);n=!s;}
1: 0
12: 0
13: 0
18: 0
20: 0
1000: 0
33550335: 0
6: 1
28: 1
496: 1
8128: 1
33550336: 1
-65536: 0 <---- Unable to represent final test case with four bytes, fails
Let me know if that failure for the final case is an issue.
-
2
-
2\$\begingroup\$ "Output can be two distinct and consistent values through any allowed output format." You're not returning any two distinct values. \$\endgroup\$Olivier Grégoire– Olivier Grégoire2019年03月12日 09:29:08 +00:00Commented Mar 12, 2019 at 9:29
-
2\$\begingroup\$ @OlivierGrégoire Fortunately that can be readily fixed by replacing the space with an exclamation mark! \$\endgroup\$Neil– Neil2019年03月12日 09:33:37 +00:00Commented Mar 12, 2019 at 9:33
-
1\$\begingroup\$ @Neil Better yet, it can be fixed with
n=!s;instead ofreturn!s;to save 5 bytes. \$\endgroup\$user77406– user774062019年03月12日 09:50:07 +00:00Commented Mar 12, 2019 at 9:50 -
\$\begingroup\$ @OlivierGrégoire ahh, I forgot that point. Also, updated the with the improved code. I tried something similar, but the idiot I am I did
s=swhich more than likely got optimized out. \$\endgroup\$Marcos– Marcos2019年03月13日 00:26:56 +00:00Commented Mar 13, 2019 at 0:26
Husk, 5 bytes
=1ΣhḊ
Yields 1 for a perfect argument and 0 otherwise.
How?
=1Σ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
1 - first argument 24
= - equal? 0
Actually, 5 bytes
;÷Σ1⁄2=
Full program taking input from STDIN which prints 1 for perfect numbers and 0 otherwise.
How?
;÷Σ1⁄2= - full program, implicitly place input, n, onto the stack
; - duplicate top of stack
÷ - divisors (including n)
Σ - sum
1⁄2 - halve
= - equal?
Forth (gforth), 45 bytes
: f 0 over 1 ?do over i mod 0= i * - loop = ;
Explanation
Loops over every number from 1 to n-1, summing all values that divide n perfectly. Returns true if sum equals n
Code Explanation
: f \ start word definition
0 over 1 \ create a value to hold the sum and setup the bounds of the loop
?do \ start a counted loop from 1 to n. (?do skips if start = end)
over \ copy n to the top of the stack
i mod 0= \ check if i divides n perfectly
i * - \ if so, use the fact that -1 = true in forth to add i to the sum
loop \ end the counted loop
= \ check if the sum and n are equal
; \ end the word definition
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
MathGolf, (削除) 5 (削除ここまで) 4 bytes
─╡Σ=
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.
Pyth, 9 (削除) 13 (削除ここまで) bytes
qsf!%QTSt
Thank you to the commentors for the golf help
Finds all the factors of the input, sums them, and compares that to the original input.
-
\$\begingroup\$ A few golfs for you -
q0can be replaced with!, andSQproduces the range[1-Q], so the range[1-Q)can be generated usingStQ. As theQs are now at the end of the program they can both be omitted. Fettled version, 9 bytes -qsf!%QTSt\$\endgroup\$Sok– Sok2019年03月12日 10:35:38 +00:00Commented Mar 12, 2019 at 10:35
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)
Vyxal, (削除) 3+1 (削除ここまで) 3 bytes
∆K=
-1 byte thanks to @Deadcode for telling me to not be an idiot and remember that I added a sum of proper divisors built-in. I actually forgot that I did
This is: does the sum of the proper divisors of the input (∆K) equal the input itself (=).
-
\$\begingroup\$ Why not
∆K=? Also, this challenge requires1to return falsey, but your program is throwing an exception on an input of1. \$\endgroup\$Deadcode– Deadcode2021年03月08日 11:08:19 +00:00Commented Mar 8, 2021 at 11:08 -
\$\begingroup\$ Cool, you fixed the handling of
1:-) \$\endgroup\$Deadcode– Deadcode2021年03月09日 02:59:02 +00:00Commented Mar 9, 2021 at 2:59 -
\$\begingroup\$ @deadcode only because I was lucky enough to be reminded that I added a built-in lol ;p \$\endgroup\$2021年03月09日 07:30:44 +00:00Commented Mar 9, 2021 at 7:30
Qbasic, (削除) 53 (削除ここまで) 47 bytes
Thank you @Deadcode, -6 bytes
INPUT n
FOR i=1TO n-1
s=s-i*(n\i=n/i)
NEXT
?n=s
Literally quite Basic... Prints -1 for perfect numbers, 0 otherwise.
-
1\$\begingroup\$
IF n\i=n/i THEN s=s+ican be changed tos=s-i*(n\i=n/i)for -6 bytes. \$\endgroup\$Deadcode– Deadcode2021年03月08日 03:37:04 +00:00Commented Mar 8, 2021 at 3:37
Machine Language (x86 32-bit), (削除) 24 (削除ここまで) 23 bytes
This is a macro that takes an unsigned integer in EAX as input (N), and outputs the result in the Zero Flag (set=perfect, clear=imperfect). It also outputs a result in the Carry Flag (set=abundant, clear=non-abundant). As such, it's actually an answer for both this question and An abundance of integers!, requiring no modification.
It's based on 640KB's abundant numbers answer, with the two additional optimizations from l4m2's answer, where the divisors are subtracted from N instead of added to it (thus simultaneously setting the flags for the return value). An input of 1 is correctly handled, costing (削除) 3 (削除ここまで) 2 bytes.
89 C1 89 C3 9E EB 0E 31 D2 50 F7 F1 58 85 D2 75 04 29 CB 72 02 E2 F0
89 C1 mov ecx, eax ; copy input number into ECX
89 C3 mov ebx, eax ; copy input number into EBX
9E sahf ; in case input number is 1, let ZF=0 and CF=0
EB 0E jmp cont_loop ; exclude original number as a divisor
fact_loop:
31 D2 xor edx, edx ; clear EDX (high word for dividend)
50 push eax ; save original dividend
F7 F1 div ecx ; divide EDX:EAX / ECX
58 pop eax ; restore dividend
85 D2 test edx, edx ; if remainder = 0, it divides evenly
75 04 jnz cont_loop ; if not, continue loop
29 CB sub ebx, ecx ; Subtract divisor from EBX; this simultaneously
; changes the running total, and sets the flags for
; the return value.
72 02 jc done ; If CF=1, the sum of divisors subtracted from EBX has
; exceeded our input number, meaning it is abundant,
; and we need to exit the loop now to return this
; result in the flags.
cont_loop:
E2 F0 loop fact_loop
done: ; return value:
; (JZ) = ZF=1 = perfect
; (JNZ) = ZF=0 = imperfect
; (JC) = CF=1 = abundant
; (JNC) = CF=0 = non-abundant
; (JA) = CF=0 and ZF=0 = deficient
; (JNA) = CF=1 or ZF=1 = non-deficient
-
-
\$\begingroup\$ @l4m2 That's a great way to do abundant numbers with full 32-bit input support costing just 2 bytes, but as I know you know, this is perfect numbers :-) \$\endgroup\$Deadcode– Deadcode2021年03月11日 15:14:42 +00:00Commented Mar 11, 2021 at 15:14
-
\$\begingroup\$ Hmm didn't go up to check question \$\endgroup\$l4m2– l4m22021年03月11日 17:01:10 +00:00Commented Mar 11, 2021 at 17:01
-
\$\begingroup\$ Is there any case where the difference happens to be times of 2^32? \$\endgroup\$l4m2– l4m22021年03月11日 17:01:59 +00:00Commented Mar 11, 2021 at 17:01
-
\$\begingroup\$ @l4m2 I checked a couple days ago, generating all aliquot sums up to 2^32-1, and there are none where σ(n) = n + k*2^32. Nevertheless, I didn't want to remove my
jcinstruction even though it'd save 2 bytes, because I really like having a single routine that handles both abundant and perfect numbers, and also would work with any operand size (not just 32 bits)... but yep, you have a point, technically I could drop 2 bytes this way. But that would be like hard-coding the perfect numbers rather than detecting them. \$\endgroup\$Deadcode– Deadcode2021年03月11日 17:17:19 +00:00Commented Mar 11, 2021 at 17:17
Machine Language (x86 32-bit), 21 bytes
is_perfect:
mov ecx, esi ; copy input number into ECX
inc esi
mov ebx, esi ; copy input number + 1 into EBX
fact_loop:
xor edx, edx ; clear EDX (high word for dividend)
mov eax, esi
div ecx ; divide (n+1) / ECX
dec edx ; if remainder = 1, n/ECX is zero and ECX is not 1
; In case EAX = 2^32-1, this doesn't work as intended
; (get edx=0 for all ECXs)
; According to test 2^(2^n)-1 up to 2^128-1 are all
; deficient so it happens to be correct
jnz cont_loop ; if not, continue loop
sub ebx, eax ; Subtract divisor from EBX; this simultaneously
; changes the running total, and sets the flags for
; the return value.
jc done ; If CF=1, the sum of divisors subtracted from EBX has
; exceeded our input number, meaning it is abundant,
; and we need to exit the loop now to return this
; result in the flags.
cont_loop:
loop fact_loop
dec ebx ; Subtract the 1 added into esi for ZF
done: ; return value:
; (JZ) = ZF=1 = perfect
; (JNZ) = ZF=0 = imperfect
end_is_perfect:
Machine Language (x86 32-bit), 22 bytes edited from here with also abundant? output
is_perfect:
mov ecx, esi ; copy input number into ECX
mov ebx, esi ; copy input number into EBX
fact_loop:
xor edx, edx ; clear EDX (high word for dividend)
lea eax, [esi+1]
div ecx ; divide (n+1) / ECX
dec edx ; if remainder = 1, n/ECX is zero and ECX is not 1
; In case EAX = 2^32-1, this doesn't work as intended
; (get edx=0 for all ECXs)
; According to test 2^(2^n)-1 up to 2^128-1 are all
; deficient so it happens to be correct
jnz cont_loop ; if not, continue loop
sub ebx, eax ; Subtract divisor from EBX; this simultaneously
; changes the running total, and sets the flags for
; the return value.
jc done ; If CF=1, the sum of divisors subtracted from EBX has
; exceeded our input number, meaning it is abundant,
; and we need to exit the loop now to return this
; result in the flags.
cont_loop:
loop fact_loop
test ebx, ebx ; Not SUBed in last cycle
done: ; return value:
; (JZ) = ZF=1 = perfect
; (JNZ) = ZF=0 = imperfect
; (JC) = CF=1 = abundant
; (JNC) = CF=0 = non-abundant
; (JA) = CF=0 and ZF=0 = deficient
; (JNA) = CF=1 or ZF=1 = non-deficient
end_is_perfect:
Bad luck in last round sub is not runned and a test is needed
-
\$\begingroup\$ Nicely done! You forgot to remove the
stdinstruction from the test harness after removingstosb, though. \$\endgroup\$Deadcode– Deadcode2021年03月13日 12:52:27 +00:00Commented Mar 13, 2021 at 12:52
Prolog (SWI), (削除) 70 (削除ここまで) (削除) 67 (削除ここまで) 63 bytes
-3 bytes thanks to @Jo King
-4 bytes thanks to @Steffan
$N:-bagof(M,(between(1,N,M),N mod M<1),L),sumlist(L,S),S=:=2*N.
Explore related questions
See similar questions with these tags.
1would be perfect, since every number is divisible by1and itself. The sum of proper divisors of1is0\$\endgroup\$