Step 1: 1+7+2+9 = 19
Step 2: 1+9 = 10
Step 3: 1+0 = 1
Because the total at the end of step 3 is the single digit 1, that value is the digital root.
Rewrite the DigitSum program shown in Figure 4-6 so that it calculates the digital root of the imput value." (Roberts ch 4, exercise 7).
Here's the code:
What the output looks like:
What made it tough:
1) A loop of loops:
As was mentioned in the question, this problem builds off an example program given in the text to sum the digits of any given integer, which is any one of the steps 1 through 3 in the explanation. The sample problem gave us what would be the inner while loop of this program. The trick was to create a loop of loops that would take the solution from step 1 and feed it back through the inner loop to find the output for step 2, and so on.
I had a go at it at first by writing it as three individual loops:
public class DigitalRoot extends ConsoleProgram {
public void run () {
println("This program finds the digital root of an integer.");
int n = readInt("Enter a positive integer: ");
int dsum = 0;
while (n > 0) {
dsum += n % 10;
n /= 10;
}
/*NEED: If dsum is > 10, send it back thru the while loop. (How?...)
If dsum < 10, print "The digital root is" + dsum.*/
int o = dsum;
dsum = 0;
while (o > 0) {
dsum += o % 10;
o /= 10;
}
int p = dsum;
dsum = 0;
while (p > 0) {
dsum += p % 10;
p /= 10;
}
println("The digital root is " + dsum);
}
}
public void run () {
println("This program finds the digital root of an integer.");
int n = readInt("Enter a positive integer: ");
int dsum = 0;
while (n > 0) {
dsum += n % 10;
n /= 10;
}
/*NEED: If dsum is > 10, send it back thru the while loop. (How?...)
If dsum < 10, print "The digital root is" + dsum.*/
int o = dsum;
dsum = 0;
while (o > 0) {
dsum += o % 10;
o /= 10;
}
int p = dsum;
dsum = 0;
while (p > 0) {
dsum += p % 10;
p /= 10;
}
println("The digital root is " + dsum);
}
}
The program worked only for inputs of 4 digits, since there are three loops. For a long time, I couldn't figure out how to get the output of one of the loops to cycle back up and go through the loop again.
2) Debugging:
Once I made up a loop of loops and used the temp variable (thanks to inspiration from the comments to Fib Seq), this problem gave me the damndest time when it came to debugging. For a long time after I sketched out the strategy and wrote my code, I'd run the program, enter the output, and got nothing; my program would just blink stupidly at me.
Usman showed me the clever tip to debug by printing lines of text at different stages of the program:
//DEBUG:
println("Entering OUTER loop: n= "+ n +" dsum= "+dsum +" temp= "+temp);
while (temp > 9) {
n = temp;
dsum = 0;
//DEBUG:
println("Entering INNER loop: n= "+ n +" dsum= "+dsum+" temp= "+temp);
while (n >= 0) {
dsum += n % 10;
n /= 10;
//DEBUG:
println(" End INNER loop: n= "+ n +" dsum= "+dsum+" temp= "+temp);
}
temp = dsum;
}
Inserting the debut text gave this output:
We had told the program to print text when a) it got to entering the outer loop, b) it entered the inner loop, and c) it exited the inner loop. Since the third line of text never got printed, that told me that the program was getting stuck somewhere in the inner loop. Specifically, it was getting stuck when it got to n = 0, since of the condition to keep the loop running was n>=0.
Here's what the debug code looks like when fixed:
Time to completion: I read the problem and worked on it for an hour every night last week.
Lingering questions: How come this took so damn long!