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

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


11

Ruby, 77 caracteres

a=gets.to_i;a=eval"#{a}".gsub /./,'+\&**2'until a<5
puts a<2?:Happy: :Unhappy

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.


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

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


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

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.


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.


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.


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.


4

Befunge, 109

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

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

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  

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

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

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"

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



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

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


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


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


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


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


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

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

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

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.