-
Notifications
You must be signed in to change notification settings - Fork 32
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Janice Lichtman - Recursion Tracing #25
base: master
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,15 +1,28 @@ | ||
# Recursion Problems | ||
|
||
## Definitions | ||
Define the following: | ||
Define the following: | ||
|
||
- Recursion | ||
- Recursive Case | ||
- Base Case | ||
- Activation Chain/Stack | ||
- Activation Record/Call | ||
- Infinite Recursion/Stack Overflow/Stack too deep | ||
- Tail Recursion | ||
- Recursion: | ||
A method that calls itself. (In general, any self-referential process or definition) | ||
- Recursive Case: | ||
The case in a recursive method, where the recursion happens (ie where the method itself is called.) | ||
- Base Case: | ||
The case in a recursive method, where no recursion happens. | ||
Generally successive terations of the recursive case bring you closer to the base case, and the base case is where the method evaluation finally terminates. | ||
- Activation Chain/Stack: | ||
The entire chain of successive iterations of the recursive case and the eventual base case that are evaluated when the method is invoked. | ||
- Activation Record/Call: | ||
A single evaluation of the recursive case in the process of evaluating a recursive method (ie one step in the activation chain/stack.) | ||
- Infinite Recursion/Stack Overflow/Stack too deep: | ||
If the recursive case does not bring the method evaluation closer to the base case on successive iterations, then the recursion will continue 'infinitely'. In practice, it will continue until the allotted memory is full, and a 'stack overflow'/'stack too deep' error will be thrown, terminating the process. | ||
- Tail Recursion: | ||
Tail Recursion is where calculations are made at every step in the recursive case, and the result is then passed to the next call of the method. It is different from traditional recursion where the full chain of recursive calls must be made before the calculations begin. | ||
|
||
In other words, in Traditional Recursion, the full chain of recursive calls are made and held in the stack. Then, once the base case is reached, calculations begin and the results for each record are passed back up the chain. | ||
In Tail Recursion, however, calculations are made along the way and only the results are passed to successive recursive cases. (Ie,in Tail Recursion, no calculations happen on the return line). | ||
|
||
The benefit of Tail Recursion, in languages that support it, is that the compiler does not need to keep track of the entire activation chain/stack. Instead, at each recursive step, it can simply replace the data and reuse the 'current stack frame'. | ||
|
||
## Tracing through a recursive method | ||
|
||
|
@@ -24,9 +37,10 @@ def mystery1(n) | |
end | ||
``` | ||
|
||
- What is mystery1(5)? | ||
- What is mystery1(10)? | ||
- What is mystery1(0)? | ||
- What is mystery1(5)? 15 | ||
- What is mystery1(10)? 55 | ||
- What is mystery1(0)? Infinite Recursion- | ||
SystemStackError: stack level too deep | ||
|
||
### Trace #2 | ||
``` | ||
|
@@ -39,11 +53,25 @@ def mystery2(n) | |
end | ||
``` | ||
|
||
- What is mystery2(123)? | ||
- What is mystery2(9005)? | ||
- What is mystery2(-123)? | ||
- What is mystery2(123)? 6 | ||
- What is mystery2(9005)? 14 | ||
- What is mystery2(-123)? -123 | ||
- _Added Fun: How could we make `mystery2(-123)` work the way we might expect it to work instead of the way it does?_ | ||
|
||
We could "ignore the negative sign" while we sum the digits and then replace it at the end. This could be done as follows: | ||
|
||
def mystery2B(n) | ||
if n < 10 && n > -10 | ||
return n | ||
elsif n >= 10 | ||
return (n%10) + mystery2(n/10) | ||
else m = n.abs | ||
a = (m%10) + mystery2(m/10) | ||
return -a | ||
end | ||
end | ||
|
||
|
||
### Trace #3 | ||
``` | ||
def mystery3(n) | ||
|
@@ -60,9 +88,9 @@ def mystery3(n) | |
end | ||
``` | ||
|
||
- What is mystery3(1)? | ||
- What is mystery3(13)? | ||
- What is mystery3(-6)? | ||
- What is mystery3(1)? 100 | ||
- What is mystery3(13)? 100 | ||
- What is mystery3(-6)? 200 | ||
|
||
### Trace #4 | ||
``` | ||
|
@@ -75,9 +103,9 @@ def mystery4(b,e) | |
end | ||
``` | ||
|
||
- What is mystery4(10,2)? | ||
- What is mystery4(4,3)? | ||
- What is mystery4(5,0)? | ||
- What is mystery4(10,2)? 100 | ||
- What is mystery4(4,3)? 64 | ||
- What is mystery4(5,0)? 1 | ||
|
||
### Trace #5 | ||
``` | ||
|
@@ -90,10 +118,24 @@ def mystery5(s) | |
end | ||
``` | ||
|
||
- What is mystery5("hi")? | ||
- What is mystery5("")? | ||
- What is mystery5("Hi, there!")? | ||
- What is mystery5("hi")? ** | ||
- What is mystery5("")? "" (ie, empty string) | ||
- What is mystery5("Hi, there!")? ********** | ||
|
||
- _Added Fun: How could we make only alphabetic characters to be changed to stars?_ | ||
def mystery5C(s) | ||
alpha_all = ("A".."Z").to_a.concat ("a".."z").to_a | ||
if s.length == 0 | ||
return "" | ||
else | ||
if alpha_all.include?(s[0]) | ||
return "*" + mystery5C(s[1..-1]) | ||
else | ||
return mystery5C(s[1..-1]) | ||
end | ||
end | ||
end | ||
|
||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This looks like it works. I did post another solution to consider. One thing is to figure out if you think I intended mystery5("Hi, there!") to produce "*******" or "**, *****!" I intended the latter, but didn't specify so you+others assumed and wrote solutions for the former. |
||
|
||
### Trace #6 | ||
``` | ||
|
@@ -110,7 +152,20 @@ def mystery6(s) | |
end | ||
``` | ||
|
||
- What is mystery6("goodnight moon")? | ||
- What is mystery6("goodnight moon")? | ||
" moon goodnight" (note: includes initial underscore) | ||
- What is mystery6("Ada Developers Academy")? | ||
" Academy Developers Ada" | ||
- What is mystery6("Hi, there!")? | ||
" there! Hi," | ||
|
||
- _Added Fun: How could we make the reversal happen by letter, instead of by word (i.e. Make it so that mystery6("goodnight moon") returned "noom thgindoog")?_ | ||
|
||
|
||
def mystery6B(s) | ||
if s == nil || s.length == 0 | ||
return "" | ||
else | ||
return mystery6B(s[1..-1]) + s[0] | ||
end | ||
end | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. +1 my solution too. Though I wrote the base case differently, they are essentially the same. I didn't account for nil though. |
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,7 @@ | ||
require 'pry' | ||
|
||
alpha_all = ("A".."Z").to_a.concat ("a".."z").to_a | ||
print alpha_all | ||
|
||
s="hi there" | ||
binding.pry |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This looks like it works. I also just posted an alternative solution that is perhaps more readable.