Reputation: 33
I am trying to define a recursive geometric function that will ask the user the first value of the sequence and the multiplier value for the sequence. The function should give a sequence of the desired length as the argument and produce as the return value a list of the arbitrary Geometric sequence of that length. As a clarifying example, if the user provides 5 as the start value and 3 as the multiplier with the desired length of 6, the first 6 elements of the arbitrary geometric sequence would be [5, 15, 45, 135, 405, 1215]
When I run this code, I get the sequence in weirdly random order. This is my code so far:
# This will define a recursive arbitrary Geometric sequence function
def recursive_geo_helper(length):
start = int(input("Enter the first value of the sequence: "))
multiplier = int(input("Enter the value that must be multiplied: "))
return actual_recursive_geo(length, start, multiplier)
def actual_recursive_geo(length, start, multiplier):
sequence = []
# print(start)
if length <= 1:
exit()
# return sequence
else:
sequence.append(start)
start = start * multiplier
length = length - 1
return actual_recursive_geo(length, start, multiplier)
#recursive_geo_helper(5)
print(recursive_geo_helper(6))
Upvotes: 0
Views: 286
Reputation: 12793
I believe your problem is that you're declaring the sequence in the function and not returning it correctly.
Also if we've going to use recursion we can go one step further and avoid mutating our variables by only passing through the modified variables to the recursive call.
def geo(sequence, length, multiplier):
if length <= 1:
return sequence
else:
return sequence + geo([sequence[-1] * multiplier], length - 1, multiplier)
Here's the output from the REPL:
>>> geo([5], 6, 3)
[5, 15, 45, 135, 405, 1215]
P.S. I'm more of a JavaScript than a Python guy, so I first did it in JS and then ported it.
This is the equivalent function in JavaScript:
function geo(sequence, length, multiplier) {
if (length <= 1) {
return sequence
}
return sequence.concat(geo([sequence.slice(-1) * multiplier], length - 1, multiplier))
}
console.log(geo([5], 6, 3))
Upvotes: 0
Reputation: 22294
Your code unfortunately does not make much sense. Here are just some issues with it: the builtin exit
should never be used outside of the shell, your function returns no base case and even if it did, it would not recursively appends to that base case.
Solving all these issues, here is what your recursive solution would look like.
def actual_recursive_geo(length, a, r):
if length <= 0:
return [] # base case
else:
return [a] + actual_recursive_geo(length - 1, a * r, r) # prepend to your base case
Although this is somewhat inefficient since it does a lot of unnecessary list concatenation..
Let me recommend to start from scratch using a better suited data structure to represent infinite sequences: generators.
Generators can lazily represent infinite sequences. Moreover Python provides you with the itertools
standard library to manipulate them. Here we will return a generator and slice it with itertools.islice
.
import itertools
def geometric_input():
"""
Prompt the user for an initial value and a ratio
Return the corresponding geometric series
"""
a = int(input("Enter the first value of the sequence: "))
r = int(input("Enter the ratio: "))
return geometric_sequence(a, r)
def geometric_sequence(a, r):
""" Return a generator for the sequence x_i = a * r ^ i"""
r_exp = 1
while True:
yield a * r_exp
r_exp *= r
seq = geometric_input()
first_elements = list(itertools.islice(seq, 6))
print(*first_elements)
Here is the output.
Enter the first value of the sequence: 5
Enter the ratio: 3
5 15 45 135 405 1215
Another nice thing about generators is that an element is consumed on generation. This means that if you slice the generator again, you will get the next elements in the sequence
next_elements = list(itertools.islice(seq, 6))
print(*next_elements)
# prints: 3645, 10935, 32805, 98415, 295245, 885735
Upvotes: 3