Descobrir se um número está feliz ou não?

21

Um número feliz é definido pelo seguinte processo. Começando com qualquer número inteiro positivo, substitua o número pela soma dos quadrados de seus dígitos e repita o processo até que o número seja igual a 1 (onde permanecerá) ou faça um loop infinito em um ciclo que não inclui 1. Esses números para os quais esse processo termina em 1, são números felizes, enquanto aqueles que não terminam em 1 são números infelizes (ou tristes). Dada uma impressão numérica, seja feliz ou infeliz.

Sample Inputs
7
4
13

Sample Outputs
Happy
Unhappy
Happy

Nota: Seu programa não deve levar mais de 10 segundos para qualquer número abaixo de 1.000.000.000.

fR0DDY
fonte

Respostas:

8

Golfscript - 34 caracteres

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

Basicamente o mesmo que este e estes .

O motivo de 9 iterações é descrito nesses comentários (isso teoricamente retorna valores corretos até cerca de 10^10^10^974( A001273 )).

Nabb
fonte
11

Ruby, 77 caracteres

a=gets.to_i;a=eval"#{a}".gsub /./,'+\&**2'until a<5
puts a<2?:Happy: :Unhappy
Ventero
fonte
Ok, então eu meio que entendo como isso funciona (literalmente pegando cada número, dividindo-o e adicionando o quadrado de cada dígito), mas qual é a condição de parada de (a <5) e usando (a <2) para decidir se está feliz ou não? Não questiono a validade, apenas a lógica.
Mr. Llama
2
É o mesmo que a <= 4e a <= 1. Se o ciclo tiver 1 nele, ele será feliz e, se houver 4, não será feliz. Veja a seção da Wikipedia sobre o ciclo infeliz. Assim, quando o valor de afor 4 ou menos, ele verifica se a é - o resultado é a sua resposta.
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");}

Isso usa uma matriz de 2 30 bytes (1 GB) como um bitmap para acompanhar quais números foram encontrados no ciclo. No Linux, isso realmente funciona, e com eficiência, desde que a confirmação excessiva de memória esteja ativada (o que geralmente ocorre por padrão). Com o comprometimento excessivo, as páginas da matriz são alocadas e zeradas sob demanda.

Observe que a compilação deste programa no Linux usa um gigabyte de RAM.

Joey Adams
fonte
11
Por que você precisaria de algo próximo a essa quantidade de memória para esse problema?
27611 Peter Olson
11
@ Peter: Suponho que a abordagem seja (ingenuamente) capturar um ciclo para qualquer número na faixa de entrada permitida de 1 a 1.000.000.000. Mas concordo que, à luz da teoria dos números felizes, a única verificação necessária é se o número 4 for alcançado, porque esse é o único ciclo que jamais ocorrerá.
precisa saber é o seguinte
Estou curioso: por que a compilação requer tanta memória RAM?
Peter Taylor
11
Parece funcionar bem no Windows 7 com o MSVC 10. Não consome nenhuma quantidade notável de memória durante a compilação e marca apenas a matriz no arquivo de paginação (algo que parece muito mais seguro do que a história que você vinculou sobre o supercomprometimento de memória sugere ;-)) .
JoeyAbr
11
Eu amo a ingenuidade dessa abordagem. E o abuso de loops é lindo.
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
fonte
6

Golfscript, 49 43 41 40 39 caracteres

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

Todo número feliz converge para 1; todo número infeliz converge para um ciclo contendo 4. Além de explorar esse fato, isso quase não é praticado.

(Graças a Ventero, de cuja solução Ruby, fiz um truque e salvei 6 caracteres).

Peter Taylor
fonte
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

Chamado como etex filename.tex 34*23 + 32/2 ?(incluindo o ponto de interrogação no final). Os espaços na expressão não importam.

Edição: Eu desceu para 123 , mas agora a saída é dvi (se compilado com etex) ou pdf (se compilado com pdfetex). Como o TeX é uma linguagem tipográfica, acho que é 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
fonte
4

Python - 81 caracteres

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

Alguma inspiração tirada de Ventero e Peter Taylor.

Juan
fonte
2
melhor fora de fazer um 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')

A entrada é fornecida configurando a para o número desejado.

Créditos para mellamokb.

Peter Olson
fonte
Salve 1 caractere:n==4?h="Unh":n==1?h="H":a=n+""}alert(h+"appy")
mellamokb
@mella Obrigado. Também raspei outro caractere ao mudar ||para |.
26811 Peter Olson
Economize 8 caracteres: Remova n==4?h.... Mude para fazer ... enquanto loop com condição while(n>4). Em seguida, use esta declaração final em vez disso:alert(["H","Unh"][n>1?1:0]+"appy")
mellamokb
@Mella Clever, eu gosto.
26611 Peter Olson
@Mella n precisa ser definido antes do loop while, eu estou tentando pensar em como não repetirn=0;
Peter Olson
4

Python (98, mas muito bagunçado para não compartilhar)

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

Caminho, tempo demais para ser competitivo, mas talvez seja bom para rir. Faz avaliação "preguiçosa" em Python. Muito parecido com a entrada de Haskell agora que penso nisso, apenas sem nenhum charme.


fonte
4

dc - 47 caracteres

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

Descrição breve:

I~: Obtenha o quociente e o restante ao dividir por 10
d*.: calcule o quadrado do restante.
0<H: Se o quociente for maior que 0, repita recursivamente.
+: Soma os valores ao reduzir a pilha recursiva.

