Finden Sie heraus, ob eine Nummer glücklich ist oder nicht?

21

Eine Glückszahl wird durch den folgenden Prozess definiert. Beginnen Sie mit einer positiven ganzen Zahl, ersetzen Sie die Zahl durch die Summe der Quadrate ihrer Ziffern und wiederholen Sie den Vorgang, bis die Zahl gleich 1 ist (wo sie verbleibt), oder sie wiederholt sich endlos in einem Zyklus, der nicht 1 enthält. Diese Zahlen für die dieser Prozess mit 1 endet, sind glückliche Zahlen, während diejenigen, die nicht mit 1 enden, unglückliche Zahlen (oder traurige Zahlen) sind. Gegeben, eine Zahl drucken, ob es glücklich oder unglücklich ist.

Sample Inputs
7
4
13

Sample Outputs
Happy
Unhappy
Happy

Hinweis: Ihr Programm sollte für Zahlen unter 1.000.000.000 nicht länger als 10 Sekunden dauern.

fR0DDY
quelle

Antworten:

11

Ruby, 77 Zeichen

a=gets.to_i;a=eval"#{a}".gsub /./,'+\&**2'until a<5
puts a<2?:Happy: :Unhappy
Ventero
quelle
Ok, ich verstehe ein bisschen, wie das funktioniert (buchstäblich jede Zahl nehmen, sie teilen und das Quadrat jeder Ziffer hinzufügen), aber was ist mit der Stoppbedingung (a <5) und der Verwendung von (a <2), um zu entscheiden, ob es glücklich ist oder nicht? Ich stelle die Gültigkeit nicht in Frage, nur die Logik.
Mr. Llama
2
Das ist dasselbe wie a <= 4und a <= 1. Wenn der Zyklus eine 1 enthält, ist er glücklich, und wenn er eine 4 enthält, ist er nicht glücklich. Siehe den Wikipedia-Abschnitt über den unglücklichen Zyklus. Sobald der Wert a4 oder weniger ist, prüft er, ob a ist - das Ergebnis ist Ihre Antwort.
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");}

Dies verwendet ein 2 30- Byte-Array (1 GB) als Bitmap, um zu verfolgen, welche Zahlen im Zyklus aufgetreten sind. Unter Linux funktioniert dies tatsächlich und effizient, vorausgesetzt, die Speicherüberlastung ist aktiviert (was normalerweise die Standardeinstellung ist). Bei einem Overcommitting werden Seiten des Arrays bei Bedarf zugewiesen und auf Null gesetzt.

Beachten Sie, dass beim Kompilieren dieses Programms unter Linux ein Gigabyte RAM benötigt wird.

Joey Adams
quelle
1
Warum benötigen Sie für dieses Problem ungefähr so ​​viel Speicher?
Peter Olson
1
@Peter: Ich nehme an, der Ansatz ist, (naiv) einen Zyklus für eine beliebige Zahl im zulässigen Eingabebereich von 1 bis 1.000.000.000 abzufangen. Aber ich stimme zu, dass im Lichte der Happy-Number-Theorie nur überprüft werden muss, ob die Zahl 4 erreicht ist, da dies der einzige Zyklus ist, der jemals auftreten wird.
Mellamokb
Ich bin gespannt: Warum erfordert das Kompilieren so viel RAM?
Peter Taylor
1
Scheint unter Windows 7 mit MSVC 10 einwandfrei zu funktionieren. Verbraucht beim Kompilieren keine nennenswerte Menge an Speicher und markiert nur das Array in der Auslagerungsdatei (etwas, das sich sicherer anhört als die Geschichte, die Sie über die Überbelegung von Speicher verbunden haben ;-)) .
Joey
1
Ich liebe die Naivität dieses Ansatzes. Und der Missbrauch von for-Schleifen ist wunderschön.
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
quelle
6

Golfscript, 49 43 41 40 39 Zeichen

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

Jede glückliche Zahl konvergiert zu 1; Jede unglückliche Zahl konvergiert zu einem Zyklus, der 4 enthält. Abgesehen davon, dass diese Tatsache ausgenutzt wird, wird hier kaum Golf gespielt.

(Dank an Ventero, von dessen Ruby-Lösung ich einen Trick geklaut und 6 Zeichen gespart habe).

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

