Find whether a number is happy or not?

21

2

A happy number is defined by the following process. Starting with any positive integer, replace the number by the sum of the squares of its digits, and repeat the process until the number equals 1 (where it will stay), or it loops endlessly in a cycle which does not include 1. Those numbers for which this process ends in 1 are happy numbers, while those that do not end in 1 are unhappy numbers (or sad numbers). Given a number print whether it is happy or unhappy.

Sample Inputs
7
4
13

Sample Outputs
Happy
Unhappy
Happy

Note: Your program should not take more than 10 secs for any number below 1,000,000,000.

fR0DDY

Posted 2011-04-25T17:54:11.833

Reputation: 4 337

Answers

8

Golfscript - 34 chars

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

Basically the same as this and these.

The reason for 9 iterations is described in these comments (this theoretically returns correct values up to about 10^10^10^974 (A001273)).

Nabb

Posted 2011-04-25T17:54:11.833

Reputation: 2 540

11

Ruby, 77 characters

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

Ventero

Posted 2011-04-25T17:54:11.833

Reputation: 9 842

Ok, so I kinda get how this works (Literally taking each number, splitting it and adding the square of each digit), but what's with the stop condition of (a < 5) and using (a < 2) to decide if it's happy or not? I don't question the validity, just the logic. – Mr. Llama – 2011-04-25T22:42:08.210

2

That is the same as a <= 4 and a <= 1. If the cycle has a 1 in it then it is happy, and if it has a 4 in it, then it is not happy. See the wikipedia section about the unhappy cycle. So once the value of a is 4 or less, he checks if a is -- the result of that is your answer.

– Casey – 2011-04-25T23:57:27.147

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

This uses a 230-byte (1GB) array as a bitmap to keep track of which numbers have been encountered in the cycle. On Linux, this actually works, and efficiently so, provided memory overcommitting is enabled (which it usually is by default). With overcommitting, pages of the array are allocated and zeroed on demand.

Note that compiling this program on Linux uses a gigabyte of RAM.

Joey Adams

Posted 2011-04-25T17:54:11.833

Reputation: 9 929

1Why would you need anywhere close to that amount of memory for this problem? – Peter Olson – 2011-04-25T20:32:54.757

1@Peter: I suppose the approach is to (naively) catch a cycle for any number in the allowed input range from 1 to 1,000,000,000. But I agree that in light of happy number theory, the only check necessary is if the number 4 is reached, because that's the only cycle that will ever occur. – mellamokb – 2011-04-25T20:51:11.010

I'm curious: why does compiling it require so much RAM? – Peter Taylor – 2011-04-25T21:22:26.260

1Appears to work fine on Windows 7 with MSVC 10. Doesn't consume any notable amount of memory while compiling and only marks the array in the page file (something that sounds way safer than the story you linked about memory overcommitting suggests ;-)). – Joey – 2011-04-25T22:11:36.620

1I love the naivety of this approach. And the abuse of for loops is beautiful. – dmckee --- ex-moderator kitten – 2011-04-27T01:52:50.230

6

Golfscript, 49 43 41 40 39 chars

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

Every happy number converges to 1; every unhappy number converges to a cycle containing 4. Other than exploiting that fact, this is barely golfed at all.

(Thanks to Ventero, from whose Ruby solution I've nicked a trick and saved 6 chars).

Peter Taylor

Posted 2011-04-25T17:54:11.833

Reputation: 41 901

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

Posted 2011-04-25T17:54:11.833

Reputation: 9 929

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

Called as etex filename.tex 34*23 + 32/2 ? (including the question mark at the end). Spaces in the expression don't matter.

EDIT: I got down to 123, but now the output is dvi (if compiled with etex) or pdf (if compiled with pdfetex). Since TeX is a typesetting language, I guess that's 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

Posted 2011-04-25T17:54:11.833

Reputation: 1 181

4

Python - 81 chars

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

Some inspiration taken from Ventero and Peter Taylor.

Juan

Posted 2011-04-25T17:54:11.833

Reputation: 2 738

2better off doing a int(c) than ord(c)-48.... – st0le – 2011-04-26T04:32:29.313

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

Input is provided by setting a to the number desired.

Credits to mellamokb.

Peter Olson

Posted 2011-04-25T17:54:11.833

Reputation: 7 412

Save 1 char: n==4?h="Unh":n==1?h="H":a=n+""}alert(h+"appy") – mellamokb – 2011-04-26T01:21:02.247

