2
$\begingroup$

I am trying to write a recursive function, toscare1[], that takes as parameter a positive natural number. Then calculate the sum of the squares of its digits, thus creating a new number; then, we repeat the procedure on this new number, etc., until one of the following cases happens: the sum becomes 1 or becomes 4. Then, the function should return the number of times we performed the procedure. This is what I have tried so far

toscare1[n_] := {
  For[i = 0, 
   NestWhile[ne = Total[IntegerDigits[#]^2] &, n, ne == 1 || ne == 4],
    i++, Print[i]]
  }
$\endgroup$
2
  • 4
    $\begingroup$ You are quite close. f[n_] := {Length@# - 1, #} &@ NestWhileList[Plus @@ (IntegerDigits[#]^2) &, n, # != 1 && # != 4 &] Usage: e.g., f[2331] $\endgroup$
    – Syed
    Dec 2, 2022 at 18:28
  • 1
    $\begingroup$ Maybe closer to your original but similar to Syed: toscare1[n_] := Length[NestWhileList[(Total[IntegerDigits[#]^2]) &, n, (! (# == 1 || # == 4)) &]] - 1 $\endgroup$ Dec 2, 2022 at 18:58

1 Answer 1

3
$\begingroup$

Syed's comment has priority, but I thought it would be useful to provide a bit of flavor. Before jumping to a one-liner, it's often useful (and easier) to break the problem up into smaller functions. You know how to do a single step in your calculation, so start by turning that into a function:

toscareStep[int_Integer] := Total[IntegerDigits[int]^2]

toscareStep[2331] gives 23.

At this point, you could build your own recursion, but Mathematica has several nice functions for repeated application: Nest, NestList, NestWhile, NestWhileList, FixedPoint, FixedPointList.

For example, NestList[toscareStep, 2331, 10] gives {2331, 23, 13, 10, 1, 1, 1, 1, 1, 1, 1}. This looks promising, because you can count the members of the list.

You want to terminate on a condition, so use the While version.

NestWhileList[toscareStep, 2331, (# != 4 && # != 1) &]

gives {2331, 23, 13, 10, 1}

To get the "number of times we performed the procedure", we need to take Length - 1, because the first element of NestWhileList was the input (i.e. no steps performed yet at that point). So,

toscareStepCount[int_Integer] := 
  -1 + Length[NestWhileList[toscareStep, int, (# != 4 && # != 1) &]]

For example, toscareStepCount[2331] gives 4. This approach "throws away" the record of each step, and that record is often useful. So, you might want something more like this:

toscareStepList[int_Integer] := NestWhileList[toscareStep, int, (# != 4 && # != 1) &];
toscareStepCount[int_Integer] := -1 + toscareStepList[int]

If you wanted to build your own recursive implementation, the typical way to do something like this is to use an accumulator (in this case a simple counter):

toscareStepCount[val_Integer] := toscareStepCount[val, 0];
toscareStepCount[1, count_Integer] := count;
toscareStepCount[4, count_Integer] := count;
toscareStepCount[current_Integer, count_Integer] := 
  toscareStepCount[toscareStep[current], 1 + count]
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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