# Am I perfect (number)?

This is my first challenge!

### Background

Perfect number is a positive integer, that is equal to the sum of all its divisors, except itself.
So 6 is perfect number, since 1 + 2 + 3 = 6.
On the other hand 12 is not, because 1 + 2 + 3 + 4 + 6 = 16 != 12.

Your task is simple, write a program, which will, for given n, print one of these messages:

I am a perfect number, because d1 + d2 + ... + dm = s == n
I am not a perfect number, because d1 + d2 + ... + dm = s [<>] n

Where
d1, ... dm are all divisors of n except for n.
s is the sum of all divisors d1, ..., dm (again, without n).
[<>] is either < (if s < n) or > (if s > n).

### Examples

For n being 6: "I am a perfect number, because 1 + 2 + 3 = 6 == 6"
For n being 12: "I am not a perfect number, because 1 + 2 + 3 + 4 + 6 = 16 > 12"
For n being 13: "I am not a perfect number, because 1 = 1 < 13"

### Rules

• n is not bigger than your language's standard int.
• You can read n from standard input, from command line arguments or from a file.
• Output message has to be printed on standard output and no additional characters can appear in the output (it may have trailing whitespace or newline)
• You may not use any built-ins or library functions which would solve the task (or its main part) for you. No GetDivisors() or something like that.
• All other standard loopholes apply.

### Winner

This is so shortest code in bytes wins!

• @orlp It is not, I edited the challenge, thanks for that. Sep 15 '15 at 21:57
• Why do you use = and == in the same equation? That makes no sense. It should be d1 + d2 + ... + dm = s = n IMO.
– orlp
Sep 15 '15 at 22:06
• @Zereges That's nonsensical. There is nothing being assigned. Only compared.
– orlp
Sep 15 '15 at 22:12
• @orlp It is intended. Sep 15 '15 at 22:24
• I wrote a four byte answer... and then I realized how the output is supposed to work. Mar 6 '19 at 7:04

# Java, 255 270 bytes (Still FF in base 17)

class C{public static void main(String[]a){int i=new Integer(a[0]),k=0,l=0;a[0]=" ";for(;++k<i;)if(i%k<1){l+=k;a[0]+=k+" ";}}System.out.print("I am "+(l==i?"":"not ")+"a perfect number, because "+a[0].trim().replace(" "," + ")+" = "+l+(l==i?" == ":l<i?" < ":" > ")+i);}}


class C {
public static void main(String[] a) {
int i = new Integer(a[0]), k = 0, l = 0;
a[0] = " ";
for(; ++k<i ;){
if (i % k == 0) {
l += k;
a[0] += k + " ";
}
}
System.out.print("I am " + (l == i ? "" : "not ") + "a perfect number, because " + a[0].trim().replace(" "," + ") + " = " + l + (l == i ? " == " : l < i ? " < " : " > ") + i);
}
}


Previously didn't work for odd numbers, so I had to tweak a few things. At least I got lucky with the byte count again. :)

• will l == i work over 255 ? Sep 16 '15 at 12:43
• I know if ruins your byte count, but you could save a character by replacing the last three (of four) occurrences of a[0] with a 'String b' and use 'b' in their place Sep 17 '15 at 7:39

# R, 158163157153143 141 bytes

Still room to golf this I think.
Edit: Replaced if(b<n)'<'else if(b>n)'>'else'==' with c('<'[b<n],'>'[b>n],'=='[b==n]). The paste(...) is replaced with an rbind(...)[-1]. Thanks @plannapus for a couple more bytes.

n=scan();a=2:n-1;b=sum(w<-a[!n%%a]);cat('I am','not'[b!=n],'a perfect number, because',rbind('+',w)[-1],'=',b,c('<'[b<n],'>'[b>n],'==')[1],n)


Ungolfed

n<-scan()             # get number from stdin
w<-which(!n%%1:(n-1)) # build vector of divisors
b=sum(w)              # sum divisors
cat('I am',           # output to STDOUT with a space separator
'not'[b!=n],      # include not if b!=n
'a perfect number, because',
rbind('+',w)[-1], # create a matrix with the top row as '+', remove the first element of the vector
'=',
b,                # the summed value
c(                # creates a vector that contains only the required symbol and ==
'<'[b<n],     # include < if b<n
'>'[b>n],     # include > if b>n
'=='
)[1],             # take the first element
n                 # the original number
)


Test run