4<h: Repita o bit da soma dos quadrados enquanto o valor for maior que 4.

Nabb
fonte
4

Befunge, 109

Retorna os valores corretos para 1 <= n <= 10 9 -1.

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

J, 56

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

Um verbo em vez de um script independente, pois a pergunta é ambígua.

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
fonte
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))}
Usuário desconhecido
fonte
11
Não (n*n)seria mais curto como n*n , ou o espaço em branco não é suficiente para separar uma expressão if do else?
Peter Taylor
Sim, eu fiz isso, Peter.
usuário desconhecido
Aqui é um 126 bytes versão cauda-recursivo, sem correspondência de padrões: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 que você não o publica como uma nova resposta?
usuário desconhecido
A postagem inicial é antiga; Eu só estava tentando melhorar sua solução.
6infinity8
3

J (50)

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

Tenho certeza de que um J-er mais competente do que posso tornar isso ainda mais curto. Eu sou um novato relativo.

Novo e melhorado:

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

Mais novo e ainda mais aprimorado, graças ao ɐɔıʇǝɥʇuʎs:

(Unhappy`Happy){~=&1`$:@.(>&6)@(+/@:*:@:("."0)@":)
Gregory Higley
fonte
11
Você pode obter um personagem não dividindo 'appy'. Eu acho que você também pode remover os parênteses aroundd ("." 0) - advérbios se ligam mais que as conjunções.
precisa
Não consigo remover os parênteses ("."0). Isso produz um erro de classificação, mas se eu não dividir 'Feliz' e deixar o resultado em caixa, posso salvar um personagem.
precisa
A razão pela qual não posso deixar de fora os parênteses ("."0)é que as conjunções se aplicam a todo o conjunto anterior de verbos aos quais estão ligados, o que não é o que eu quero. Se eu digo +/@:("."0)@":, isso é muito diferente do +/@:"."0@:que é realmente (+/@:".)"0@:.
Gregory Higley
11
Um necro enorme, mas você pode salvar 4 caracteres substituindo 'Unhappy';'Happy'por Unhappy`Happy.
ɐɔıʇǝɥʇuʎs
@ ɐɔıʇǝɥʇuʎs Isso funciona, mas onde está documentado que você pode pular a citação de strings com `?
precisa
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
fonte
2

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

Mais legível:

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

Seria mais curto retornar apenas "Feliz" ou "Infeliz" (do), mas sem dúvida isso não conta como um programa inteiro

daniero
fonte
2

K, 43

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

Gelatina , 17 bytes (não concorrente *)

* Desafio pós-data do idioma

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

Experimente online!

Quão?

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

Perl 5 - 77 bytes

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

$ n é o valor de entrada

Kaundur
fonte
1

05AB1E , 21 bytes

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

Experimente online ou verifique os 100 primeiros casos de teste .

Explicação:

Cada número acabará resultando em um 1ou 4, portanto, fazemos um loop indefinidamente e paramos assim que o número estiver abaixo 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)

Veja esta dica 05AB1E meu (seção Como usar o dicionário? ) Para entender por que 'ŽØé "happy".

Kevin Cruijssen
fonte
0

C ++ 135, 2 linhas

#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 é uma versão modificada da que eu fiz aqui:

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

Scott Logan
fonte
Qual é o &999fazer? E como funciona se jé um valor de lixo?
David diz Reinstate Monica
@ Dgrin91, escrevi isso há 3 anos, então não me lembro exatamente como isso funciona. Eu acho que o & 999 faz a declaração if(j==999){n = 0;}else{n=n*n +i;}, j não deve ser um valor de lixo, os globais são zero inicializados.
perfil completo de Scott Logan
0

Sim, esse desafio tem três anos; Sim, ele já tem uma resposta vencedora; mas como eu estava entediado e fiz isso por outro desafio, pensei em colocá-lo aqui. Surpresa surpresa, é longa - e ...

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

Ungolfed:

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

Bytes C # 94

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 qualquer número (as int), h()retornará o valor correto. Você pode tentar o código no .NetFiddle .

Parabéns ao usuário desconhecido para o algoritmo original .

aloisdg diz Restabelecer Monica
fonte
0

Clojure, 107 97 bytes

Atualização: letligação desnecessária removida .

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

Primeira vez usando um aninhado for: o

NikoNyrh
fonte
0

R, 117 91 bytes

-16 bytes graças 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
fonte
11
Use em strtoivez de as.numerice em pastevez de as.character, mas existe uma abordagem mais curta para obter os dígitos . Se você usar, `if`(a-1,"unhappy","happy")isso deve salvar outro byte. Por fim, você pode tornar esse anonimato para economizar mais alguns bytes.
21717 Giuseppe
0

Python 2 , 71 bytes

f=lambda n:n>4and f(sum(int(d)**2for d in`n`))or("H","Unh")[n>1]+"appy"

Experimente online!

... ou, para a mesma contagem de bytes:

f=lambda n:n>4and f(eval('**2+'.join(`n*10`)))or("H","Unh")[n>1]+"appy"

Experimente online!

FlipTack
fonte
-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
fonte
6
Bem-vindo à Programação de quebra-cabeças e código de golfe, @jannat. Observe que o código de golfe é um desafio de escrever o código mais curto possível. Isso significa que, aqui , escrevemos códigos não indentados e quase ilegíveis e forçamos os limites da sintaxe da linguagem a reduzir nossos códigos o máximo possível.
Manatwork
xkcd.com/292
aditsu 11/03/2013