¿Averigua si un número es feliz o no?

21

Un número feliz se define mediante el siguiente proceso. Comenzando con cualquier número entero positivo, reemplace el número por la suma de los cuadrados de sus dígitos y repita el proceso hasta que el número sea igual a 1 (donde permanecerá), o se repite sin parar en un ciclo que no incluye 1. Esos números para los cuales este proceso termina en 1 son números felices, mientras que los que no terminan en 1 son números infelices (o números tristes). Dado un número, imprima si es feliz o infeliz.

Sample Inputs
7
4
13

Sample Outputs
Happy
Unhappy
Happy

Nota: Su programa no debería tomar más de 10 segundos para cualquier número por debajo de 1,000,000,000.

fR0DDY
fuente

Respuestas:

8

Golfscript - 34 caracteres

~{0\`{48-.*+}/}9*1="UnhH"3/="appy"

Básicamente lo mismo que esto y estos .

La razón de 9 iteraciones se describe en estos comentarios (esto teóricamente devuelve valores correctos hasta aproximadamente 10^10^10^974( A001273 )).

Nabb
fuente
11

Ruby, 77 caracteres

a=gets.to_i;a=eval"#{a}".gsub /./,'+\&**2'until a<5
puts a<2?:Happy: :Unhappy
Ventero
fuente
Ok, entonces entiendo cómo funciona esto (literalmente tomando cada número, dividiéndolo y sumando el cuadrado de cada dígito), pero qué pasa con la condición de parada de (a <5) y usando (a <2) para decidir si es feliz ¿o no? No cuestiono la validez, solo la lógica.
Sr. Llama
2
Eso es lo mismo que a <= 4y a <= 1. Si el ciclo tiene un 1, entonces es feliz, y si tiene un 4, entonces no es feliz. Vea la sección de wikipedia sobre el ciclo infeliz. Entonces, una vez que el valor de aes 4 o menos, verifica si a es - el resultado de eso es su respuesta.
Casey
8

C - 115

char b[1<<30];a;main(n){for(scanf("%d",&n);b[n]^=1;n=a)for
(a=0;a+=n%10*(n%10),n/=10;);puts(n-1?"Unhappy":"Happy");}

Utiliza una matriz de 2 30 bytes (1 GB) como mapa de bits para realizar un seguimiento de los números que se han encontrado en el ciclo. En Linux, esto realmente funciona, y de manera eficiente, siempre y cuando se habilite el sobrecompromiso de memoria (que generalmente es por defecto). Con el exceso de compromiso, las páginas de la matriz se asignan y se ponen a cero bajo demanda.

Tenga en cuenta que compilar este programa en Linux usa un gigabyte de RAM.

Joey Adams
fuente
1
¿Por qué necesitarías un lugar cercano a esa cantidad de memoria para este problema?
Peter Olson el
1
@Peter: Supongo que el enfoque es (ingenuamente) capturar un ciclo para cualquier número en el rango de entrada permitido de 1 a 1,000,000,000. Pero estoy de acuerdo en que, a la luz de la teoría de los números felices, la única verificación necesaria es si se alcanza el número 4, porque ese es el único ciclo que ocurrirá.
mellamokb
Tengo curiosidad: ¿por qué compilarlo requiere tanta RAM?
Peter Taylor
1
Parece funcionar bien en Windows 7 con MSVC 10. No consume una cantidad notable de memoria durante la compilación y solo marca la matriz en el archivo de página (algo que suena mucho más seguro que la historia que vinculó sobre el exceso de memoria sugiere ;-)) .
Joey
1
Me encanta la ingenuidad de este enfoque. Y el abuso de for loops es hermoso.
dmckee
6

Haskell - 77

f 1="Happy"
f 4="Unhappy"
f n=f$sum[read[c]^2|c<-show n]
main=interact$f.read
Joey Adams
fuente
6

Golfscript, 49 43 41 40 39 caracteres

~{0\10base{.*+}/.4>}do(!"UnhH"3/="appy"

Cada número feliz converge a 1; cada número infeliz converge a un ciclo que contiene 4. Además de explotar ese hecho, esto apenas se juega al golf.

(Gracias a Ventero, de cuya solución de Ruby he robado un truco y guardo 6 caracteres).

Peter Taylor
fuente
5

eTeX, 153

\let~\def~\E#1{\else{\fi\if1#1H\else Unh\fi appy}\end}~\r#1?{\ifnum#1<5
\E#1\fi~\s#1{0?}}~\s#1{+#1*#1\s}~~{\expandafter\r\the\numexpr}\message{~\noexpand

Llamado como etex filename.tex 34*23 + 32/2 ?(incluido el signo de interrogación al final). Los espacios en la expresión no importan.

EDITAR: bajé a 123 , pero ahora la salida es dvi (si está compilada con etex) o pdf (si está compilada con pdfetex). Dado que TeX es un lenguaje tipográfico, supongo que es justo.

\def~{\expandafter\r\the\numexpr}\def\r#1?{\ifnum#1<5 \if1#1H\else
Unh\fi appy\end\fi~\s#1{0?}}\def\s#1{+#1*#1\s}~\noexpand
Bruno Le Floch
fuente
4

Python - 81 caracteres

n=input()
while n>4:n=sum((ord(c)-48)**2for c in`n`)
print("H","Unh")[n>1]+"appy"

Alguna inspiración tomada de Ventero y Peter Taylor.

Juan
fuente
2
mejor haciendo un int(c)que ord(c)-48....
st0le
4

Javascript ( 94 92 87 86)

do{n=0;for(i in a){n+=a[i]*a[i]|0}a=n+''}while(n>4);alert(['H','Unh'][n>1?1:0]+'appy')

La entrada se proporciona estableciendo a en el número deseado.

Créditos a mellamokb.

Peter Olson
fuente
Guardar 1 char:n==4?h="Unh":n==1?h="H":a=n+""}alert(h+"appy")
mellamokb
@mella Gracias. También me afeité otro carbón cambiando ||a |.
Peter Olson el
Guardar 8 caracteres: eliminar n==4?h.... Cambiar para hacer ... mientras bucle con condición while(n>4). Luego use esta declaración final en su lugar:alert(["H","Unh"][n>1?1:0]+"appy")
mellamokb
@Mella Clever, me gusta.
Peter Olson el
@Mella n necesita ser definido antes del ciclo while, estoy tratando de pensar en cómo no repetirlon=0;
Peter Olson
4

Python (98, pero demasiado desordenado para no compartir)

f=lambda n:eval({1:'"H"',4:'"Unh"'}.get(n,'f(sum(int(x)**2for x in`n`))'))
print f(input())+"appy"

Demasiado largo para ser competitivo, pero tal vez bueno para reír. Hace una evaluación "perezosa" en Python. Realmente bastante similar a la entrada de Haskell ahora que lo pienso, simplemente sin nada de encanto.


fuente
4

dc - 47 caracteres

[Unh]?[[I~d*rd0<H+]dsHxd4<h]dshx72so1=oP[appy]p

Breve descripción:

I~: Obtenga el cociente y el resto al dividir por 10
d*.: Cuadre el resto.
0<H: Si el cociente es mayor que 0, repita recursivamente.
+: Suma los valores al reducir la pila recursiva.

4<h: Repite el bit de suma de cuadrados mientras el valor es mayor que 4.

Nabb
fuente
4

Befunge, 109

Devuelve los valores correctos para 1 <= n <= 10 9 -1.

v v              <   @,,,,,"Happy"<      >"yppahnU",,,,,,,@
>&>:25*%:*\25*/:#^_$+++++++++:1-!#^_:4-!#^_10g11p
Lowjacker
fuente
3

J, 56

'Happy'"_`('Unhappy'"_)`([:$:[:+/*:@:"."0@":)@.(1&<+4&<)

Un verbo en lugar de un guión independiente ya que la pregunta es ambigua.

Uso:

   happy =: 'Happy'"_`('Unhappy'"_)`([:$:[:+/*:@:"."0@":)@.(1&<+4&<)
happy =: 'Happy'"_`('Unhappy'"_)`([:$:[:+/*:@:"."0@":)@.(1&<+4&<)
   happy"0 (7 4 13)
