Skip to content

Commit 5cde97e

Browse files
committed
add xml:ids to codeblocks and improve clarity
1 parent 849982d commit 5cde97e

1 file changed

Lines changed: 38 additions & 23 deletions

File tree

source/ch7_recursion.ptx

Lines changed: 38 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,31 @@
1212
<p><idx>recursion</idx>
1313
As you may know from Python, <term>recursion</term> is a powerful problem-solving technique involving base cases and recursive steps in which a function or method calls itself. When moving to Java, the core logic you've learned remains identical. The challenge is adapting that logic to Java's statically-typed, class-based syntax.
1414
</p>
15+
16+
<p>
17+
Let's take the familiar factorial function, which calculates <m>n!</m> (read as "n factorial"), so for example 5! = 5 × 4 × 3 × 2 × 1 = 120. Factorial is a classic example of recursion, where the function calls itself with a smaller value until it reaches a base case.
18+
In general, <m>n! = n \times (n-1) \times (n-2) \times \cdots \times 2 \times 1</m>,
19+
or recursively defined as <m>n! = n \times (n-1)!</m> with base cases <m>0! = 1</m> and <m>1! = 1</m>.
20+
</p>
21+
<p>
22+
You may recall mathematical notation using the symbol <m>\sum</m> (Greek letter sigma)
23+
to represent "sum." For example, when we sum all elements in an array, we write
24+
<m>\sum_{i=0}^{n-1} a_i</m>, where <m>i=0</m> below the symbol indicates we start at index 0,
25+
<m>n-1</m> above it means we end at index <m>n-1</m>, and <m>a_i</m> represents the array
26+
element at each index <m>i</m>. Similarly, <m>\sum_{i=1}^{n} i</m> means "sum all integers
27+
<m>i</m> from 1 to <m>n</m>."
28+
</p>
29+
<p>
30+
Factorial involves multiplication rather than addition, so we use the product symbol
31+
<m>\prod</m> (Greek letter pi): <m>n! = \prod_{i=1}^{n} i</m>, which means "multiply
32+
all integers <m>i</m> from 1 to <m>n</m>." Both summation and factorial can be expressed
33+
recursively—summation as the first element plus the sum of remaining elements, and factorial
34+
as <m>n \times (n-1)!</m>.
35+
</p>
1536
<p>
16-
Let's take the familiar factorial function (which calculates the factorial of a number, namely the product of all positive integers from 1 to n). The logical steps in the code are the same, but the implementation details change.
17-
</p>
18-
<p>
19-
Here is a Python implementation using functions:
37+
Here is a Python implementation of factorial using functions:
2038
</p>
21-
<program interactive="activecode" language="python">
39+
<program xml:id="factorial-python-function" interactive="activecode" language="python">
2240
<code>
2341
def factorial(n):
2442
# Check for negative numbers
@@ -42,7 +60,7 @@ main()
4260
<p>
4361
Many Python programs organize related functions into classes. The same factorial function can be placed inside a class as a method. Then you need to create an instance of the class to call the method. There we create the class <c>MathTools</c> with a method <c>factorial</c>, and we call it from the <c>main</c> function.
4462
</p>
45-
<program interactive="activecode" language="python">
63+
<program xml:id="factorial-python-class" interactive="activecode" language="python">
4664
<code>
4765
class MathTools:
4866
def factorial(self, n):
@@ -72,7 +90,7 @@ main()
7290
<p>
7391
Here is the equivalent Java code:
7492
</p>
75-
<program interactive="activecode" language="java">
93+
<program xml:id="factorial-java-class" interactive="activecode" language="java">
7694
<code>
7795
public class MathTools {
7896
public static int factorial(int n) {
@@ -105,19 +123,17 @@ public class MathTools {
105123
<title>Using Helper Methods</title>
106124

107125
<p>
108-
In many recursive algorithms, the recursive calls need extra information that the original caller shouldn't have to provide. For example, to recursively process an array, you need to keep track of the current position (index). This extra information clutters the public-facing method signature and forces users to provide implementation details they shouldn't need to know about.
126+
In many recursive algorithms, the recursive calls need extra information that the original caller shouldn't have to provide. For example, to recursively process an array, you need to keep track of the index of the current position. This extra information clutters the public-facing signature by forcing users to provide implementation details they shouldn't actually need to know about.
109127
</p>
110128
<p><idx>helper method pattern in recursion</idx>
111-
A common pattern to solve this is using a <term>helper method</term>. This pattern lets you create a clean, simple public method that users will call, while the private helper method handles the complex details of the recursion. The public method typically makes the initial call to the private helper, providing the necessary starting values for the extra parameters.
112-
</p>
113-
<p>
114-
Let's see this pattern in action with an example that calculates the sum of all elements in an integer array. Notice how the public method only requires the array, but the recursive logic needs to track the current index position.
129+
A common pattern to solve this problem is by using a <term>helper method</term>. This pattern lets you create a clean, simple function or public method that users can call, while the private helper function or method handles the complex details of the recursion. The function or public method typically makes an initial call to the private helper method or function, providing the necessary starting values for the extra parameters.
115130
</p>
131+
116132

117133
<p>
118134
First, let's see what happens if we try to write a recursive array sum function <em>without</em> using a helper method. In this approach, the user must provide the starting index, which is awkward and exposes implementation details:
119135
</p>
120-
<program interactive="activecode" language="python">
136+
<program xml:id="array-sum-python-no-helper" interactive="activecode" language="python">
121137
<code>
122138
class ArrayProcessor:
123139
def sum_array(self, arr, index):
@@ -144,9 +160,9 @@ main()
144160
</program>
145161

146162
<p>
147-
This approach has several problems: users must remember to start with index 0, the method signature is cluttered with implementation details, and it's easy to make mistakes by passing the wrong starting index. The same awkward pattern appears in Java:
163+
This approach has a significant problem, namely that users must remember to start with index 0. Hence, the method signature is cluttered with an implementation detail, and it's easy to make a mistake by passing the wrong starting index. The same awkward pattern appears in Java:
148164
</p>
149-
<program interactive="activecode" language="java">
165+
<program xml:id="array-sum-java-no-helper" interactive="activecode" language="java">
150166
<code>
151167
public class ArrayProcessor {
152168
public static int sumArray(int[] arr, int index) {
@@ -170,13 +186,12 @@ public class ArrayProcessor {
170186
</program>
171187

172188
<p>
173-
Both versions force users to understand and provide implementation details they shouldn't need to know about. Now let's see how helper methods solve this problem by providing a clean, user-friendly interface.
189+
Both versions force users to understand and provide implementation details they shouldn't need to know about. Now let's see how helper methods solve this problem by providing a clean, user-friendly interface. Notice how the public method only requires the array itself, and the hidden recursive logic tracks the current index position.
174190
</p>
175-
176191
<p>
177192
Here's the improved Python version using a helper method:
178193
</p>
179-
<program interactive="activecode" language="python">
194+
<program xml:id="array-sum-python-with-helper" interactive="activecode" language="python">
180195
<code>
181196
class ArrayProcessor:
182197
def sum_array(self, arr):
@@ -212,13 +227,13 @@ main()
212227
</program>
213228

214229
<p><idx>separation of concerns</idx>
215-
The key insight here is called the <term>separation of concerns</term>. The public <c>sum_array</c> method provides a user-friendly interface—callers just pass an array and get the sum. They don't need to know about indexes or how the recursion works internally. The private <c>_sum_helper</c> method handles the recursive logic with the extra parameter needed to track progress through the array.
230+
The key insight here is called the <term>separation of concerns</term>. The public <c>sum_array</c> method provides a user-friendly interface—callers just pass an array and get the sum. Users don't need to know about indexes or how the recursion works internally. The private <c>_sum_helper</c> method handles the recursive logic with the extra parameter needed to track progress through the array.
216231
</p>
217232

218233
<p>
219234
Now let's see the improved Java version using a helper method:
220235
</p>
221-
<program interactive="activecode" language="java">
236+
<program xml:id="array-sum-java-with-helper" interactive="activecode" language="java">
222237
<code>
223238
public class ArrayProcessor {
224239
public static int sumArray(int[] arr) {
@@ -254,7 +269,7 @@ public class ArrayProcessor {
254269
</p>
255270

256271
<p>
257-
This helper method pattern is essential when your recursive algorithm needs to track additional state (like array positions, accumulated values, or depth counters) that the original caller shouldn't need to provide. It's a fundamental technique you'll use frequently in recursive problem solving.
272+
This helper method pattern is essential when your recursive algorithm needs to track additional state (like array positions, accumulated values, or depth counters) that the original caller shouldn't need to provide or care about. It's a fundamental pattern and technique you'll likely use frequently in recursive problem solving.
258273
</p>
259274
</section>
260275

@@ -276,7 +291,7 @@ public class ArrayProcessor {
276291
<p>
277292
The following Python code demonstrates a situation where a function calls itself indefinitely without a base case, leading to aRecursionError.
278293
</p>
279-
<program interactive="activecode" language="python">
294+
<program xml:id="python-recursion-error" interactive="activecode" language="python">
280295
<code>
281296
def cause_recursion_error():
282297
"""
@@ -297,7 +312,7 @@ public class ArrayProcessor {
297312
<p>
298313
The following Java code demonstrates a similar situation, where a method calls itself indefinitely without a base case, leading to a StackOverflowError.
299314
</p>
300-
<program interactive="activecode" language="java">
315+
<program xml:id="java-stack-overflow" interactive="activecode" language="java">
301316
<code>
302317
public class Crash {
303318
public static void causeStackOverflow() {

0 commit comments

Comments
 (0)