Genannt als etex filename.tex 34*23 + 32/2 ?(einschließlich des Fragezeichens am Ende). Leerzeichen im Ausdruck spielen keine Rolle.

EDIT: Ich bin auf 123 gekommen , aber jetzt ist die Ausgabe dvi (wenn kompiliert mit etex) oder pdf (wenn kompiliert mit pdfetex). Da TeX eine Schriftsprache ist, halte ich das für fair.

\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
quelle
4

Python - 81 Zeichen

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

Inspiration von Ventero und Peter Taylor.

Juan
quelle
2
besser dran int(c)als 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')

Die Eingabe erfolgt durch Setzen von a auf die gewünschte Zahl.

Dank an mellamokb.

Peter Olson
quelle
1 n==4?h="Unh":n==1?h="H":a=n+""}alert(h+"appy")
Zeichen
@ Mella Danke. Ich habe auch einen anderen Saibling rasiert, indem ich zu gewechselt ||habe |.
Peter Olson
8 Zeichen sparen: Entfernen n==4?h.... Ändern, um ... while-Schleife mit Bedingung auszuführen while(n>4). Verwenden Sie stattdessen diese abschließende Aussage:alert(["H","Unh"][n>1?1:0]+"appy")
mellamokb
@ Mella Clever, ich mag es.
Peter Olson
@ Mella n muss vor der while-Schleife definiert werden, ich versuche zu überlegen, wie man nicht wiederholtn=0;
Peter Olson
4

Python (98, aber zu durcheinander, um es nicht zu teilen)

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

Viel zu lange, um wettbewerbsfähig zu sein, aber vielleicht gut zum Lachen. In Python wird "faul" ausgewertet. Wirklich ziemlich ähnlich dem Haskell-Eintrag, jetzt, wo ich darüber nachdenke, nur ohne den Charme.


quelle
4

DC - 47 Zeichen

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

Kurze Beschreibung:

I~: Ermitteln Sie den Quotienten und den Rest bei der Division durch 10
d*.: Quadrieren Sie den Rest.
0<H: Wenn der Quotient größer als 0 ist, rekursiv wiederholen.
+: Summiere die Werte beim Verkleinern des rekursiven Stapels.

4<h: Wiederholen Sie das Quadratsummenbit, während der Wert größer als 4 ist.

Nabb
quelle
4

Befunge, 109

Gibt korrekte Werte für 1 <= n <= 10 9 -1 zurück.

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

J, 56

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

Ein Verb und kein eigenständiges Skript, da die Frage nicht eindeutig ist.

Verwendung:

   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
quelle
3

Scala, 145 Zeichen

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))}
Benutzer unbekannt
quelle
1
Wäre nicht (n*n)kürzer als n*n , oder reicht Leerzeichen nicht aus, um einen if-Ausdruck vom zu trennen else?
Peter Taylor
Ja, das habe ich getan, Peter.
Benutzer unbekannt
Hier ist eine 126-Byte-Schwanz-rekursive Version ohne Mustererkennung: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: Warum postest du es nicht als neue Antwort?
Benutzer unbekannt
Der ursprüngliche Beitrag ist alt; Ich habe nur versucht, Ihre Lösung zu verbessern.
6infinity8
3

J (50)

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

Ich bin sicher ein kompetenterer J-er, als ich das noch kürzer machen kann. Ich bin ein relativer Neuling.

Neu und verbessert:

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

Neu und noch besser dank ʇǝɥʇıɐɔuʇǝɥʇs:

