¿Soy perfecto (número)?


26

Este es mi primer desafío!

Fondo

El número perfecto es un entero positivo, que es igual a la suma de todos sus divisores, excepto a sí mismo.
Entonces 6es un número perfecto, ya que 1 + 2 + 3 = 6.
Por otro lado 12no lo es, porque 1 + 2 + 3 + 4 + 6 = 16 != 12.

Tarea

Su tarea es simple, escriba un programa que, por supuesto n, imprima uno de estos mensajes:

Soy un número perfecto, porque d1 + d2 + ... + dm = s == n
no soy un número perfecto, porqued1 + d2 + ... + dm = s [<>] n

¿Dónde
d1, ... dmestán todos los divisores de nexcepto n?
ses la suma de todos los divisores d1, ..., dm(de nuevo, sin n).
[<>]es <(if s < n) o >(if s > n).

Ejemplos

Por nser 6: "Soy un número perfecto, porque 1 + 2 + 3 = 6 == 6"
Por nser 12: "No soy un número perfecto, porque 1 + 2 + 3 + 4 + 6 = 16> 12"
Por nser 13: "No soy un número perfecto, porque 1 = 1 <13"

Reglas

  • nno es más grande que el estándar de tu idioma int.
  • Puede leer ndesde la entrada estándar, desde argumentos de línea de comandos o desde un archivo.
  • El mensaje de salida debe imprimirse en la salida estándar y no pueden aparecer caracteres adicionales en la salida (puede tener espacios en blanco al final o nueva línea)
  • No puede usar ninguna función incorporada o de biblioteca que resuelva la tarea (o su parte principal) por usted. No GetDivisors()o algo así.
  • Se aplican todas las demás lagunas estándar .

Ganador

Este es el código más corto en bytes gana!


@orlp No es así, edité el desafío, gracias por eso.
Zereges

77
¿Por qué usas =y ==en la misma ecuación? Eso no tiene sentido. Debería ser de la d1 + d2 + ... + dm = s = nOMI.
orlp

¿Podría dar algún ejemplo de entrada y salida, por ejemplo, con las entradas 6 y 12?
Zgarb

14
@ Zereges Eso no tiene sentido. No hay nada asignado. Solo comparado.
orlp

1
@orlp Está destinado.
Zereges

Respuestas:


4

Pyth, 81 bytes

jd[+WK-QsJf!%QTStQ"I am"" not""a perfect number, because"j" + "J\=sJ@c3"==<>"._KQ

Pruébelo en línea: Demostración o conjunto de pruebas

Explicación:

                                 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

9

Java, 255 270 bytes (Todavía FF en 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);}}

Y una versión más legible:

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

Anteriormente no funcionaba para números impares, así que tuve que modificar algunas cosas. Al menos tuve suerte con el recuento de bytes nuevamente. :)


¿l == trabajaré sobre 255?
dwana

Sé si arruina tu conteo de bytes, pero podrías salvar a un personaje reemplazando las últimas tres (de cuatro) apariciones de a [0] con una 'Cadena b' y usar 'b' en su lugar
Craig

6

R, 158 163 157 153 143 141 bytes

Todavía hay espacio para jugar al golf, creo.
Editar: reemplazado if(b<n)'<'else if(b>n)'>'else'=='por c('<'[b<n],'>'[b>n],'=='[b==n]). El paste(...)se reemplaza con un rbind(...)[-1]. Gracias @plannapus por un par de bytes más.

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)

Sin golf

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
)

Prueba de funcionamiento

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

Debe haber una +señal entre los divisores.
Zereges

@Zereges Acabo de notar eso y lo arreglaré en breve
MickyT

¡+1 por el rbindtruco brillante ! Puede guardar 2 bytes adicionales si asigna 2:n-1a una variable, por ejemplo a: which(!n%%1:(n-1)) se convierte así a[!n%%a]. (El código completo es entonces 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

@plannapus Gracias, yo también estaba muy satisfecho con eso.
MickyT

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)

Ejemplos:

$ 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

¡Gracias a xnor por guardar 13 bytes!


44
'=<>'[cmp(b,d)]- ¡Únete a la revolución!
orlp

¡Excelente, gracias! Oh, espera ... :)
Celeo

1
@Celeo Se me ocurrió una solución similar. Puedes escribir b%i<1para b%i==0. Para ['not ',''][int(d==b)], no necesita el int, porque Python se convertirá automáticamente. Además, puede usar la multiplicación de cadenas "not "*(d!=b).
xnor

@xnor gracias por las sugerencias!
Celeo

1
@Celeo Puede ajustar la sugerencia de orlp para que funcione como "=<>="[cmp(b,d)%3::3].
xnor

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

Sin golf:

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

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*

A modo de comparación, la impresión de un solo =se puede lograr en 83 bytes.

Pruébelo en línea en el intérprete de CJam .

Cómo funciona

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

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"

Con saltos de línea:

$a=<>;
$_=join' + ',grep{$a%$_==0}1..$a-1;
$s=eval;
print"I am ".($s==$a?'':'not ')."a perfect number because $_ = $s ".(('==','>','<')[$s<=>$a])." $a"

He tenido un empuje sobre esta y puede ahorrar 10 bytes mediante la eliminación de los parens exteriores alrededor de la 'not 'y '==','>','<'declaraciones y se cambia de .a ,(ya que nada se añade cuando printing una lista). También mover sus tareas en parens la primera vez que se usan ahorra un par, y si cambia la lógica ligeramente hacia grep$a%_<1,1..($a=<>)-1y $a!=($s=eval)&&'not 'hay que rallar un poco más! ¡Espero que todo tenga sentido!
Dom Hastings

2

Lua, 244 231 bytes

Golfizado:

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

Sin golf:

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

2

JavaScript (ES6), 146

Usando cadenas de plantillas, funciona en Firefox y en la última versión de 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)


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

Guardado otros 6 bytes :)

Gracias a los consejos para jugar al golf en Ruby


El comando de impresión todavía me molesta ... ¿Y necesito encontrar una manera de acortar el ternario de la declaración if? necesita una cláusula else que no puedo proporcionar y solo acepta una llamada por caso
Yuri Kazakov

solo queda una declaración impresa :)
Yuri Kazakov

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

1

Hassium , 285 bytes

Descargo de responsabilidad: funciona solo con la última versión de Hassium debido a problemas con los argumentos de la línea de comandos.

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

Versión más legible:

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
1. Parece que no puedo convencer a Hassium para que lea mis argumentos de la línea de comandos. Si ejecuto mono src/Hassium/bin/Debug/Hassium.exe t.hs 6, dice System.ArgumentException: The file 6 does not exist.. 2. Esto no funciona con esta versión , que es la última confirmación antes de que se publicara este desafío. Agregue un descargo de responsabilidad a su respuesta que indique que su envío no es competitivo.
Dennis

Lo probé en Windows (construido usando MVS2015) y obtuve el mismo error.
Zereges

Este es un problema que se actualizó literalmente hace 15 minutos. Clona el Hassium y compila de nuevo. Lo siento mucho, ya que me encontré exactamente con el mismo problema.
Jacob Misirian

1
Funciona bien con la última versión. Ahora, si pudiera agregar el descargo de responsabilidad, me complacerá eliminar mi voto negativo. (Por cierto, puede enviarme un ping agregando @Dennisa su comentario. De lo contrario, no recibiré una notificación de su respuesta.)
Dennis

@Dennis Lo agregué. Gracias por su notificación :)
Jacob Misirian

1

MATLAB, 238

Nunca será el más corto de todos los idiomas, pero aquí está mi intento con 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)])

Y esto está en una forma ligeramente más legible:

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

Me las arreglé para guardar 2 bytes más al no usar una función. En su lugar, ejecuta la línea de código y solicita el número como entrada. Una vez ejecutado, muestra la salida al final.


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]
  } $_"

(El recuento ignora las nuevas líneas y las sangrías, porque no son necesarias)

@des la matriz que contiene los divisores.
$scontiene la suma de los divisores.
$ces el valor de la comparación entre la entrada y la suma de los divisores.
(De hecho, $ces uno de -1, 0, 1, pero es realmente uno de Order::Less, Order::Sameo Order::More)

En 'not 'x?$c, ?$cen este caso es efectivamente el mismo que abs $c, y xes el operador de repetición de cadena.

«> == <»es la abreviatura de ( '>', '==', '<' ).
Como $ctiene uno de ellos -1,0,1, tenemos que subirlo uno para poder usarlo para indexarlo en una lista.

Técnicamente, esto funcionará para números muy superiores a 2⁶⁴, pero requiere una cantidad de tiempo excesiva para los números superiores a 2¹⁶.


0

Pyth, 84 bytes

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

Respuesta no válida, porque me niego a implementar =y ==en la misma ecuación.


2
+1 por negarse a "implementar = y == en la misma ecuación".
theonlygusti

0

Rubí, 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}"}

Prueba

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

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

Versión sin golf:

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

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"

Algunos de los trucos PoSh comunes y no tan comunes;

  • Crea la suma, luego evalúala con iex
  • Compare para indexar la matriz gt, lt, eq
  • !! $ d se evaluará como verdadero == 1 para $ d = 1 o -1, y falso == 0 para $ d = 0

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

Se desperdiciaron algunos bytes para corregir esto como entrada 1. No estoy seguro de si eso se espera.

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

0

05AB1E , 58 bytes

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

Pruébelo en línea o verifique todos los casos de prueba .

Explicación:

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)

Vea esta sugerencia mía 05AB1E (sección ¿Cómo usar el diccionario? ) Para comprender por qué „I€Ües "I am", '€–es "not"y “€…íÀ‚³,ƒ«“es "a perfect number, because".

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.