Sprawdź, czy numer jest szczęśliwy, czy nie?

21

Szczęśliwa liczba jest definiowana przez następujący proces. Zaczynając od dodatniej liczby całkowitej, zamień liczbę na sumę kwadratów jej cyfr i powtarzaj proces, aż liczba wyniesie 1 (gdzie pozostanie), lub zapętli się bez końca w cyklu, który nie obejmuje 1. Te liczby dla których ten proces kończy się na 1 są liczbami szczęśliwymi, podczas gdy te, które nie kończą się na 1 są liczbami nieszczęśliwymi (lub liczbami smutnymi). Biorąc pod uwagę wydruk numeru, czy jest szczęśliwy czy nieszczęśliwy.

Sample Inputs
7
4
13

Sample Outputs
Happy
Unhappy
Happy

Uwaga: Twój program nie powinien trwać dłużej niż 10 sekund dla dowolnej liczby poniżej 1 000 000 000.

fR0DDY
źródło

Odpowiedzi:

8

Golfscript - 34 znaki

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

Zasadniczo taki sam jak ten i te .

Powód 9 iteracji jest opisany w tych komentarzach (teoretycznie zwraca prawidłowe wartości do około 10^10^10^974( A001273 )).

Nabb
źródło
11

Ruby, 77 znaków

a=gets.to_i;a=eval"#{a}".gsub /./,'+\&**2'until a<5
puts a<2?:Happy: :Unhappy
Ventero
źródło
Ok, więc trochę rozumiem, jak to działa (dosłownie biorąc każdą liczbę, dzieląc ją i dodając kwadrat każdej cyfry), ale co z warunkiem zatrzymania (a <5) i używając (a <2), aby zdecydować, czy jest szczęśliwy albo nie? Nie kwestionuję ważności, tylko logikę.
Pan Llama,
2
To jest to samo co a <= 4i a <= 1. Jeśli cykl ma 1, to jest szczęśliwy, a jeśli ma 4, to nie jest szczęśliwy. Zobacz sekcję wikipedii o nieszczęśliwym cyklu. Kiedy więc wartość awynosi 4 lub mniej, sprawdza, czy jest - wynikiem jest twoja odpowiedź.
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");}

Wykorzystuje tablicę 2 30- bajtową (1 GB) jako mapę bitową do śledzenia, które liczby napotkano w cyklu. W systemie Linux działa to faktycznie i wydajnie, pod warunkiem, że włączone jest nadmierne zaangażowanie pamięci (co zwykle jest domyślnie). Przy nadmiernym zaangażowaniu strony tablicy są przydzielane i zerowane na żądanie.

Pamiętaj, że kompilacja tego programu w systemie Linux wymaga gigabajta pamięci RAM.

Joey Adams
źródło
1
Dlaczego potrzebujesz tego miejsca blisko takiej ilości pamięci na ten problem?
Peter Olson,
1
@Peter: Przypuszczam, że podejście polega na (naiwnym) uchwyceniu cyklu dla dowolnej liczby w dozwolonym zakresie wejściowym od 1 do 1 000 000 000. Zgadzam się jednak, że w świetle teorii szczęśliwych liczb jedyną konieczną kontrolą jest osiągnięcie liczby 4, ponieważ to jedyny cykl, jaki kiedykolwiek nastąpi.
mellamokb
Jestem ciekawy: dlaczego kompilacja wymaga tak dużo pamięci RAM?
Peter Taylor,
1
Wygląda na to, że działa dobrze w systemie Windows 7 z MSVC 10. Nie zużywa znaczącej ilości pamięci podczas kompilacji i jedynie zaznacza tablicę w pliku stronicowania (coś, co brzmi o wiele bezpieczniej niż historia, którą podłączyłeś, mówiąc o nadmiernym zaangażowaniu pamięci ;-)) .
Joey,
1
Uwielbiam naiwność tego podejścia. A nadużywanie pętli jest piękne.
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
źródło
6

Golfscript, 49 43 41 40 39 znaków

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

Każda szczęśliwa liczba jest zbieżna do 1; każda nieszczęśliwa liczba zbiega się w cykl zawierający 4. Poza wykorzystaniem tego faktu, jest to ledwo w golfa.

(Dzięki Ventero, z którego rozwiązania Ruby stworzyłem lewę i zaoszczędziłem 6 znaków).

Peter Taylor
źródło
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