@mella Thanks. I also shaved another char off by changing || to |. – Peter Olson – 2011-04-26T01:28:16.557

Save 8 chars: Remove n==4?h.... Change to do...while loop with condition while(n>4). Then use this final statement instead: alert(["H","Unh"][n>1?1:0]+"appy") – mellamokb – 2011-04-26T01:43:02.687

@Mella Clever, I like it. – Peter Olson – 2011-04-26T02:01:16.200

@Mella n needs to be defined before the while loop, I'm trying to think of how to not repeat n=0; – Peter Olson – 2011-04-26T02:08:28.940

@Peter: Technically, it doesn't need to be defined: http://jsfiddle.net/8bqWF/ – mellamokb – 2011-04-26T02:15:54.440

@Peter: You also have to change it from a while loop to a do...while loop in order for my code to work, so that the condition is checked at the end. – mellamokb – 2011-04-26T02:26:06.703

@Mella Ok, I see now. That saves me one more char. Maybe I can make it look shorter by replacing double wuotes with single quotes. :) – Peter Olson – 2011-04-26T03:11:02.503

4

Python (98, but too messed up not to share)

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

Way, way too long to be competitive, but perhaps good for a laugh. It does "lazy" evaluation in Python. Really quite similar to the Haskell entry now that I think about it, just without any of the charm.

user1011

Posted 2011-04-25T17:54:11.833

Reputation:

4

dc - 47 chars

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

Brief description:

I~: Get the quotient and remainder when dividing by 10.
d*: Square the remainder.
0<H: If the quotient is greater than 0, repeat recursively.
+: Sum the values when shrinking the recursive stack.

4<h: Repeat the sum-of-squares bit while the value is greater than 4.

Nabb

Posted 2011-04-25T17:54:11.833

Reputation: 2 540

4

Befunge, 109

Returns correct values for 1<=n<=109-1.

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

Lowjacker

Posted 2011-04-25T17:54:11.833

Reputation: 4 466

3

J (50)

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

I'm sure a more competent J-er than I can make this even shorter. I'm a relative newb.

New and improved:

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

Newer and even more improved, thanks to ɐɔıʇǝɥʇuʎs:

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

Gregory Higley

Posted 2011-04-25T17:54:11.833

Reputation: 395

1A massive necro, but you could save 4 chars by replacing 'Unhappy';'Happy' with Unhappy\Happy`. – ɐɔıʇǝɥʇuʎs – 2014-12-15T07:39:37.100

@ɐɔıʇǝɥʇuʎs That works, but where is it documented that you can skip the quoting of strings with `? – Gregory Higley – 2014-12-15T10:50:49.870

Ah, I see. All this time I misunderstood gerunds. It appears to be strings all the way down. Fascinating. – Gregory Higley – 2014-12-15T10:53:34.347

http://www.jsoftware.com/help/dictionary/d610.htm – ɐɔıʇǝɥʇuʎs – 2014-12-15T11:02:53.070

Thanks. I know the vocab well and visit it often. In fact, I went straight there when I saw that your suggestion worked. Unfortunately that vocab entry could be a little more explicit. It's natural to assume that the gerund conjunction joins the atom itself rather than converting it to a string first. That's what I always thought, but I'm "happy" to find out I'm wrong. – Gregory Higley – 2014-12-15T11:07:31.880

1You can get a character by not splitting out 'appy'. I think you can also remove the parentheses aroundd ("."0) - adverbs bind tighter than conjunctions. – Jesse Millikan – 2011-04-27T05:36:22.603

I can't remove the parentheses around ("."0). That produces a rank error, but if I don't split 'Happy' and leave the result boxed, I can save a character. – Gregory Higley – 2011-04-28T20:12:42.567

The reason I can't leave out the parentheses around ("."0) is that conjunctions apply to the entire preceding train of verbs to which they're attached, which is not what I want. If I say +/@:("."0)@":, that is very different from +/@:"."0@:, which is actually (+/@:".)"0@:. – Gregory Higley – 2011-05-01T15:55:30.747

3

J, 56

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

A verb rather than a standalone script since the question is ambiguous.

Usage:

   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

Posted 2011-04-25T17:54:11.833

Reputation: 1 438

3

Scala, 145 chars

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

user unknown

Posted 2011-04-25T17:54:11.833

Reputation: 4 210

Here is a 126 bytes tail-recursive version, without pattern matching: 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 – 2017-10-21T13:56:40.243