> n=scan();b=sum(w<-which(!n%%1:(n-1)));cat('I am','not'[b!=n],'a perfect number, because',rbind('+',w)[-1],'=',b,c('<'[b<n],'>'[b>n],'==')[1],n)
1: 6
2:
I am a perfect number, because 1 + 2 + 3 = 6 == 6
> n=scan();b=sum(w<-which(!n%%1:(n-1)));cat('I am','not'[b!=n],'a perfect number, because',rbind('+',w)[-1],'=',b,c('<'[b<n],'>'[b>n],'==')[1],n)
1: 12
2:
I am not a perfect number, because 1 + 2 + 3 + 4 + 6 = 16 > 12
> n=scan();b=sum(w<-which(!n%%1:(n-1)));cat('I am','not'[b!=n],'a perfect number, because',rbind('+',w)[-1],'=',b,c('<'[b<n],'>'[b>n],'==')[1],n)
1: 13
2:
I am not a perfect number, because 1 = 1 < 13
>

• There should be + sign in between divisors. Sep 15 '15 at 22:43
• @Zereges I've just noticed that and will fix shortly Sep 15 '15 at 22:44
• +1 for the brilliant rbind trick! You can save 2 extra bytes if you assign 2:n-1 to a variable, say a: which(!n%%1:(n-1)) thus becomes a[!n%%a]. (The full code being then n=scan();a=2:n-1;b=sum(w<-a[!n%%a]);cat('I am','not'[b!=n],'a perfect number, because',rbind('+',w)[-1],'=',b,c('<'[b<n],'>'[b>n],'==')[1],n)) Sep 18 '15 at 9:07
• @plannapus Thanks, I was really pleased with that myself. Sep 18 '15 at 18:48

# Python 2, 183173 170 bytes

b=input();c=[i for i in range(1,b)if b%i<1];d=sum(c);print'I am %sa perfect number because %s = %d %s %d'%('not '*(d!=b),' + '.join(map(str,c)),d,'=<>='[cmp(b,d)%3::3],b)


Examples:

$python perfect_number.py <<< 6 I am a perfect number because 1 + 2 + 3 = 6 == 6$ python perfect_number.py <<< 12
I am not a perfect number because 1 + 2 + 3 + 4 + 6 = 16 > 12
$python perfect_number.py <<< 13 I am not a perfect number because 1 = 1 < 13$ python perfect_number.py <<< 100
I am not a perfect number because 1 + 2 + 4 + 5 + 10 + 20 + 25 + 50 = 117 > 100
$python perfect_number.py <<< 8128 I am a perfect number because 1 + 2 + 4 + 8 + 16 + 32 + 64 + 127 + 254 + 508 + 1016 + 2032 + 4064 = 8128 == 8128  Thanks to xnor for saving 13 bytes! • '=<>'[cmp(b,d)] - join the revolution! – orlp Sep 15 '15 at 23:42 • Excellent, thanks! Oh, wait ... :) Sep 15 '15 at 23:54 • @Celeo I came up with a similar solution. You can write b%i<1 for b%i==0. For ['not ',''][int(d==b)], you don't need the int, because Python will convert automatically. Moreover, you can use string mulitplication "not "*(d!=b). – xnor Sep 16 '15 at 3:59 • @xnor thanks for the suggestions! Sep 16 '15 at 15:36 • @Celeo You can adjust orlp's suggestion to work as "=<>="[cmp(b,d)%3::3]. – xnor Sep 19 '15 at 0:57 # Pyth, 81 bytes jd[+WK-QsJf!%QTStQ"I am"" not""a perfect number, because"j" + "J\=sJ@c3"==<>"._KQ  Try it online: Demonstration or Test Suite ### Explanation:  implicit: Q = input number StQ the range of numbers [1, 2, ..., Q-1] f filter for numbers T, which satisfy: !%QT Q mod T != 0 J save this list of divisors in J -QsJ difference between Q and sum of J K save the difference in K jd[ put all of the following items in a list and print them joined by spaces: "I am" * "I am" +WK " not" + "not" if K != 0 "a perfect number, because" * "a perfect ..." j" + "J * the divisors J joined by " + " \= * "=" sJ * sum of J c3"==<>" * split the string "==<>" in 3 pieces: ["==", "<", ">"] @ ._K and take the (sign of K)th one (modulo 3) Q * Q  # Julia, 161 157 bytes n=int(ARGS[1]) d=filter(i->n%i<1,1:n-1) s=sum(d) print("I am ",s!=n?"not ":"","a perfect number, because ",join(d," + ")," =$s ",s<n?"<":s>n?">":"=="," $n")  Ungolfed: # Read n as the first command line argument n = int(ARGS[1]) # Get the divisors of n and their sum d = filter(i -> n % i == 0, 1:n-1) s = sum(d) # Print to STDOUT print("I am ", s != n ? "not " : "", "a perfect number, because ", join(d, " + "), " =$s ",
s < n ? "<" : s > n ? ">" : "==",
" $n")  # CJam, 90 bytes "I am"rd:R{R\%!},:D:+R-g:Cz" not"*" a perfect number, because "D'+*'=+D:++'=C+_'=a&+a+R+S*  For comparison, printing a single = could be achieved in 83 bytes. Try it online in the CJam interpreter. ### How it works "I am" e# Push that string. rd:R e# Read a Double from STDIN and save it in R. { e# Filter; for each I in [0 ... R-1]: R\%! e# Push the logical NOT of (R % I). }, e# Keep the elements such that R % I == 0. :D e# Save the array of divisors in D. :+R-g e# Add the divisors, subtract R and compute the sign of the difference. :Cz e# Save the sign in C and apply absolute value. "not "* e# Repeat the string "not " that many times. " a perfect number, because " D'+* e# Join the divisors, separating by plus signs. '=+D:++ e# Append a '=' and the sum of the divisors. '=C+ e# Add the sign to '=', pushing '<', '=' or '>'. _'=a& e# Intersect a copy with ['=']. +a+ e# Concatenate, wrap in array and concatenate. e# This appends "<", "==" or ">". R+ e# Append the input number. S* e# Join, separating by spaces.  # Perl, 148 Bytes $a=<>;$_=join' + ',grep{$a%$_==0}1..$a-1;$s=eval;print"I am ".($s==$a?'':'not ')."a perfect number because$_ = $s ".(('==','>','<')[$s<=>$a])."$a"


