2

Really confused by how one should use the Module[] command in two variables. For example my function here should return the DigitalRoot of a number; i.e. func[5432] -> 14 -> 5 or for func[23] -> 5.

My example uses the Module command but the solution is wrong;

Fox[a_] := Module[
  {x1, x2},
  x1 = 0; 
  x2 = a; 
  While[
    x1 != 1, 
    x1 = Length[IntegerDigits[x2]]; 
    x2 = Total[InterDigits[x2]]; 
    Return[x2]
  ]
] 

The Module[] and While[] don't appear to loop, so Fox[5432] = 5432 and Fox[23] = 23.

Maybe my understanding of the Module[] command is wrong.

Please help

Thies Heidecke
  • 8,814
  • 34
  • 44
user57592
  • 21
  • 2

3 Answers3

9

Your approach works fine, aside from one typo, InterDigits, and the fact that you have a Return inside the While statement, when you rarely need to use Return at all.

Fox[a_] := Module[
    {x1, x2},
    x1 = 0;
    x2 = a;
    While[x1 =!= 1,
        x1 = Length[ IntegerDigits[ x2 ] ];
        x2 = Total[ IntegerDigits[ x2 ] ];
    ];
    (* no need to use Return, just return the value *)
    x2
]
Jason B.
  • 68,381
  • 3
  • 139
  • 286
6

better way..

Fox[a_] :=
 NestWhile[Total@IntegerDigits@# & , a , 
  Length@IntegerDigits@# != 1 & ]

or

Fox[a_] :=
  NestWhile[Total@IntegerDigits@# & , a , # > 10 & ]
george2079
  • 38,913
  • 1
  • 43
  • 110
  • I like the functional style! You could use the infix composition @* to make it pointfree, e.g. Total@*IntegerDigits or even (IntegerDigits/*Length/*(Not@*EqualTo[1])) :) – Thies Heidecke Apr 17 '18 at 21:22
2

I am not sure what your scoping is attempting to accomplish. If your question needs to be solved with a scoping construct, I'm not sure where to go, but you might want to try

singDigitNumberSum[num_] := If[
    Length[IntegerDigits[num]] === 1, 
    num, 
    singDigitNumberSum[Total[IntegerDigits[num]]]
]

with an appropriate $RecursionLimit.

kjosborne
  • 1,008
  • 7
  • 9