Scopri se un numero è felice o no?


21

Un numero felice è definito dal seguente processo. Cominciando con qualsiasi numero intero positivo, sostituisci il numero con la somma dei quadrati delle sue cifre e ripeti il ​​processo fino a quando il numero è uguale a 1 (dove rimarrà), oppure si avvolge all'infinito in un ciclo che non include 1. Quei numeri per cui questo processo termina in 1 sono numeri felici, mentre quelli che non terminano in 1 sono numeri infelici (o numeri tristi). Dato un numero stampa se è felice o infelice.

Sample Inputs
7
4
13

Sample Outputs
Happy
Unhappy
Happy

Nota: il programma non dovrebbe richiedere più di 10 secondi per un numero inferiore a 1.000.000.000.

Risposte:


8

Golfscript - 34 caratteri

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

Fondamentalmente lo stesso di questo e questi .

Il motivo di 9 iterazioni è descritto in questi commenti (ciò restituisce teoricamente valori corretti fino a circa 10^10^10^974( A001273 )).


11

Rubino, 77 caratteri

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

Ok, quindi capisco come funziona (prendendo letteralmente ogni numero, dividendolo e aggiungendo il quadrato di ogni cifra), ma cosa c'è con la condizione di stop di (a <5) e usando (a <2) per decidere se è felice o no? Non metto in dubbio la validità, solo la logica.
Mr. Llama,

2
Questo è lo stesso di a <= 4e a <= 1. Se il ciclo ha un 1 in esso, allora è felice, e se ha un 4 in esso, allora non è felice. Vedi la sezione di Wikipedia sul ciclo infelice. Quindi, una volta che il valore di aè 4 o meno, controlla se è - il risultato è la tua risposta.
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");}

Questo utilizza un array da 2 30 byte (1 GB) come bitmap per tenere traccia di quali numeri sono stati rilevati nel ciclo. Su Linux, questo funziona davvero, e in modo efficiente, a condizione che sia abilitato il sovraccarico di memoria (che di solito è di default). Con il commit eccessivo, le pagine dell'array vengono allocate e azzerate su richiesta.

Nota che la compilazione di questo programma su Linux utilizza un gigabyte di RAM.


1
Perché dovresti aver bisogno di un posto vicino a quella quantità di memoria per questo problema?
Peter Olson,

1
@Peter: suppongo che l'approccio sia quello di catturare (ingenuamente) un ciclo per qualsiasi numero nell'intervallo di input consentito da 1 a 1.000.000.000. Ma sono d'accordo sul fatto che alla luce della felice teoria dei numeri, l'unico controllo necessario è se il numero 4 viene raggiunto, perché è l'unico ciclo che si verificherà mai.
mellamokb,

Sono curioso: perché la compilazione richiede tanta RAM?
Peter Taylor,

1
Sembra funzionare bene su Windows 7 con MSVC 10. Non consuma alcuna notevole quantità di memoria durante la compilazione e segna solo l'array nel file di paging (qualcosa che sembra molto più sicuro della storia che hai collegato a proposito di overcommitting di memoria ;-)) .
Joey,

1
Adoro l'ingenuità di questo approccio. E l'abuso di per i loop è bellissimo.
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 caratteri

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

Ogni numero felice converge in 1; ogni numero infelice converge in un ciclo contenente 4. Oltre a sfruttare questo fatto, questo è a malapena a golf.

(Grazie a Ventero, dalla cui soluzione Ruby ho scritto un trucco e ho salvato 6 caratteri).


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

Chiamato come etex filename.tex 34*23 + 32/2 ?(incluso il punto interrogativo alla fine). Gli spazi nell'espressione non contano.

EDIT: sono arrivato a 123 , ma ora l'output è dvi (se compilato con etex) o pdf (se compilato con pdfetex). Dato che TeX è un linguaggio tipografico, credo sia giusto.

\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 caratteri

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

Qualche ispirazione presa da Ventero e Peter Taylor.


2
meglio fare un int(c)di 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')

L'immissione viene fornita impostando a sul numero desiderato.

Crediti a mellamokb.


Salva 1 carattere:n==4?h="Unh":n==1?h="H":a=n+""}alert(h+"appy")
mellamokb il

@mella Grazie. Ho anche rasato un altro personaggio cambiando ||in |.
Peter Olson,

Salva 8 caratteri: rimuovi n==4?h.... Cambia per fare ... mentre loop con condizione while(n>4). Quindi usa invece questa frase finale:alert(["H","Unh"][n>1?1:0]+"appy")
mellamokb

@Mella Clever, mi piace.
Peter Olson,

@Mella n deve essere definita prima del ciclo while, sto cercando di pensare a come non ripeteren=0;
Peter Olson,

4

Python (98, ma troppo incasinato per non condividere)

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

Modo, troppo tempo per essere competitivo, ma forse buono per una risata. Fa una valutazione "pigra" in Python. Davvero abbastanza simile alla voce di Haskell ora che ci penso, solo senza il fascino.


4