With line breaks:

$a=<>;$_=join' + ',grep{$a%$_==0}1..$a-1;$s=eval;
print"I am ".($s==$a?'':'not ')."a perfect number because $_ =$s ".(('==','>','<')[$s<=>$a])." $a"  • I've had a poke over this and you can save 10 bytes by removing the outer parens around the 'not ' and '==','>','<' statements and switching from . to , (since nothing is added when printing a list). Also moving your assignments into parens the first time they're used saves a couple, and if you change the logic slightly to grep$a%_<1,1..($a=<>)-1 and $a!=($s=eval)&&'not ' you should shave off a few more! Hope that all makes sense! Sep 21 '15 at 23:20 # Lua, 244 231 bytes Golfed: n=io.read("*n")d={}s="1"t=1 for i=2,n-1 do if n%i==0 then table.insert(d,i)s=s.." + "..i t=t+i end end print(("I am%s a perfect number, because %s = %s"):format(t==n and""or" not", s, t..(t==n and" == "or(t>n and" > "or" < "))..n))  Ungolfed: n=io.read("*n") divisors={} sequence="1" sum=1 for i=2,n-1 do if n%i==0 then table.insert(divisors,i) sequence=sequence.." + "..i sum=sum+i end end print(("I am%s a perfect number, because %s = %s"):format(sum==n and""or" not", sequence, sum..(sum==n and" == "or(sum>n and" > "or" < "))..n))  # JavaScript (ES6), 146 Using template strings, it works in Firefox and latest Chrome. for(n=prompt(),o=t=i=1;++i<n;)n%i||(t+=i,o+=' + '+i) alert(I am${t-n?'not ':''}a perfect number because ${o} =${t} ${t<n?'<':t>n?'>':'=='} +n) ## Ruby, 174160155136134128 122 Bytes n=6;a=[*1...n].reject{|t|n%t>0};b=a.inject(:+)<=>n;print"I am#{" not"*b.abs} a perfect number, because ",a*?+,"<=>"[b+1],n  Saved another 6 Bytes :) Thanks to Tips for golfing in Ruby • The print command still bothers me.. And I need to figure out a way to shorten the if-statement ternary ? needs an else clause I cannot provide and only accepts one call per case Sep 16 '15 at 20:17 • only one print statement is left :) Sep 17 '15 at 10:30 # C#, 252 bytes class A{static void Main(string[]a){int i=int.Parse(a[0]);var j=Enumerable.Range(1,i-1).Where(o=>i%o==0);int k=j.Sum();Console.Write("I am "+(i!=k?"not ":"")+"a perfect number, because "+string.Join(" + ",j)+" = "+k+(k>i?" > ":k<i?" < ":" == ")+i);}}  # Hassium, 285 Bytes Disclaimer: Works with only the latest version of Hassium due to issues with command line args. func main(){n=Convert.toNumber(args[0]);s=1;l="1";foreach(x in range(2,n-3)){if(n%x==0){l+=" + "+x;s+=x;}}if(s==n)println("I am a perfect number, because "+l+" = "+s+" == "+s);else {print("I am not a perfect number, because "+l+" = "+s);if(s>n)println(" > "+n);else println(" < "+n);}}  More readable version: func main() { n = Convert.toNumber(args[0]); s = 1; l = "1"; foreach(x in range(2, n - 3)) { if (n % x== 0) { l += " + " + x; s += x; } } if (s == n) println("I am a perfect number, because " + l + " = " + s + " == " + s); else { print("I am not a perfect number, because " + l + " = " + s); if (s > n) println(" > " + n); else println(" < " + n); }  } • 1. I can't seem to convince Hassium to read my command-line arguments. If I execute mono src/Hassium/bin/Debug/Hassium.exe t.hs 6, it says System.ArgumentException: The file 6 does not exist.. 2. This doesn't work with this version, which is the lastest commit before this challenge was posted. Please add a disclaimer to your answer that state that your submission is non-competing. Sep 16 '15 at 21:29 • I tried it on Windows (built using MVS2015) and got same error. Sep 16 '15 at 21:45 • This is an issue that was updated literally 15 minutes ago. Clone the Hassium and compile again. I am very sorry as I ran into the exact same problem. Sep 16 '15 at 22:29 • It works fine with the latest version. Now if you could just add the disclaimer, I'll be happy to remove my downvote. (By the way, you can ping me by adding @Dennis to your comment. Otherwise, I don't get notified of your reply.) Sep 16 '15 at 22:47 • @Dennis I added it in. Thank you for your notification :) Sep 17 '15 at 1:23 # MATLAB, 238 Never going to be the shortest of all languages, but here's my attempt with MATLAB: n=input('');x=1:n-1;f=x(~rem(n,x));s=sum(f);a='not ';b=strjoin(strtrim(cellstr(num2str(f')))',' + ');if(s>n) c=' > ';elseif(s<n) c=' < ';else c=' == ';a='';end;disp(['I am ' a 'a perfect number, because ' b ' = ' num2str(s) c num2str(n)])  And this is in a slightly more readable form: n=input(); %Read in the number using the input() function x=1:n-1; %All integers from 1 to n-1 f=x(~rem(n,x)); %Determine which of those numbers are divisors s=sum(f); %Sum all the divisors a='not '; %We start by assuming it is not perfect (to save some bytes) b=strjoin(strtrim(cellstr(num2str(f')))',' + '); %Also convert the list of divisors into a string %where they are all separated by ' + ' signs. %Next check if the number is >, < or == to the sum of its divisors if(s>n) c=' > '; %If greater than, we add a ' > ' to the output string elseif(s<n) c=' < '; %If less than, we add a ' < ' to the output string else c=' == '; %If equal, we add a ' == ' to the output string a=''; %If it is equal, then it is a perfect number, so clear the 'not' string end %Finally concatenate the output string and display the result disp(['I am ' a 'a perfect number, because ' b ' = ' num2str(s) c num2str(n)])  I've managed to save 2 more bytes by not using a function. Instead you run the line of code and it requests the number as an input. Once run it displays the output at the end. ## Perl 6, 138 bytes $_=get;
my$c=$_ <=>my$s=[+] my@d=grep$_%%*,^$_; say "I am { 'not 'x?$c
}a perfect number, because {
join ' + ',@d
} = $s { «> == <»[1+$c]
} $_"  ( The count ignores the newlines, and indents, because they aren't needed ) @d is the array holding the divisors. $s holds the sum of the divisors.
$c is the value of the comparison between the input, and the sum of the divisors. ( effectively $c is one of -1,0,1, but is really one of Order::Less, Order::Same, or Order::More )

