A prime number is a whole number greater than 1 whose only factors are 1 and itself. A factor is a whole number that can be divided evenly into another number. The first few prime numbers are 2, 3, 5, 7, 11, 13, 17, 19, 23 and 29. Numbers that have more than two factors are called composite numbers.
The task is to determine if N is a Happy Number. A Happy number is a number defined by the following process: Start with any positive integer, replace the number with the sum of the squares of its digits. Repeat the process until the number equals 1, or it loops endlessly in a cycle which does not include 1.
A -happy prime is a number that is both -happy and prime. Unlike happy numbers, rearranging the digits of a. -happy prime will not necessarily create another happy prime. For instance, while 19 is a 10-happy prime, 91 = 13 × 7 is not prime (but is still 10-happy).
$ cat happyprimes
[happy][sad]?dsI[[I~d*rd0<H+]dsHxd4<h]dshx[r]sr1=rP[ ][ non-]_1lI[1-d2>rdlIr%0<p]dspx-2=rP[prime]p
$ echo 1 |dc happyprimes
happy non-prime
$ echo 139|dc happyprimes
happy prime
$ echo 2 |dc happyprimes
sad prime
$ echo 440|dc happyprimes
happy non-prime
$ echo 78 |dc happyprimes
sad non-prime
Print[If[Nest[Tr[IntegerDigits@#^2]&,#,9]>1,Sad,Happy],If[PrimeQ@#," "," non-"],prime]&
-- Mr.Wizard
Da monkey learnt a few tricks (91 chars)
Print[
If[Nest[Plus@@(IntegerDigits@ #^2) &, #, 9] > 1, Sad, Happy ],
If[PrimeQ@#, " ", " non-"], prime
] &
Invoke with %[7]
Nine iterations is enough. Thanks @Nabb, @mjschultz
h = Print[
If[Nest[Plus @@ (IntegerDigits@#^2) &, #, 9] > 1, "Sad ", "Happy "]
, If[PrimeQ@#, "", "non-"], "prime"] &
Same as Edit 3, replacing 10^2 by 99 (allowing 84 digits for input values) ... Thanks, @Greg
h = Print[
If[Nest[Plus @@ (IntegerDigits@#^2) &, #, 99] > 1, "Sad ", "Happy "]
, If[PrimeQ@#, "", "non-"], "prime"] &
Reworked the loop again.
It is interesting that the recursion depth until eventually reaching 1 is bounded by (15 + Number of digits of the argument). See here
So for numbers with less than 85 digits (I think this limit is pretty well into the OP's "Don't worry about handling big numbers" consideration) the following code works
h = Print[
If[Nest[Plus @@ (IntegerDigits@#^2) &, #, 10^2] > 1, "Sad ", "Happy "]
, If[PrimeQ@#, "", "non-"], "prime"] &
I changed the "NestWhile" for the shorter "Nest", and so, instead of specifying a stop condition for the recursion, is enough to hardcode the desired recursion depth (10^2).
It is not very efficient, but that's the golfer's life :D
Reworked the Sad/Happy assignment
h = Print[
If[NestWhile[Plus @@ (IntegerDigits@#^2) &, #, # > 4 &] > 1,"Sad ","Happy "]
,If[PrimeQ@#, "", "non-"]
, "prime"] &
All spaces/newlines except on literals are optional and added for readability
Explanation:
The
NestWhile[Plus @@ (IntegerDigits@#^2) &, #, # > 4 &]
Recurses applying "function" [Add up sum of digits squared] until the result is 4 or less. The function has the property that it stagnates at "1", or enters the cycle {4, 16, 37, 58, 89, 145, 42, 20, 4, ...}.
So, when the outcome is "1", the number is "Happy" and when the outcome is "4", it is "Sad".
If the result is "2", the number is also SAD, because it'll enter the SAD cycle in the next iteration (2^2 = 4).
If the result is 3, the cycle is 3->9->81->65->61->37->58->89->145-> .... (Enters the SAD loop).
So, we can stop the recursion when the result is 4 or less, knowing that only a result of "1" will lead to a Happy number.
Perhaps other solutions may take advantage of this fact.
In fact, the results 5 and 6 also lead to SAD numbers, but that gives us only an efficiency boost and not a golfing advantage (I guess).
Reworked the Loop Control logic
h = Print[
NestWhile[Plus@@(IntegerDigits@#^2) &, #, #>4 &] /.{1 →"Happy ",_→"Sad "}
, If[PrimeQ@#, "", "non-"]
, "prime"] &
h = Print[
If[NestWhile[Plus @@ (IntegerDigits@#^2) &, #, Unequal, All] == 1
,"Happy ", "Sad "],
If[PrimeQ@#, "", "non-"], "prime"] &
The statement
NestWhile[Plus @@ (IntegerDigits@#^2) &, #, Unequal, All]
performs the recursive application of the sums of the digits squared, until some value repeats. The "Unequal,All" part takes care of the comparison across the preceding values list. Finally returns the repeated value, which is "1" for Happy Numbers.
Sample run
h[7]
Happy prime
h[2535301200456458802993406410753]
Sad non-prime
Looping (Slightly changing the Print statement)
1 Happy non-prime
2 Sad prime
3 Sad prime
4 Sad non-prime
5 Sad prime
6 Sad non-prime
7 Happy prime
8 Sad non-prime
9 Sad non-prime
10 Happy non-prime
11 Sad prime
12 Sad non-prime
13 Happy prime
~:@.{0\`{15&.*+}/}*1=!"happy sad "6/=@,{@\)%!},,2=4*"non-prime">
This program does n
iterations to determine the happiness of the number, which is very wasteful for large numbers, but code-golf is not about conserving resources other than characters. The prime test is similarly inefficient - dividing n
by all the values from 1
to n
inclusive and checking that there are exactly two values with zero remainder. So while it is theoretically correct, running with really large numbers is not practical on real computers
GolfScript - 63 chars (fails for 1)
~:@9{0\`{15&.*+}/}*1=!"happy sad "6/=@,2>{@\%!},!4*"non-prime">
Beating both perl answers at this moment!
l=n=input()
while l>4:l=sum(int(i)**2for i in`l`)
print['sad','happy'][l<2],'non-prime'[4*all(n%i for i in range(2,n))*(n>1):]
I also ported this answer to GolfScript and it is just over 1/2 the size!
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With