Finding minimum value in a list recursively [duplicate] - python

This question already has answers here:
Recursive method to find the minimum number in a list of numbers
(6 answers)
Closed 5 years ago.
I'm trying to find the minimum value in a list recursively. Since I'm still new in adapting to the recursive method, I would like to seek some help regarding my line of code:
listA = [9,-2,6,1,80,9,-2]
def findMinimum(l):
if len(l) == 1:
return l
else:
minNumber = findMinimum(l-1)
min = listA[0]
for i in listA:
if listA[i]<listA[i+1]:
min = listA[i]
return min
findMinimum(listA)
I'll appreciate if anyone could help me out as I'm relatively new to recursion and my understanding is definitely up to standard.

The first part of your function is correct. But you should change the second part like this:
listA = [9,-2,6,1,80,9,-2]
def findMinimum(l):
if len(l) == 1:
return l[0]
else:
return min(l[0], findMinimum(l[1:]))
findMinimum(listA)
Remember, recursive functions comes to make our codes simpler and easier.

The structure of your code is about right, but it has some mistakes. First, you should not be using listA inside of your function; listA is passed as an argument from the outside, and from within the function you should only refer to l. In the non-recursive case (where len(l) == 1), you should return l[0] (the minimum of a list with one element is that one element). Then, it is correct to call findMinimum inside your function again (that's the recursive call, as you know); however, what you probably want is to call it with the all the list l except the first element, that is, l[1:]. Then, you should compare the result minNumber to the first element of l; the idea is that you pick the smallest of l[0] and the minimum in l[1:]. Then you return the one you have chosen.
Additionally, you may want to consider the case when you get an empty list and throw an error; if you don't, you may get into an infinite recursion!
So a possible solution could be something like this:
listA = [9,-2,6,1,80,9,-2]
def findMinimum(l):
if len(l) == 0:
raise ValueError('Cannot find the minimum of an empty list.')
elif len(l) == 1:
return l[0]
else:
minNumber = findMinimum(l[1:])
min = l[0]
if minNumber < min:
min = minNumber
return min
findMinimum(listA)

Related

Is there a reason I'm getting IndexError: list index out of range on this recursive function?

I struggle a lot with recursion and my brain doesn't seem to be able to process this question apparently. Can anyone explain why this doesn't work?
Question prompt: Write a recursive program that computes the product of all numbers in a given list.
def product(L):
if L[0]==0:
return 0
else:
if len(L) > 0:
return L[0] * product(L[1:])
I thought first checking the length would always make sure to cover the empty list case.
There are two issues.
L[0]==0 checks if the first element in the list contains the value of 0. It is not a check on the length of the list. In particular, if all of the elements in the list are nonzero, the recursive function will eventually call itself with an empty list and try to access L[0], causing an IndexError.
The empty product has a value of 1. Your base case should return 1, not 0 -- doing the latter would cause the function to always output 0.
Here is a recursive solution that fixes both of these issues:
def product(L):
if len(L) == 0:
return 1
else:
return L[0] * product(L[1:])
Edit
The other answer gives you code that will work, and succinctly points out where the problem is. This answer is intended more to show you how to figure out the solution for yourself.
/Edit
It's often a good idea to pick a very small input and try to step through it yourself, on paper. In this case let's try
product([1,2,3])
L[0] is 1, so we skip to the else, then len(L) is 3 so we return 1 * product([2,3]), and then we have
product([2,3])
which we move into again. L[0] is 2, so we skip to the else, and then len(L) is 2 so we return 2 * product([3]). All good so far.
product([3])
L[0] is 3, so skip to else, and len(L) is 1, so return 3 * product([]), and then
product([])
L[0] is... ah, there is no L[0] - L is empty. That's where the IndexError is coming from. Now you know where the error is, you can fix it - move the check for the length of the list to before that (and add a base case) and you get
def product(L):
if len(L) > 0:
if L[0] == 0:
return 0
else:
return L[0] * product(L[1:])
else:
return 1
which will work.

Recursive function returning None in Python for josephus algorithm [duplicate]

This question already has answers here:
Python recursive function returning none after completion
(3 answers)
Closed 1 year ago.
I'm programming the josephus algorithm.
The Josephus Problem is a mathematical problem in which a circle is made, its circumference formed of n people.
Starting from the person in the 0th position, each person eliminates the person to their left (the next person in the circle). The next living person then does the same, and the process is repeated until there is only one person left alive.
I used a recursive function like this :
def loopInList(L):
if len(L)>1:
i=0
while i < len(L) - 1 :
L.remove(L[i+1])
i += 1
loopInList(L[i:] + L[:i])
else:
return L[0]
def josephus(n):
L = [x for x in range(n)]
return loopInList(L)
print(josephus(9))
The problem is that it's returning me None, yet when I print L[0] instead of returning it, I have this list [2,0] which is the good result, so my algorithm works. But it only return the value of the first function loopInList called (the one that get the fresh list as argument), and with this fresh list I don't go in the else statement so it's returning None. I want my first function called to return the value returned in the last function called in the recursive loop.
Did you intend this (just added the return statement in the recursing block):
def loopInList(L):
if len(L)>1:
i=0
while i < len(L) - 1 :
L.remove(L[i+1])
i += 1
return loopInList(L[i:] + L[:i])
else:
return L[0]
def josephus(n):
L = [x for x in range(n)]
return loopInList(L)
print(josephus(9))

Extracting the subsequence of maximum length from a sequence [PYTHON] [duplicate]

This question already has an answer here:
Longest increasing unique subsequence
(1 answer)
Closed 6 years ago.
I have a sequence of values [1,2,3,4,1,5,1,6,7], and I have to find the longest subsequence of increasing length. However, the function needs to stop counting once it reaches a number lower than the previous one. The answer in this sequence in that case is [1,2,3,4]. As it has 4 values before being reset. How would I write the Python code for this?
Note: Finding the "longest increasing subsequence" seems to be a common challenge and so searching online I find a lot of solutions that would count for the entire length of the sequence, and return a subsequence of increasing values, ignoring any decrease, so in this case it would return [1,2,3,4,5,6,7]. That is not what I'm looking for.
It needs to count each subsequence, and reset the count upon reaching a number lower than the previous one. It then needs to compare all the subsequences counted, and return the longest one.
Thanks in advance.
Consider a function that generates all possible ascending subsequences, you would start with an empty list, add items until one element was less (or equal to?) the the previous at which point you save (yield) the subsequence and restart with a new subsequence.
One implementation using a generator could be this:
def all_ascending_subsequences(sequence):
#use an iterator so we can pull out the first element without slicing
seq = iter(sequence)
try: #NOTE 1
last = next(seq) # grab the first element from the sequence
except StopIteration: # or if there are none just return
#yield [] #NOTE 2
return
sub = [last]
for value in seq:
if value > last: #or check if their difference is exactly 1 etc.
sub.append(value)
else: #end of the subsequence, yield it and reset sub
yield sub
sub = [value]
last = value
#after the loop we send the final subsequence
yield sub
two notes about the handling of empty sequences:
To finish a generator a StopIteration needs to be
raised so we could just let the one from next(seq) propegate out - however when from __future__ import generator_stop is in
effect it would cause a RuntimeError so to be future compatible we
need to catch it and explicitly return.
As I've written it passing an empty list to
all_ascending_subsequences would generate no values, which may not
be the desired behaviour. Feel free to uncomment the yield [] to
generate an empty list when passed an empty list.
Then you can just get the longest by calling max on the result with key=len
b = [1,2,3,4,1,5,1,6,7]
result = max(all_ascending_subsequences(b),key=len)
print("longest is", result)
#print(*all_ascending_subsequences(b))
b = [4,1,6,3,4,5,6,7,3,9,1,0]
def findsub(a):
start = -1
count = 0
cur = a[0]
for i, n in enumerate(a):
if n is cur+1:
if start is -1:
start = i - 2
count=1
count+=1
cur = n
if n < cur and count > 1:
return [a[j] for j in range(start,start+count+1)]
print findsub(b)
A somewhat sloppy algorithm, but I believe it does what you want. Usually i would not have simply shown you code, but I suspect that is what you wanted, and I hope you can learn from it, and create your own from what you learn.
a slightly better looking way because I didn't like that:
b = [1,2,0,1,2,3,4,5]
def findsub(a):
answer = [a[0]]
for i in a[1:]:
if answer[-1] + 1 is i:
answer.append(i)
if not len(answer) > 1:
answer = [i]
elif i < answer[-1] and len(answer) > 1:
return answer
return answer
print findsub(b)
You need to do the following:
Create a function W that given a list, returns the index of the last item which is not strictly increasing from the start of the list.
For example, given the following lists: [1,2,3,4,1,2,3], [4,2,1], [5,6,7,8], it should return 4, 1, 4, respectively for each list
Create a variable maxim and set the value to 0
Repeatedly do the following until your list is empty
Call your function W on your list, and let's call the return value x
if x is greater than maxim
set maxim to x
At this point if you wish to store this sequence, you can use the list-slice notation to get that portion of your list which contains the sequence.
delete that portion of your list from the list
Finally, print maxim and if you were storing the parts of your list containing the longest sequence, then print the last one you got

Check whether an element occurs in a list using recursion [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 6 years ago.
Improve this question
def check(x,num,i):
for n in range(len(x)):
if x[i] == num:
return True
else:
return(check(x,num,i+1))
return False
def User(x,num):
return(check(x,num,0))
User([2,6,1,9,7,3],5,0)
this should out put false since 5 is not in the list
checks whether an element occurs in a list recursively
so for example:
Input: a list L read from the keyboard, for example L = [2,6,1,9,7,3]
an element e, for example e = 9
but for some reason, i get an error when the number is not in the list
The beauty (and purpose) of recursion is that you do not need the loop:
def check(x, num, i):
if not x[i:]: # index past length
return False
if x[i] == num:
return True
return(check(x, num, i+1))
You can also do without the index parameter:
def check(x, num):
if not x:
return False
return x[0] == num or check(x[1:], num)
I don't exactly understand what you're doing, but this is a bizarre combination of recursion and iteration. If you're going to use recursion, it's worthwhile, at least for a basic recursive problem like this, to avoid iteration. Try something like this
def check(x, num, i = 0):
if i >= len(x):
return False
elif x[i] == num:
return True
else:
return check(x, num, i + 1)
This solution will work perfectly fine and is tail recursive so it will work quickly and optimally.
The way this works is it checks if the index, i, is out of bounds. If so, then it returns False. If it is in bounds, it checks if x[i] is equal to the number. If so, it returns True. If it is not, it returns check with the index increased and thus the recursion works.
First of all, your for loop doesn't make any sense. You never use that n and never go into the loop a second time, as you always return something in the first iteration. The return statement after the for loop is also unreachable, so your code could as well be
def check(x,num,i):
if x[i] == num:
return True
else:
return(check(x,num,i+1))
Then the actual issue is, that if you have a list with 5 elements for example, which does not contain the element searched for, you ask what the 6th is, although there is no 6th element, thus the error. You'd have to check whether the list contains 6 elements. So you check whether it has more than 5, return false if it does and continue if it doesn't. (Alternatively you could also check this at the start of the whole function)
def check(x,num,i):
if x[i] == num:
return True
else:
if len(num)>i:
return False
else:
return(check(x,num,i+1))
What you've done then is nothing but a overcomlicated, recursive for-Loop. You just increase i and compare, until you find the element or i is bigger than the list length. So this is equivalent to
def check(x,num):
for i in range(len(num)):
if x[i]==num:
return True
return False
It is very important that the return False is AFTER the for-Loop, as you only return, if you didn't find the element, even after iterating over the WHOLE list.
Also you can avoid indices. With a for-Loop you can directly iterate over the elements in a list:
def check(x,num):
for elem in num:
if elem==num:
return True
return False
This makes the variable elem become every element in you list, one after another.

Recursive fibonnaci-like cumulative [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
calling func. change the input
I have to write a recursive function that takes a list of numbers in input and returns a list of numbers in output, for example called like this:
rec_cumsum([2,2,2,3])
the output should be like:
[2,4,6,9]
Thing is, I cant seem to get my head around for this to work.. this got me questioning my whole recursive thinking..
what i have so far is :
newlist = []
k = 1
def rec_cumsum(numbers):
if len(numbers) == 0:
return 0
if len(numbers) > 1 and len(numbers) != (k+1):
newlist[k+1] == newlist[k+1] + newlist[k]
k = k+1
return rec_cumsum(numbers)
but I'm getting errors which doesn't really make any sense to me.
the recursion should always take the number, and add it to the one before it, than save it in the next location of the list.. (new one or original one)
I would write it like this:
def cumulative_sum(lst,prev=0):
if not lst:
return []
else:
elem = prev+lst[0]
return [elem] + cumulative_sum(lst[1:],prev=elem)
print cumulative_sum([2,2,2,3])
Now to look at your code (note I didn't actually work through the logic to decide whether it would give the correct result, the following only addresses possible exceptions that your code is probably throwing):
You're probably getting an IndexError because of this line:
newlist[k+1] == newlist[k+1] + newlist[k]
You're assigning to a list position which doesn't exist yet. You could pre-allocate your list:
newlist = [0]*len(lst)
but even if you fix that, you'll get a recursion error with your code because of the line:
k = k + 1
The problem here is that on the left hand side, k is local whereas on the right hand side, k is global. So essentially each time you run this, you're getting the local k == 2 and not touching the global one. If you really want to modify the global k, you need to declare k as global via global k. Of course, then you need to reset k every time you're going to use this function which would be a somewhat strange API.

Categories

Resources