In 'not 'x?$c, ?$c in this case is effectively the same as abs $c, and x is the string repetition operator. «> == <» is short for ( '>', '==', '<' ). Since $c has one of -1,0,1, we have to shift it up by one to be able to use it to index into a list.

Technically this will work for numbers well above 2⁶⁴, but takes an inordinate amount of time for numbers above 2¹⁶.

# Pyth, 84 bytes

jd+,+"I am"*.aK._-QsJf!%QTtUQ" not""a perfect number, because"+.iJm\+tJ[\=sJ@"=<>"KQ


Invalid answer, because I refuse to implement = and == in the same equation.

• +1 for refusing to "implement = and == in the same equation." Sep 16 '15 at 20:35

# Ruby, 164 Bytes

->i{t=(1...i).select{|j|i%j==0};s=t.inject &:+;r=['==','>','<'][s<=>i];puts "I am #{'not ' if r!='=='}a perfect number, because #{t.join(' + ')} = #{s} #{r} #{i}"}


# Test

irb(main):185:0> ->i{t=(1...i).select{|j|i%j==0};s=t.inject &:+;r=['==','>','<'][s<=>i];puts "I am #{'not ' if r!='=='}a perfect number, because #{t.join(' + ')} = #{s} #{r} #{i}"}.call 6
I am a perfect number, because 1 + 2 + 3 = 6 == 6

irb(main):186:0> ->i{t=(1...i).select{|j|i%j==0};s=t.inject &:+;r=['==','>','<'][s<=>i];puts "I am #{'not ' if r!='=='}a perfect number, because #{t.join(' + ')} = #{s} #{r} #{i}"}.call 12
I am not a perfect number, because 1 + 2 + 3 + 4 + 6 = 16 > 12

irb(main):187:0> ->i{t=(1...i).select{|j|i%j==0};s=t.inject &:+;r=['==','>','<'][s<=>i];puts "I am #{'not ' if r!='=='}a perfect number, because #{t.join(' + ')} = #{s} #{r} #{i}"}.call 13
I am not a perfect number, because 1 = 1 < 13


# Emacs Lisp, 302 Bytes

(defun p(n)(let((l(remove-if-not'(lambda(x)(=(% n x)0))(number-sequence 1(- n 1)))))(setf s(apply'+ l))(format"I am%s a perfect number, because %s%s = %s %s %s"(if(= s n)""" not")(car l)(apply#'concat(mapcar'(lambda(x)(concat" + "(number-to-string x)))(cdr l)))s(if(= sum n)"=="(if(> sum n)">""<"))n)))


Ungolfed version:

(defun perfect (n)
(let ((l (remove-if-not '(lambda (x) (= (% n x) 0))
(number-sequence 1 (- n 1)))))
(setf sum (apply '+ l))
(format "I am%s a perfect number, because %s%s = %s %s %s" (if (= sum n)"" " not") (car l)
(apply #'concat (mapcar '(lambda (x) (concat " + " (number-to-string x))) (cdr l)))
sum (if(= sum n)
"=="
(if(> sum n)
">"
"<"))
n)))


# Powershell, 164 bytes

$a=$args[0]
$b=(1..($a-1)|?{!($a%$_)})-join" + "
$c=iex$b
$d=$a.compareto($c) "I am$("not "*!!$d)a perfect number, because$b = $c$(("==","<",">")[$d])$a"


A few of the common and not so common PoSh tricks;

• Create the sum, then evaluate it with iex
• Compareto to index the gt, lt, eq array
• !!$d will evaluate to true == 1 for$d = 1 or -1, and false == 0 for $d = 0 # awk, 150 n=$0{for(p=i=s=n>1;++i<n;)for(;n%i<1;p+=i++)s=s" + "i;printf"I am%s a perfect number, because "s" = "p" %s "n RS,(k=p==n)?_:" not",k?"==":p<n?"<":">"}


Wasted some bytes on making this correct for input 1. I'm not sure if that is expected.

n=\$0{
for(p=i=s=n>1;++i<n;)
for(;n%i<1;p+=i++)s=s" + "i;
printf "I am%s a perfect number, because "s" = "p" %s "n RS,
(k=p==n)?_:" not",k?"==":p<n?"<":">"
}


# 05AB1E, 58 bytes

„I€ÜIÑ¨©OIÊi'€–}“€…íÀ‚³,ƒ«“®vy'+}\'=®ODI.S"==><"211S£sèIðý


Explanation:

„I€Ü              # Push dictionary string "I am"
IÑ¨               # Push the divisors of the input-integer, with itself removed
©              # Store it in the register (without popping)
O             # Get the sum of these divisors
IÊi   }      # If it's not equal to the input-integer:
'€–      '#  Push dictionary string "not"
“€…íÀ‚³,ƒ«“       # Push dictionary string "a perfect number, because"
®v   }            # Loop y over the divisors:
y'+            '#  Push the divisor y, and the string "+" to the stack
\           # Discard the final "+"
'=        '# And push the string "="
®O                # Get the sum of the divisors again
D               # Duplicate it
I.S               # Compare it to the input-integer (-1 if smaller; 0 if equal; 1 if larger)
"==><"         # Push string "==><"
211S£    # Split into parts of size [2,1,1]: ["==",">","<"]
sè  # Index into it (where the -1 will wrap around to the last item)
I                 # Push the input-integer again
ðý                # Join everything on the stack by spaces
# (and output the result implicitly)


See this 05AB1E tip of mine (section How to use the dictionary?) to understand why „I€Ü is "I am", '€– is "not", and “€…íÀ‚³,ƒ«“ is "a perfect number, because".