dc - 47 caratteri

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

Breve descrizione:

I~: Ottiene il quoziente e il resto quando si divide per 10
d*.: quadrare il resto.
0<H: Se il quoziente è maggiore di 0, ripetere in modo ricorsivo.
+: Somma i valori quando si riduce la pila ricorsiva.

4<h: Ripete il bit della somma dei quadrati mentre il valore è maggiore di 4.


4

Befunge, 109

Restituisce i valori corretti per 1 <= n <= 10 9 -1.

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

3

J, 56

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

Un verbo piuttosto che uno script autonomo poiché la domanda è 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 caratteri

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
Non (n*n)sarebbe più breve come n*n , o lo spazio bianco non è sufficiente per separare un'espressione if da else?
Peter Taylor,

Sì, l'ho fatto, Peter.
utente sconosciuto

Ecco una versione ricorsiva della coda di 126 byte, senza corrispondenza del modello: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: Perché non lo pubblichi come una nuova risposta?
utente sconosciuto

Il post iniziale è vecchio; Stavo solo cercando di migliorare la tua soluzione.
6infinity8

3

J (50)

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

Sono sicuro che un J-er più competente di quanto possa renderlo ancora più breve. Sono un newb relativo.

Nuovo e migliorato:

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

Più recenti e ancora più migliorati, grazie a ɐɔıʇǝɥʇuʎs:

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

1
Puoi ottenere un personaggio non dividendo 'appy'. Penso che puoi anche rimuovere le parentesi attorno a ("." 0) - gli avverbi si legano più strettamente delle congiunzioni.
Jesse Millikan,

Non riesco a rimuovere le parentesi ("."0). Ciò produce un errore di rango, ma se non divido "Happy" e non lascio il risultato inscatolato, posso salvare un personaggio.
Gregory Higley,

Il motivo per cui non posso tralasciare le parentesi ("."0)è che le congiunzioni si applicano all'intero precedente treno di verbi a cui sono attaccate, che non è quello che voglio. Se lo dico +/@:("."0)@":, è molto diverso da quello +/@:"."0@:che è in realtà (+/@:".)"0@:.
Gregory Higley,

1
Un enorme necro, ma è possibile salvare 4 caratteri sostituendoli 'Unhappy';'Happy'con Unhappy`Happy.
ɐɔıʇǝɥʇuʎs,

@ ɐɔıʇǝɥʇuʎs Funziona, ma dove è documentato che puoi saltare la citazione delle stringhe con `?
Gregory Higley,

2

Python (91 caratteri)

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

Più leggibile:

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

Sarebbe più breve restituire "Happy" o "Unhappy" fin (do)dall'inizio, ma probabilmente non conterebbe come un intero programma


2

K, 43

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

2

Gelatina , 17 byte (non competitiva *)

* Sfida post-lingua in lingua

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

Provalo online!

Come?

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 byte

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

$ n è il valore di input


1

05AB1E , 21 byte

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

Provalo online o verifica i primi 100 casi di test .

Spiegazione:

Ogni numero alla fine si tradurrà in uno 1o 4, quindi eseguiamo il ciclo indefinitamente e ci fermiamo non appena il numero è inferiore a 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)

Vedere questo suggerimento 05AB1E mio (sezione Come utilizzare il dizionario? ) Per capire il motivo per cui 'ŽØè "happy".


0

C ++ 135, 2 righe

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

Questa è una versione modificata di quella che ho fatto qui:

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


Che cosa è il &999fare? E come funziona se jè un valore di immondizia?
David dice di reintegrare Monica l'

@ Dgrin91, l'ho scritto 3 anni fa, quindi non ricordo esattamente come funziona. Penso che il & 999 faccia la dichiarazione if(j==999){n = 0;}else{n=n*n +i;}, j non dovrebbe essere un valore di immondizia, i globuli sono zero inizializzati.
Scott Logan,

0

Sì, questa sfida ha tre anni; sì, ha già una risposta vincente; ma dato che ero annoiato e ho fatto questo per un'altra sfida, ho pensato di poterlo mettere qui. Sorpresa sorpresa, è lunga - e in ...

Java - 280 264 byte

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 byte

Aggiornamento: rimosso l' letassociazione non necessaria .

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

Originale:

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

Prima volta usando un nidificato for: o


0

R, 117 91 byte

-16 byte grazie 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
Utilizzare strtoiinvece di as.numerice pasteinvece di as.character, ma esiste un approccio più breve per ottenere le cifre . Se usi `if`(a-1,"unhappy","happy")invece quello dovrebbe salvare un altro byte. Infine, puoi renderlo anonimo per radere qualche byte in più.
Giuseppe,



-1

C: 1092 caratteri

#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
Benvenuti in Programming Puzzles & Code Golf, @jannat. Si noti che il codice golf è una sfida di scrivere il codice più breve possibile. Ciò significa che qui scriviamo codice indifferente e quasi illeggibile e forziamo i limiti della sintassi del linguaggio per abbreviare i nostri codici il più possibile.
arte

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.