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