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.

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


11

Ruby, 77 caracteres

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

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.


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

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


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

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.


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.


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.


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.


4

Befunge, 109

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

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

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  

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

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

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"

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


2

K, 43

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

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

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


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


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


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


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


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

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



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

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

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.