@6infinity8: Why don't you post it as a new answer? – user unknown – 2017-10-21T19:00:37.657

The initial post is old; I was just trying to improve your solution. – 6infinity8 – 2017-10-21T20:38:53.787

1Wouldn't (n*n) be shorter as n*n, or does whitespace not suffice to separate an if-expression from the else? – Peter Taylor – 2011-04-27T11:50:42.783

Yes, I did so, Peter. – user unknown – 2011-04-27T12:07:58.080

2

K, 43

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

tmartin

Posted 2011-04-25T17:54:11.833

Reputation: 3 917

2

Jelly, 17 bytes (non-competing*)

* Language post-dates challenge

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

Try it online!

How?

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

Posted 2011-04-25T17:54:11.833

Reputation: 67 804

2

Python (91 characters)

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

marinus

Posted 2011-04-25T17:54:11.833

Reputation: 30 224

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

More readable:

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

Would be shorter to just return "Happy" or "Unhappy" right from the (do), but arguably that wouldn't count as a whole program

daniero

Posted 2011-04-25T17:54:11.833

Reputation: 17 193

1

05AB1E, 21 bytes

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

Try it online or verify the first 100 test cases.

Explanation:

Each number will eventually result in either 1 or 4, so we loop indefinitely, and stop as soon as the number is below 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)

See this 05AB1E tip of mine (section How to use the dictionary?) to understand why 'ŽØ is "happy".

Kevin Cruijssen

Posted 2011-04-25T17:54:11.833

Reputation: 67 575

1

Perl 5 - 77 Bytes

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

$n is the input value

Kaundur

Posted 2011-04-25T17:54:11.833

Reputation: 71

0

Clojure, 107 97 bytes

Update: Removed unnecessary let binding.

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

First time using a nested for :o

NikoNyrh

Posted 2011-04-25T17:54:11.833

Reputation: 2 361

0

R, 117 91 bytes

-16 bytes thanks to 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

Posted 2011-04-25T17:54:11.833

Reputation: 311

1

Use strtoi instead of as.numeric and paste instead of as.character, but there is a shorter approach to get the digits. If you use \if`(a-1,"unhappy","happy")` instead that should save another byte. Finally, you can make this anonymous to shave off a few more bytes.

– Giuseppe – 2017-10-19T16:40:33.787

0

Perl 5, 62 + 1 (-p) = 63 bytes

$_=eval s/./+$&**2/gr while$_>1&&!$k{$_}++;$_=un x($_>1).happy

Try it online!

Xcali

Posted 2011-04-25T17:54:11.833

Reputation: 7 671

0

Python 2, 71 bytes

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

Try it online!

...or, for the same byte count:

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

Try it online!

FlipTack

Posted 2011-04-25T17:54:11.833

Reputation: 13 242

0

C++ 135 , 2 Lines

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

This is a modified version of the one I did here:

https://stackoverflow.com/questions/3543811/code-golf-happy-primes/3545056#3545056

Scott Logan

Posted 2011-04-25T17:54:11.833

Reputation: 332

What is the &999 do? And how does it work if j is a garbage value? – David says Reinstate Monica – 2014-04-11T13:44:09.083

@Dgrin91, I wrote this 3 years ago, so i can't remember exactly how it works. I think the &999 makes the statement if(j==999){n = 0;}else{n=n*n +i;}, j shouldn't be a garbage value, globals are zero initialized. – Scott Logan – 2014-04-14T09:18:09.433

0

Yes, this challenge has three years; yes, it already has a winner answer; but since I was bored and done this for another challenge, thought I might put it up here. Surprise surprise, its long - and 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

Posted 2011-04-25T17:54:11.833

Reputation: 3 940

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

For any given number (as int), h() will return the correct value. You can try the code on .NetFiddle.

Kudos to user unknown for the original algorithm.

aloisdg moving to codidact.com

Posted 2011-04-25T17:54:11.833

Reputation: 1 767

-1

C: 1092 characters

#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

Posted 2011-04-25T17:54:11.833

Reputation: 1

6Welcome to Programming Puzzles & Code Golf, @jannat. Please note that code golf is a challenge of writing the shortest code possible. That means, here we write unindented and almost unreadable code and force the limits of the language syntax to shorten our codes as possible. – manatwork – 2013-03-09T16:28:37.750

http://xkcd.com/292/ – aditsu quit because SE is EVIL – 2013-03-11T18:06:58.663