happy"0 (7 4 13)
Happy  
Unhappy
Happy  
Jesse Millikan
fuente
3

Scala, 145 caracteres

def d(n:Int):Int=if(n<10)n*n else d(n%10)+d(n/10)
def h(n:Int):Unit=n match{
case 1=>println("happy")
case 4=>println("unhappy")
case x=>h(d(x))}
usuario desconocido
fuente
1
¿No (n*n)sería más corto como n*n , o el espacio en blanco no es suficiente para separar una expresión if del else?
Peter Taylor
Sí, lo hice, Peter.
usuario desconocido
Aquí hay una versión recursiva de 126 bytes, sin coincidencia de patrones:def h(s: String):String=if(s=="1")"H"else if(s=="4")"Unh"else h(s.map(_.asDigit).map(a=>a*a).sum+"");print(h(readLine)+"appy")
6infinity8
@ 6infinity8: ¿Por qué no lo publicas como una nueva respuesta?
usuario desconocido el
La publicación inicial es antigua; Solo intentaba mejorar tu solución.
6infinity8
3

J (50)

'appy',~>('Unh';'H'){~=&1`$:@.(>&6)@(+/@:*:@:("."0)@":)

Estoy seguro de que es un J-er más competente de lo que puedo hacer esto aún más corto. Soy un nuevo pariente.

Nuevo y mejorado:

('Unhappy';'Happy'){~=&1`$:@.(>&6)@(+/@:*:@:("."0)@":)

Más nuevo e incluso más mejorado, gracias a ɐɔıʇǝɥʇuʎs:

(Unhappy`Happy){~=&1`$:@.(>&6)@(+/@:*:@:("."0)@":)
Gregory Higley
fuente
1
Puedes obtener un personaje al no dividir 'appy'. Creo que también puedes eliminar los paréntesis aroundd ("." 0): los adverbios se unen más que las conjunciones.
Jesse Millikan
No puedo eliminar los paréntesis ("."0). Eso produce un error de rango, pero si no divido 'Happy' y dejo el resultado en el recuadro, puedo guardar un personaje.
Gregory Higley
La razón por la que no puedo dejar de lado los paréntesis ("."0)es que las conjunciones se aplican a todo el tren de verbos anterior al que están unidas, que no es lo que quiero. Si digo +/@:("."0)@":, eso es muy diferente de lo +/@:"."0@:que es en realidad (+/@:".)"0@:.
Gregory Higley
1
Un necro masivo, pero podría guardar 4 caracteres reemplazando 'Unhappy';'Happy'con Unhappy`Happy.
Decıʇǝɥʇuʎs
@ ɐɔıʇǝɥʇuʎs Eso funciona, pero ¿dónde está documentado que puede omitir la cita de cadenas con `?
Gregory Higley
2

Python (91 caracteres)

a=lambda b:b-1and(b-4and a(sum(int(c)**2for c in`b`))or"Unh")or"H";print a(input())+"appy"
marinus
fuente
2

Lisp común 138

(format t"~Aappy~%"(do((i(read)(loop for c across(prin1-to-string i)sum(let((y(digit-char-p c)))(* y y)))))((< i 5)(if(= i 1)"H""Unh"))))

Más legible:

(format t "~Aappy~%"
        (do
          ((i (read)
              (loop for c across (prin1-to-string i)
                    sum (let
                          ((y (digit-char-p c)))
                          (* y y)))))
          ((< i 5) (if (= i 1) "H" "Unh"))))

Sería más corto simplemente devolver "Feliz" o "Infeliz" directamente desde el (do), pero podría decirse que eso no contaría como un programa completo

daniero
fuente
2

K, 43

{{$[4=d:+/a*a:"I"$'$x;unhappy;d]}/x;`happy}
tmartin
fuente
2

Jalea , 17 bytes (no competidora *)

* Desafío post-fechas de idiomas

D²SµÐLỊị“¢*X“<@Ḥ»

Pruébalo en línea!

¿Cómo?

D²SµÐLỊị“¢*X“<@Ḥ» - Main link: n
   µÐL            - loop while the accumulated unique set of results change:
D                 -   cast to a decimal list
 ²                -   square (vectorises)
  S               -   sum
                  - (yields the ultimate result, e.g. n=89 yields 58 since it enters the
                  -  "unhappy circle" at 145, loops around to 58 which would yield 145.)
      Ị           - insignificant? (abs(v)<=1 - in this case, 1 for 1, 0 otherwise)
        “¢*X“<@Ḥ» - dictionary lookup of ["Happy", "Unhappy"] (the central “ makes a list)
       ị          - index into
                  - implicit print
Jonathan Allan
fuente
1

Perl 5 - 77 Bytes

{$n=$_*$_ for split//,$u{$n}=$n;exit warn$/.'un'[$n==1].'happy'if$u{$n};redo}

$ n es el valor de entrada

Kaundur
fuente
1

05AB1E , 21 bytes

'ŽØs[SnOD5‹#}≠i„unì}™

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

Explicación:

Cada número eventualmente resultará en uno 1o 4, por lo que hacemos un bucle indefinidamente y nos detenemos tan pronto como el número esté por debajo de 5.

'ŽØ                    '# Push string "happy"
   s                    # Swap to take the (implicit) input
    [       }           # Loop indefinitely
     S                  #  Convert the integer to a list of digits
      n                 #  Square each
       O                #  Take the sum
        D5‹#            #  If this sum is smaller than 5: stop the infinite loop
             i    }    # If the result after the loop is NOT 1:
               unì     #  Prepend string "un" to string "happy"
                       # Convert the string to titlecase (and output implicitly)

Ver este consejo 05AB1E mío (sección Cómo usar el diccionario? ) Para entender por qué 'ŽØes "happy".

Kevin Cruijssen
fuente
0

C ++ 135, 2 líneas

#include<iostream>
int n,i,j;int main(){for(std::cin>>n;n>1;n=++j&999?n*n+i:0)for(i=0;n/10;n/=10)i+=n%10*(n%10);std::cout<<(n?"H":"Unh")<<"appy";}

Esta es una versión modificada de la que hice aquí:

/programming/3543811/code-golf-happy-primes/3545056#3545056

Scott Logan
fuente
¿Qué es el &999hacer? ¿Y cómo funciona si jes un valor basura?
David dice que reinstale a Mónica el
@ Dgrin91, escribí esto hace 3 años, así que no recuerdo exactamente cómo funciona. Creo que el & 999 hace la declaración if(j==999){n = 0;}else{n=n*n +i;}, j no debería ser un valor basura, los globales son cero inicializados.
Scott Logan
0

Sí, este desafío tiene tres años; sí, ya tiene una respuesta ganadora; pero como estaba aburrido e hice esto para otro desafío, pensé que podría ponerlo aquí. Sorpresa sorpresa, es larga ... y en ...

Java - 280 264 bytes

import java.util.*;class H{public static void main(String[]a){int n=Integer.parseInt(new Scanner(System.in).nextLine()),t;while((t=h(n))/10!=0)n=t;System.out.print(t==1?"":"");}static int h(int n){if(n/10==0)return n*n;else return(int)Math.pow(n%10,2)+h(n/10);}}

Sin golf:

import java.util.*;

class H {

    public static void main(String[] a) {
        int n = Integer.parseInt(new Scanner(System.in).nextLine()), t;
        while ((t = h(n)) / 10 != 0) {
            n = t;
        }
        System.out.print(t == 1 ? "" : "");
    }

    static int h(int n) {
        if (n / 10 == 0) {
            return n * n;
        } else {
            return (int) Math.pow(n % 10, 2) + h(n / 10);
        }
    }
}
Rodolfo Dias
fuente
0

C # 94 bytes

int d(int n)=>n<10?n*n:(d(n%10)+d(n/10));string h(int n)=>n==1?"happy":n==4?"unhappy":h(d(n));

Para cualquier número dado (como int), h()devolverá el valor correcto. Puede probar el código en .NetFiddle .

Felicitaciones al usuario desconocido para el algoritmo original .

aloisdg dice Reinstate Monica
fuente
0

Clojure, 107 97 bytes

Actualización: se eliminó el letenlace innecesario .

#(loop[v %](case v 1"Happy"4"Unhappy"(recur(apply +(for[i(for[c(str v)](-(int c)48))](* i i))))))

Original:

#(loop[v %](let[r(apply +(for[i(for[c(str v)](-(int c)48))](* i i)))](case r 1"Happy"4"Unhappy"(recur r))))

Primera vez que usa un anidado for: o

NikoNyrh
fuente
0

R, 117 91 bytes

-16 bytes gracias a Giuseppe

a=scan();while(!a%in%c(1,4))a=sum((a%/%10^(0:nchar(a))%%10)^2);`if`(a-1,'unhappy','happy')
Andrew Haynes
fuente
1
Use en strtoilugar de as.numericy en pastelugar de as.character, pero hay un enfoque más corto para obtener los dígitos . Si usa `if`(a-1,"unhappy","happy")en su lugar eso debería guardar otro byte. Finalmente, puede hacer esto anónimo para ahorrar unos pocos bytes más.
Giuseppe
-1

C: 1092 caracteres

#include <iostream>
using namespace std ;
int main ()
{
    int m , a[25] , kan=0 , y , z=0  , n , o=0, s , k=0 , e[25]  ;
    do {
m :
        for ( int j=1 ; j <10000 ; j++ )
        {   
n:
            for (int i=0 ; j!=0 ; i++ )
            {
                a[i]=j%10 ;
                j/=10 ;
                kan++ ;
            }
            for ( int i=0 ; i<kan ; i++ )
            {
                y=a[i]*a[i] ;
                z+=y ;
            }
            k+=1 ;
            if (z==1)
            {
              cout<<j<<endl;
               o++ ;
            }

            else 
            {   
                 for (int f=0 ; f<k ; f++ )
                 {
                     e[f]=z ;
                 }
                 for ( int f=0 ; f=k-1 ; f++ )
                 {
                     for ( int p=f+1 ; p <k-1 ; p++ )
                     {
                         if(e[f]=e[p])
                             goto m ;
                         else { j=z ; goto n ; } 
                     }
                 }
            }
        }
    }while(o!=100) ;
    return 0 ;
}
jannat
fuente
66
Bienvenido a Programming Puzzles & Code Golf, @jannat. Tenga en cuenta que el código de golf es un desafío de escribir el código más corto posible. Eso significa que aquí escribimos código sin sangría y casi ilegible y forzamos los límites de la sintaxis del lenguaje para acortar nuestros códigos lo más posible.
manatwork
xkcd.com/292
aditsu