# What's wrong when I use NestWhileList?

Problem :

A Happy number is a number that if one squares its digits and add them together, and then take the result and square its digits and add them together again and keep doing this process, one comes down to the number 1. Find all the Happy ages, i.e., happy numbers up to 100.

This is the problem the book gave, and the solution of the author is shown below:

f[1] = 1;
f[4] = 4;
f[n_] := f[Plus @@ ( IntegerDigits[n]^2)]
Select[Range[100], f[#] == 1 &]
(*
{1, 7, 10, 13, 19, 23, 28, 31, 32, 44, 49, 68, 70, 79, 82, 86, 91, 94, 97, 100}
*)


But I want to use a different method from the author.

Select[Range[100], NestWhile[Plus @@ (IntegerDigits[#]^2 &), # &, # != 1 &]]
(*{}*)


However, I do not know where it went wrong. Could someone help me? Thanks!

The second argument of Select must be a function, and it must return True for your element to be selected. Your expression:

NestWhile[Plus @@ (IntegerDigits[#]^2 &), # &, # != 1 &]


Evaluates to:

#1 &


Which is a function, but it is a function that merely returns its first argument. This is because you incorrectly used # & rather than # as the second argument of NestWhile. Also, as Pinguin Dirk noted you forgot to account for the 4 exist value of non-happy numbers which will lead to an infinite loop Try this instead:

Select[
Range@100,
1 == NestWhile[Tr[IntegerDigits[#]^2] &, #, # != 1 && # != 4 &] &
]


I used Tr instead of Plus @@ to make the code a bit more compact.
To break this down down a bit to make it easier to read:

squareAndSum = Tr[IntegerDigits[#]^2] &;

termination  = # != 1 && # != 4 &;

test = 1 == NestWhile[squareAndSum, #, termination] &;

Select[Range @ 100, test]

• I still got confused why you included !=4 in the code. Can you explain it? Also, when doing this problem, how do we know that we must include 4 in our code? It seems to come out of nowhere. Commented Aug 21, 2014 at 6:30
• @Lawerance See en.wikipedia.org/wiki/Happy_number -- "If n is not happy, then its sequence does not go to 1. Instead, it ends in the cycle: 4, 16, 37, 58, 89, 145, 42, 20, 4, ... " We must account for that cycle and terminate when 4 appears or we have an infinite loop. Commented Aug 21, 2014 at 6:59

I think this deals with cyclic behaviour and accomplishes aim using NestWhileList

fun[x_] := #.# &@(IntegerDigits@x)
Cases[NestWhileList[fun, #, UnsameQ[##] &, All] & /@ Range[100],
x_?(Last@# == 1 &) :> x[[1]]]


yielding:

{1, 7, 10, 13, 19, 23, 28, 31, 32, 44, 49, 68, 70, 79, 82, 86, 91, \
94, 97, 100}


Note 7 and 70 have the longest (and same) route to happiness (5 applications): 7 or 70, 49-, 97, 130, 10, 1