Triangular Numbers: Finding The NTH Term Using A Loop
Triangular Numbers: Finding The NTH Term Using A Loop
Module 6: Recursion
Triangular Numbers
It's said that the Pythagorians, a band of mathematicians in ancient Greece who worked under Pythagoras (of Pythagorian
theorem fame), felt a mystical connection with the series of numbers 1, 3, 6, 10, 15, 21, … (where the … means the series
continues indefinitely). Can you find the next member of this series?
The nth term in the series is obtained by adding n to the previous term. Thus the second term is found by adding 2 to the
first term (which is 1), giving 3. The third term is 3 added to the second term (which is 3), giving 6, and so on. The numbers
in this series are called triangular numbers because they can be visualized as a triangular arrangements of objects, shown as
little squares in Figure 6.1.
Finding the nth Term Using a Loop
Suppose you wanted to find the value of some arbitrary nth term in the series; say the fourth term (whose value is 10). How
would you calculate it? Looking at Figure 6.2, you might decide that the value of any term can be obtained by adding up all
the vertical columns of squares.
In the fourth term, the first column has four little squares, the second column has three, and so on. Adding 4+3+2+1 gives
10.
return total;
}
The method cycles around the loop n times, adding n to total the first time, n-1 the second time, and so on down to 1,
quitting the loop when n becomes 0.
Module 6: Recursion
Data Structures and Algorithms in Java 2
Notice in Figure 6.3, however, that the sum of all the remaining columns for term n is the same as the sum of all the
columns for term n-1. Thus, if we knew about a method that summed all the columns for term n, we could call it with an
argument of n-1 to find the sum of all the remaining columns for term n:
int triangle(int n)
{
return( n + sumAllColumns(n-1) ); // (incomplete version)
}
But when you think about it, the sumAllColumns() method is doing exactly the same thing the triangle() method is
doing: summing all the columns for some number n passed as an argument. So why not use the triangle() method itself,
instead of some other method? That would look like this:
int triangle(int n)
{
return( n + triangle(n-1) ); // (incomplete version)
}
It may seem amazing that a method can call itself, but why shouldn't it be able to? A method call is (among other things) a
transfer of control to the start of the method. This transfer of control can take place from within the method as well as from
outside.
Passing the Buck
All this may seem like passing the buck. Someone tells me to find the 9th triangular number. I know this is 9 plus the 8th
triangular number, so I call Harry and ask him to find the 8th triangular number. When I hear back from him, I'll add 9 to
whatever he tells me, and that will be the answer.
Harry knows the 8th triangular number is 8 plus the 7th triangular number, so he calls Sally and asks her to find the 7th
triangular number. This process continues with each person passing the buck to another one.
Where does this buck-passing end? Someone at some point must be able to figure out an answer that doesn't involve asking
another person to help them. If this didn't happen, there would be an infinite chain of people asking other people questions;
a sort of arithmetic Ponzi scheme that would never end. In the case of triangle(), this would mean the method calling
itself over and over in an infinite series that would paralyze the program.
The Buck Stops Here
To prevent an infinite regress, the person who is asked to find the first triangular number of the series, when n is 1, must
know, without asking anyone else, that the answer is 1. There are no smaller numbers to ask anyone about, there's nothing
left to add to anything else, so the buck stops there. We can express this by adding a condition to the triangle() method:
int triangle(int n)
Module 6: Recursion
Data Structures and Algorithms in Java 3
{
if(n==1)
return 1;
else
return( n + triangle(n-1) );
}
The condition that leads to a recursive method returning without making another recursive call is referred to as the base
case. It's critical that every recursive method have a base case to prevent infinite recursion and the consequent demise of the
program.
The triangle.java Program
Does recursion actually work? If you run the triangle.java program, you'll see that it does. Enter a value for the term
number, n, and the program will display the value of the corresponding triangular number. Listing 6.1 shows the
triangle.java program.
System.out.flush();
theNumber = getInt();
System.out.println("Triangle="+theAnswer);
} // end main()
//-------------------------------------------------------------
//-------------------------------------------------------------
//-------------------------------------------------------------
//-------------------------------------------------------------
The main() routine prompts the user for a value for n, calls triangle(), and displays the return value. The triangle()
method calls itself repeatedly to do all the work.
Here's some sample output:
Enter a number: 1000
Triangle = 500500
What's Really Happening?
Module 6: Recursion
Data Structures and Algorithms in Java 4
Let's modify the triangle() method to provide an insight into what's happening when it executes. We'll insert some
output statements to keep track of the arguments and return values:
public static int triangle(int n)
{
System.out.println("Entering: n=" + n);
if(n==1)
{
System.out.println("Returning 1");
return 1;
}
else
{
int temp = n + triangle(n-1);
System.out.println("Returning " + temp);
return temp;
}
}
Here's the interaction when this method is substituted for the earlier triangle() method and the user enters 5:
Enter a number: 5
Entering: n=5
Entering: n=4
Entering: n=3
Entering: n=2
Entering: n=1
Returning 1
Returning 3
Returning 6
Returning 10
Returning 15
Triangle = 15
Each time the triangle() method calls itself, its argument, which starts at 5, is reduced by 1. The method plunges down
into itself again and again until its argument is reduced to 1. Then it returns. This triggers an entire series of returns. The
method rises back up, phoenixlike, out of the discarded versions of itself. Each time it returns, it adds the value of n it was
called with to the return value from the method it called.
The return values recapitulate the series of triangular numbers, until the answer is returned to main(). Figure 6.4 shows how
each invocation of the triangle() method can be imagined as being "inside" the previous one.
Notice that, just before the innermost version returns a 1, there are actually five different incarnations of triangle() in
existence at the same time. The outer one was passed the argument 5; the inner one was passed the argument 1.
Module 6: Recursion
Data Structures and Algorithms in Java 5
Module 6: Recursion