Take the 2-minute tour ×
Programming Puzzles & Code Golf Stack Exchange is a question and answer site for programming puzzle enthusiasts and code golfers. It's 100% free, no registration required.

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.

share|improve this question
add comment

20 Answers

up vote 5 down vote accepted

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

share|improve this answer
add comment

Piet - 103 codels

Codel Size 8

golfed

Codel size 1

golfed small version

I took some liberties when coming up with the 103 count. Technically there are 448 codels, but only 103 are "important", though without the full 64x7 space I wouldn't have been able to fit the nested loops' structures. It also only prints U or H instead of the full words Unhappy and Happy as that would've added tens to hundreds of more codels.

Since Piet isn't really a competitive language when it comes to code golf, I hope no one takes issue when I break the rules a little.

Here is a 'fun' version of the same algorithm that outputs :) or :( instead of the words. Fun fact: the code path runs through the half the the smiley/frowny face that corresponds with the result.

Codel size 10

Artsy version

Edit: Fixed a bug that broke the program on large numbers. The number of codels stayed the same.

Explanation

The algorithm was based on this C solution.

Here is a manually annotated image depicting the structure (click to enlarge)

annotated version

And because I'm already taking up too much space here are links to traces:

share|improve this answer
1  
How do they work? –  Peter Olson Apr 26 '11 at 23:58
    
@Casey. Beautiful. Is there a authoritative link for learning about Piet? –  dmckee Apr 27 '11 at 1:45
    
I diddled your formatting a little because the inline code blocks were confusing Georges userscript. –  dmckee Apr 27 '11 at 1:55
    
@dmckee The most authoritative Piet site would be the creator's specification. There is a samples page showing different user submitted Piet programs, and a tools page with some helpful utilities. As for learning you're sort of on your own. I made this tool to help me understand the roll operator. I'd like to drum up some more interest in Piet, maybe with a Piet focused challenge or two. Herm.. –  Casey Apr 27 '11 at 2:18
6  
Your solution images are no longer available. –  Joey Adams Jul 15 '11 at 22:24
show 2 more comments

Ruby, 77 characters

a=gets.to_i;a=eval"#{a}".gsub /./,'+\&**2'until a<5
puts a<2?:Happy: :Unhappy
share|improve this answer
    
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. –  GigaWatt Apr 25 '11 at 22:42
1  
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 Apr 25 '11 at 23:57
add comment

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.

share|improve this answer
1  
Why would you need anywhere close to that amount of memory for this problem? –  Peter Olson Apr 25 '11 at 20:32
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 Apr 25 '11 at 20:51
    
I'm curious: why does compiling it require so much RAM? –  Peter Taylor Apr 25 '11 at 21:22
1  
Appears 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 Apr 25 '11 at 22:11
1  
I love the naivety of this approach. And the abuse of for loops is beautiful. –  dmckee Apr 27 '11 at 1:52
add comment

Haskell - 77

f 1="Happy"
f 4="Unhappy"
f n=f$sum[read[c]^2|c<-show n]
main=interact$f.read
share|improve this answer
add comment

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

share|improve this answer
add comment

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.

share|improve this answer
1  
better off doing a int(c) than ord(c)-48.... –  st0le Apr 26 '11 at 4:32
add comment

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.

share|improve this answer
    
Save 1 char: n==4?h="Unh":n==1?h="H":a=n+""}alert(h+"appy") –  mellamokb Apr 26 '11 at 1:21
    
@mella Thanks. I also shaved another char off by changing || to |. –  Peter Olson Apr 26 '11 at 1:28
    
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 Apr 26 '11 at 1:43
    
@Mella Clever, I like it. –  Peter Olson Apr 26 '11 at 2:01
    
@Mella n needs to be defined before the while loop, I'm trying to think of how to not repeat n=0; –  Peter Olson Apr 26 '11 at 2:08
show 3 more comments

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.

share|improve this answer
add comment

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.

share|improve this answer
add comment

Befunge, 109

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

v v              <   @,,,,,"Happy"<      >"yppahnU",,,,,,,@
>&>:25*%:*\25*/:#^_$+++++++++:1-!#^_:4-!#^_10g11p
share|improve this answer
add comment

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  
share|improve this answer
add comment

J (54)

'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)@":)
share|improve this answer
1  
You 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 Apr 27 '11 at 5:36
    
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 Apr 28 '11 at 20:12
    
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 May 1 '11 at 15:55
add comment

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
share|improve this answer
add comment

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"
share|improve this answer
add comment

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))}
share|improve this answer
1  
Wouldn't (n*n) be shorter as n*n , or does whitespace not suffice to separate an if-expression from the else? –  Peter Taylor Apr 27 '11 at 11:50
    
Yes, I did so, Peter. –  user unknown Apr 27 '11 at 12:07
add comment

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

share|improve this answer
add comment

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:

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

share|improve this answer
    
What is the &999 do? And how does it work if j is a garbage value? –  Dgrin91 Apr 11 at 13:44
    
@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. –  Bunnit Apr 14 at 9:18
add comment

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 ;
}
share|improve this answer
3  
Welcome 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 Mar 9 '13 at 16:28
    
xkcd.com/292 –  aditsu Mar 11 '13 at 18:06
add comment

K, 43

{{$[4=d:+/a*a:"I"$'$x;unhappy;d]}/x;`happy}
share|improve this answer
add comment

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.