Am I perfect (number)?

26

2

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.

Task

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!

Zereges

Posted 2015-09-15T21:39:15.693

Reputation: 1 165

@orlp It is not, I edited the challenge, thanks for that. – Zereges – 2015-09-15T21:57:15.903

7Why do you use = and == in the same equation? That makes no sense. It should be d1 + d2 + ... + dm = s = n IMO. – orlp – 2015-09-15T22:06:16.053

Could you give some example input and output, for example with inputs 6 and 12? – Zgarb – 2015-09-15T22:08:43.290

@orlp first = is assignment. Second == is comparism. – Zereges – 2015-09-15T22:10:58.500

14@Zereges That's nonsensical. There is nothing being assigned. Only compared. – orlp – 2015-09-15T22:12:53.110

1@orlp It is intended. – Zereges – 2015-09-15T22:24:18.307

@flawr Related, but closed as unclear. – Zereges – 2015-09-16T21:38:48.757

What is being assigned? I don't see any variables. I only see constants, and you can't assign anything to a constant. – corsiKa – 2015-09-16T22:43:19.610

@corsiKa Ok, so I'll tell it in other way. First = is elementary school's, it means, computing the value of sum of divisors. The second == is to show off, that the value is the same. – Zereges – 2015-09-16T23:03:55.313

Does it matter if there are extra spaces in the list of numbers, e.g. I am a perfect number, because<space><space>1<space>+<space><space>2 +<space><space>4<space>+<space><space>7<space>+<space>14 == 28 – Tom Carpenter – 2015-09-25T16:07:31.050

@TomCarpenter Yes, it matters. You can have trailing whitespace/newline, but no whitespaces in the middle of output. – Zereges – 2015-09-25T17:33:33.797

I figured as much. Fortunately I found a way to combat it in my MATLAB code after I left the comment. :) – Tom Carpenter – 2015-09-25T17:37:03.537

I wrote a four byte answer... and then I realized how the output is supposed to work. – Unrelated String – 2019-03-06T07:04:50.540

Answers

4

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

Jakube

Posted 2015-09-15T21:39:15.693

Reputation: 21 462

9

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);}}

And a more readable version:

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. :)

TNT

Posted 2015-09-15T21:39:15.693

Reputation: 2 442

will l == i work over 255 ? – dwana – 2015-09-16T12:43:11.980

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 – Craig – 2015-09-17T07:39:25.933

6

R, 158 163 157 153 143 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: 
Read 1 item
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: 
Read 1 item
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: 
Read 1 item
I am not a perfect number, because 1 = 1 < 13
> 

MickyT

Posted 2015-09-15T21:39:15.693

Reputation: 11 735

There should be + sign in between divisors. – Zereges – 2015-09-15T22:43:42.863

@Zereges I've just noticed that and will fix shortly – MickyT – 2015-09-15T22:44:32.797

+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)) – plannapus – 2015-09-18T09:07:11.097

@plannapus Thanks, I was really pleased with that myself. – MickyT – 2015-09-18T18:48:15.720

5

Python 2, 183 173 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!

Celeo

Posted 2015-09-15T21:39:15.693

Reputation: 520

4'=<>'[cmp(b,d)] - join the revolution! – orlp – 2015-09-15T23:42:02.330

Excellent, thanks! Oh, wait ... :) – Celeo – 2015-09-15T23:54:15.013

1@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 – 2015-09-16T03:59:03.603

@xnor thanks for the suggestions! – Celeo – 2015-09-16T15:36:37.543

1@Celeo You can adjust orlp's suggestion to work as "=<>="[cmp(b,d)%3::3]. – xnor – 2015-09-19T00:57:01.803

Clever, @xnor, thanks! – Celeo – 2015-09-21T15:27:54.190

4

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")

Alex A.

Posted 2015-09-15T21:39:15.693

Reputation: 23 761

4

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.

Dennis

Posted 2015-09-15T21:39:15.693

Reputation: 196 637

2

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))

Nikolai97

Posted 2015-09-15T21:39:15.693

Reputation: 653

2

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"

faubi

Posted 2015-09-15T21:39:15.693

Reputation: 2 599

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! – Dom Hastings – 2015-09-21T23:20:52.710

2

Ruby, 174 160 155 136 134 128 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

Yuri Kazakov

Posted 2015-09-15T21:39:15.693

Reputation: 21

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 – Yuri Kazakov – 2015-09-16T20:17:17.903

only one print statement is left :) – Yuri Kazakov – 2015-09-17T10:30:09.020

2

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)

edc65

Posted 2015-09-15T21:39:15.693

Reputation: 31 086

1

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);}}

Yitz

Posted 2015-09-15T21:39:15.693

Reputation: 21

1

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);
    }

}

Jacob Misirian

Posted 2015-09-15T21:39:15.693

Reputation: 737

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.
  • – Dennis – 2015-09-16T21:29:15.563

    I tried it on Windows (built using MVS2015) and got same error. – Zereges – 2015-09-16T21:45:17.163

    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. – Jacob Misirian – 2015-09-16T22:29:16.003

    1It 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.) – Dennis – 2015-09-16T22:47:31.193

    @Dennis I added it in. Thank you for your notification :) – Jacob Misirian – 2015-09-17T01:23:42.777

    1

    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.

    Tom Carpenter

    Posted 2015-09-15T21:39:15.693

    Reputation: 3 990

    1

    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¹⁶.

    Brad Gilbert b2gills

    Posted 2015-09-15T21:39:15.693

    Reputation: 12 713

    0

    05AB1E, 58 bytes

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

    Try it online or verify all test cases.

    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".

    Kevin Cruijssen

    Posted 2015-09-15T21:39:15.693

    Reputation: 67 575

    0

    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.

    orlp

    Posted 2015-09-15T21:39:15.693

    Reputation: 37 067

    2+1 for refusing to "implement = and == in the same equation." – theonlygusti – 2015-09-16T20:35:57.733

    0

    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
    

    Vasu Adari

    Posted 2015-09-15T21:39:15.693

    Reputation: 941

    0

    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)))
    

    Soupy

    Posted 2015-09-15T21:39:15.693

    Reputation: 151

    0

    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

    tomkandy

    Posted 2015-09-15T21:39:15.693

    Reputation: 167

    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?"<":">"
    }
    

    Cabbie407

    Posted 2015-09-15T21:39:15.693

    Reputation: 1 158