(Unhappy`Happy){~=&1`$:@.(>&6)@(+/@:*:@:("."0)@":)
Gregory Higley
quelle
1
Sie können einen Charakter erhalten, indem Sie "appy" nicht aufteilen. Ich denke, Sie können auch die Klammern um d ("." 0) entfernen - Adverbien binden enger als Konjunktionen.
Jesse Millikan
Ich kann die Klammern nicht entfernen ("."0). Das führt zu einem Rangfehler, aber wenn ich nicht 'Happy' teile und das Ergebnis in der Box lasse, kann ich einen Charakter speichern.
Gregory Higley
Der Grund, warum ich die Klammern nicht auslassen kann, ("."0)ist, dass Konjunktionen für die gesamte vorhergehende Reihe von Verben gelten, an die sie angehängt sind, was ich nicht möchte. Wenn ich sage +/@:("."0)@":, ist das ganz anders als das +/@:"."0@:, was eigentlich ist (+/@:".)"0@:.
Gregory Higley
1
Eine massive necro, aber man konnte 4 Zeichen sparen durch Ersetzen 'Unhappy';'Happy'mit Unhappy`Happy.
15.
@ ɐɔıɐɔuʇǝɥʇs Das funktioniert, aber wo ist dokumentiert, dass Sie das Zitieren von Strings mit `überspringen können?
Gregory Higley
2

Python (91 Zeichen)

a=lambda b:b-1and(b-4and a(sum(int(c)**2for c in`b`))or"Unh")or"H";print a(input())+"appy"
Marinus
quelle
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"))))

Besser lesbar:

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

Wäre kürzer, wenn Sie einfach "Happy" oder "Unhappy" aus dem zurückgeben würden (do), aber das würde wohl nicht als ganzes Programm gelten

daniero
quelle
2

K, 43

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

Gelee , 17 Bytes (nicht konkurrierend *)

* Herausforderung nach den Terminen

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

Probieren Sie es online!

Wie?

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

Perl 5 - 77 Bytes

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

$ n ist der Eingabewert

Kaundur
quelle
1

05AB1E , 21 Bytes

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

Probieren Sie es online aus oder überprüfen Sie die ersten 100 Testfälle .

Erläuterung:

Jede Zahl wird irgendwann entweder 1oder ergeben 4, so dass wir eine Endlosschleife ausführen und anhalten, sobald die Zahl unter 5 liegt.

'ŽØ                    '# 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)

Sehen Sie diese 05AB1E Spitze von mir (Abschnitt Wie das Wörterbuch benutzen? ) Zu verstehen , warum 'ŽØist "happy".

Kevin Cruijssen
quelle
0

C ++ 135, 2 Zeilen

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

Dies ist eine modifizierte Version von der, die ich hier gemacht habe:

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

Scott Logan
quelle
Was ist das zu &999tun? Und wie funktioniert es, wenn jein Müllwert ist?
David sagt Reinstate Monica
@ Dgrin91, ich habe das vor 3 Jahren geschrieben, daher kann ich mich nicht genau erinnern, wie es funktioniert. Ich denke, das & 999 macht die Aussage if(j==999){n = 0;}else{n=n*n +i;}, j sollte kein Müllwert sein, Globals werden mit Null initialisiert.
Scott Logan
0

Ja, diese Herausforderung hat drei Jahre; Ja, es gibt bereits eine Gewinnerantwort. aber da ich gelangweilt war und dies für eine andere Herausforderung tat, dachte ich, ich könnte es hier aufstellen. Überraschung Überraschung, es ist lang - und in ...

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

C # 94 Bytes

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

Gibt für eine bestimmte Zahl (as int) h()den korrekten Wert zurück. Sie können den Code auf .NetFiddle ausprobieren .

Lob an den Benutzer unbekannt für den ursprünglichen Algorithmus .

aloisdg sagt Reinstate Monica
quelle
0

Clojure, 107 97 Bytes

Update: Unnötig entfernt let Bindung entfernt.

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

Zum ersten Mal mit einem verschachtelten for: o

NikoNyrh
quelle
0

R 117 91 Bytes

-16 Bytes dank 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
quelle
1
Verwenden Sie strtoianstelle von as.numericund pasteanstelle von as.character, aber es gibt einen kürzeren Ansatz, um die Ziffern zu erhalten . Wenn Sie `if`(a-1,"unhappy","happy")stattdessen verwenden, sollte das ein anderes Byte speichern. Schließlich können Sie dies anonymisieren, um ein paar weitere Bytes zu entfernen.
Giuseppe
-1

C: 1092 Zeichen

#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
quelle
6
Willkommen bei Programming Puzzles & Code Golf, @jannat. Bitte beachten Sie, dass Codegolf eine Herausforderung ist, den kürzestmöglichen Code zu schreiben. Das bedeutet, dass wir hier nicht eingerückten und fast nicht lesbaren Code schreiben und die Grenzen der Sprachsyntax erzwingen, um unsere Codes so kurz wie möglich zu halten.
Manatwork
xkcd.com/292
aditsu