Nazywany jako etex filename.tex 34*23 + 32/2 ?(w tym znak zapytania na końcu). Spacje w wyrażeniu nie mają znaczenia.

EDYCJA: przeszedłem do 123 , ale teraz wyjście to dvi (jeśli skompilowane z etex) lub pdf (jeśli skompilowane z pdfetex). Ponieważ TeX jest językiem składanym, to chyba sprawiedliwe.

\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
źródło
4

Python - 81 znaków

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

Inspiracje zaczerpnięte z Ventero i Petera Taylora.

Juan
źródło
2
lepiej robić int(c)niż niż 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')

Wprowadzanie odbywa się poprzez ustawienie a na żądaną liczbę.

Kredyty dla mellamokb.

Peter Olson
źródło
Zaoszczędź 1 znak:n==4?h="Unh":n==1?h="H":a=n+""}alert(h+"appy")
mellamokb
@mella Dzięki. Ogoliłem też inny zwęgiel, zmieniając ||na |.
Peter Olson,
Zapisz 8 znaków: Usuń n==4?h.... Zmień na czyn ... podczas pętli z warunkiem while(n>4). Zamiast tego użyj tego końcowego oświadczenia:alert(["H","Unh"][n>1?1:0]+"appy")
mellamokb
@Mella Clever, podoba mi się.
Peter Olson,
@Mella n musi zostać zdefiniowana przed pętlą while, próbuję wymyślić, jak się nie powtarzaćn=0;
Peter Olson,
4

Python (98, ale zbyt popsuty, by go nie udostępniać)

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

Zbyt długo, by być konkurencyjnym, ale być może dobrym do śmiechu. Dokonuje „leniwej” oceny w Pythonie. Naprawdę całkiem podobny do wpisu Haskell, kiedy o tym myślę, tylko bez uroku.


źródło
4

dc - 47 znaków

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

Krótki opis:

I~: Uzyskaj iloraz i resztę, dzieląc przez 10
d*.: Kwadrat reszty.
0<H: Jeśli iloraz jest większy niż 0, powtarzaj rekurencyjnie.
+: Zsumuj wartości podczas zmniejszania stosu rekurencyjnego.

4<h: Powtórz bit sumy kwadratów, gdy wartość jest większa niż 4.

Nabb
źródło
4

Befunge, 109

Zwraca poprawne wartości dla 1 <= n <= 10 9 -1.

v v              <   @,,,,,"Happy"<      >"yppahnU",,,,,,,@
>&>:25*%:*\25*/:#^_$+++++++++:1-!#^_:4-!#^_10g11p
Lowjacker
źródło
3

J, 56

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

Czasownik zamiast samodzielnego skryptu, ponieważ pytanie jest dwuznaczne.

Stosowanie:

   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
źródło
3

Scala, 145 znaków

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))}
nieznany użytkownik
źródło
1
Czy nie (n*n)byłby krótszy n*n , czy białe znaki nie wystarczają do oddzielenia wyrażenia if od else?
Peter Taylor
Tak, zrobiłem to, Peter.
użytkownik nieznany
Oto 126- 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")
bajtowa
@ 6infinity8: Dlaczego nie opublikujesz go jako nowej odpowiedzi?
użytkownik nieznany
Początkowy post jest stary; Właśnie próbowałem ulepszyć twoje rozwiązanie.
6infinity8
3

J (50)

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

Jestem pewien, że bardziej kompetentny J-er, niż mogę to uczynić jeszcze krótszym. Jestem względnym nowicjuszem.

Nowe i ulepszone:

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

Nowsze i jeszcze bardziej ulepszone dzięki ɐɔıʇǝɥʇuʎs:

(Unhappy`Happy){~=&1`$:@.(>&6)@(+/@:*:@:("."0)@":)
Gregory Higley
źródło
1
Możesz zdobyć postać, nie dzieląc „appy”. Myślę, że możesz także usunąć nawiasy wokół d ("." 0) - przysłówki wiążą się mocniej niż spójniki.
Jesse Millikan
Nie mogę usunąć nawiasów ("."0). Powoduje to błąd rangi, ale jeśli nie podzielę „Szczęśliwego” i nie zostawię wyniku w polu, mogę zapisać postać.
Gregory Higley,
Powodem, dla którego nie mogę pominąć nawiasów, ("."0)jest to, że spójniki mają zastosowanie do całego poprzedzającego zestawu czasowników, do których są dołączone, co nie jest tym, czego chcę. Jeśli powiem +/@:("."0)@":, to bardzo różni się od tego +/@:"."0@:, co jest w rzeczywistości (+/@:".)"0@:.
Gregory Higley
1
Ogromne nekro, ale możesz zapisać 4 znaki, zastępując 'Unhappy';'Happy'je Unhappy`Happy.
15ıʇǝɥʇuʎs
@ Thatıʇǝɥʇuʎs To działa, ale gdzie jest udokumentowane, że można pominąć cytowanie ciągów za pomocą `?
Gregory Higley,
2

Python (91 znaków)

a=lambda b:b-1and(b-4and a(sum(int(c)**2for c in`b`))or"Unh")or"H";print a(input())+"appy"
marinus
źródło
2

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

Bardziej czytelny:

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

Krótsze byłoby po prostu zwrócenie „Szczęśliwego” lub „Nieszczęśliwego” od razu (do), ale prawdopodobnie nie byłoby to liczone jako cały program

daniero
źródło
2

K, 43

{{$[4=d:+/a*a:"I"$'$x;unhappy;d]}/x;`happy}
tartin
źródło
2

Galaretka , 17 bajtów (niekonkurencyjna *)

* Wyzwanie po dacie językowej

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

Wypróbuj online!

W jaki sposób?

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
źródło
1

Perl 5 - 77 bajtów

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

$ n jest wartością wejściową

Kaundur
źródło
1

05AB1E , 21 bajtów

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

Wypróbuj online lub sprawdź pierwsze 100 przypadków testowych .

Wyjaśnienie:

Każda liczba ostatecznie spowoduje albo, 1albo 4, więc zapętlamy w nieskończoność i zatrzymamy się, gdy tylko liczba spadnie poniżej 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)

Zobacz moją wskazówkę 05AB1E (sekcja Jak korzystać ze słownika? ), Aby zrozumieć, dlaczego tak 'ŽØjest "happy".

Kevin Cruijssen
źródło
0

C ++ 135, 2 linie

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

To jest zmodyfikowana wersja tej, którą tutaj zrobiłem:

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

Scott Logan
źródło
Co to &999zrobić? I jak to działa, jeślij wartość śmieci jest wartością?
David mówi Przywróć Monikę
@ Dgrin91, napisałem to 3 lata temu, więc nie pamiętam dokładnie, jak to działa. Myślę, że & 999 wypowiada zdanie if(j==999){n = 0;}else{n=n*n +i;}, j nie powinno być wartością śmieciową, globały są inicjowane na zero.
Scott Logan
0

Tak, wyzwanie to trwa trzy lata; tak, ma już odpowiedź zwycięzcy; ale ponieważ nudziłem się i robiłem to dla kolejnego wyzwania, pomyślałem, że mogę to tutaj postawić. Niespodzianka niespodzianka, jej długi - i ...

Java - 280 264 bajtów

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

Nie golfowany:

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
źródło
0

C # 94 bajtów

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

Dla dowolnej liczby (as int), h()zwróci prawidłową wartość. Możesz wypróbować kod na .NetFiddle .

Uznanie dla użytkownika nieznane dla oryginalnego algorytmu .

aloisdg mówi Przywróć Monikę
źródło
0

Clojure, 107 97 bajtów

Aktualizacja: Usunięto niepotrzebne let powiązanie.

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

Oryginalny:

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

Pierwszy raz używając zagnieżdżonego for: o

NikoNyrh
źródło
0

R, 117 91 bajtów

-16 bajtów dzięki 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
źródło
1
Użyj strtoizamiast as.numerici pastezamiast as.character, ale istnieje krótsze podejście do uzyskania cyfr . Jeśli użyjesz `if`(a-1,"unhappy","happy")zamiast tego, powinien zapisać kolejny bajt. Na koniec możesz uczynić to anonimowym, aby zgolić jeszcze kilka bajtów.
Giuseppe,
0

Python 2 , 71 bajtów

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

Wypróbuj online!

... lub dla tej samej liczby bajtów:

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

Wypróbuj online!

FlipTack
źródło
-1

C: 1092 znaków

#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
źródło
6
Witamy w Programowanie Puzzle i Code Golf, @jannat. Pamiętaj, że kod golfowy to wyzwanie polegające na napisaniu możliwie najkrótszego kodu. Oznacza to, że tutaj piszemy niezauważalny i prawie nieczytelny kod i wymuszamy ograniczenia składni języka, aby skrócić nasze kody, jak to możliwe.
manatwork
xkcd.com/292
aditsu