recursive function find the max value on python - python

I am stuck my code. I want to find recursive max value.
here is my goal
1.If more than one element maximises the key, then the first one (the one that comes earliest in the array) must be returned.
2.The key parameter must be optional; if not provided, the function must return the (first) largest element. Think of a good default value for the key function!
3.Do not use the built-in max or min functions (obviously).
here is my code!
def recursive_max(seq, key):
if len(seq) == 1:
return seq[0]
else:
key = recursive_max(seq[1:])
if key > seq[0]:
return key
else:
return seq[0]
print(recursive_max(range(-5, 5 + 1))) #answer is 5
print(recursive_max(range(-5, 5 + 1), lambda x: x * x)) #answer is -5
class PoliticalDivision:
def __init__(self, name, area):
self.name = name
self.area = area
divisions = [
PoliticalDivision("Brazil", 8.5),
PoliticalDivision("China", 9.5),
PoliticalDivision("New Zealand", 0.27),
PoliticalDivision("Russia", 17),
PoliticalDivision("UK", 0.24),
PoliticalDivision("US", 9.5),
]
print(recursive_max(divisions, lambda division: division.area).name) #answer is Russia.
I just cant get ritht output.
even another code is
def recursive_max(seq, key=lambda x: x):
if len(seq) == 1:
return seq[0]
else:
return max(seq[0], recursive_max(seq[1:], key), key=key)
the feedback is Runtime error
File "prog.python3", line 5, in recursive_max
return max(seq[0], recursive_max(seq[1:], key), key=key)
how to improve it ?
any suggestions will be glad :)

Consider:
def recursive_max(seq, key=None):
# if key isn't given, call it again with key being returning the value itself
if not key: return recursive_max(seq, lambda a: a)
# error checking: can't get max of empty sequence
if not seq: raise ValueError("max of empty seq")
# base case: seq of 1, the max is the first element
if len(seq) == 1: return seq[0]
# get the max of the rest of the list
sub_max = recursive_max(seq[1:], key)
# if that's bigger than 1st element, return that, else return 1st element
return sub_max if key(sub_max) > key(seq[0]) else seq[0]

Related

Binary Search in Python - Iterative Method

so I'm trying to learn programming myself in Python language and was confused implementing Binary Search in Python. So here's what I have done
list = [3,6,8,12,14,17,25,29,31,36,42,47,63,55,62]
key = 42
print(list)
def high(sorted_list):
max_index = len(sorted_list)
return max_index
def low(sorted_list):
start_index = 0
return start_index
def mid(sorted_list):
mid_index = ( low(sorted_list) + (high(sorted_list) - low(sorted_list)) ) // 2
return mid_index
for x in range(4):
if list[mid(list)] < key:
list = list[mid(list)+1:]
elif list[mid(list)] < key:
list = list[mid(list)-1:]
print(list)
I know I should not keep a range number in for loop but I know it will only make 4 comparisons in this example so I hardcoded it. But when I run it, it splits the list only once and keep on printing the second half of the list. Output image:
Ok, I tried your code and had to do a few corrections:
The while loop had to be modified (you knew that)
There wasn't a check for the case where the key is found (see comments)
There was a typo, < instead of > (see comments)
In the same line, the list partition was wrong
The low function was useless (returning a constant value) (see comments)
The high function was useless too (simply returning the value from another function)
The mid function was more complicated than needed (it boiled down to taking a value, then adding and subtracting zero), so it can simply take the value
Ah, btw the input list is not sorted in your example.
This is my proposal:
def mid(lst):
return len(lst) // 2
def bin_search(lst, k):
while lst:
i = mid(lst)
if lst[i] == k:
return True
if lst[i] < k:
lst = lst[i+1:]
elif lst[i] > k:
lst = lst[:i]
else:
return False
bin_search([3,6,8,12,14,17,25,29,31,36,42,47,55,62,63], 42)
True
bin_search([3,6,8,12,14,17,25,29,31,36,42,47,55,62,63], 58)
False

recursive to find number of nested list and element value if depth reaches 0

I have a nested list and I want to return the number of nested list (or the depth) and the element value if the depth reaches 0. For example, with below nested list, the value I want to return is (13, 37). But my code returns 36 only.
nested = [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[13]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
def search(a, depth=0):
count = 0
for e in a:
if isinstance(e, list):
count = count + 1 + search(e)
return count
search(nested)
How should correct my code to make it return (13, 37) as expected?
This gives the right answer for a single value wrapped in a single set of lists. Not sure why you are iterating over the elements of the list. Are there potentially multiple nested sub lists/values?
nested = [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[13]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
def search(a, depth=0):
if type(a) is list:
return search(a[0], depth + 1)
else:
return a, depth
print(search(nested))
You're not counting the outermost list. To correct this, pull the list check outside of the loop. To return the inner value, retrieve it when the list element is not a list anymore:
def search(a):
count = 0
if isinstance(a, list):
count += 1
for e in a:
inner_value, count_inc = search(e)
count += count_inc
else:
inner_value = a
return inner_value, count
A good recursive function has a base case and a recursive case. Ruswick's (good) answer can be modified to meet these criteria:
def search(a, depth=0):
if type(a) is int: #base case
return a, depth
return search(a[0], depth + 1) #recusive case
print(search(nested))
#(13, 37)
You can use a recursive generator function to handle inputs with more than one non-list element:
def search(d, c = 0):
for i in d:
if not isinstance(i, list):
yield (i, c)
else:
yield from search(i, c+1)
nested = [[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[[13]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]
print(list(search(nested)))
Output:
[(13, 36)]

How to search list of objects for index of minimum

I want to search through a list of objects for the lowest number present in an attribute of the objects.
This is easy enough using a list comprehension and the min function. The issue comes when I want to find the index of the object.
class School:
def __init__(self, name, num_pupils, num_classrooms):
self.name = name
self.num_pupils = num_pupils
self.num_classrooms = num_classrooms
def students_per_class(self):
return self.num_pupils / self.num_classrooms
def show_info(self):
print(f"{self.name} has {self.students_per_class():.2f} students per class.")
def string_checker(question):
valid = False
while not valid:
try:
response = str(input(question))
if all(character.isalpha() or character.isspace() for character in response):
valid = True
return response
else:
print("Enter a string containing no numbers of special characters. ")
except ValueError:
print("Enter a string containing no numbers of special characters. ")
def num_checker(question):
valid = False
while not valid:
try:
response = int(input(question))
if (response):
valid = True
return response
else:
print("Enter an integer containing no letters or special characters. ")
except ValueError:
print("Enter an integer containing no letters or special characters. ")
def new_school():
school_name = string_checker("School Name: ")
num_pupils = num_checker("Number of Pupils: ")
num_classrooms = num_checker("Number of Classrooms: ")
return School(school_name, num_pupils, num_classrooms)
if __name__ == "__main__":
schools = []
school = School("Darfield High School", 900, 37)
schools.append(school)
school.show_info()
for i in range(1):
schools.append(new_school())
for school in schools:
school.show_info()
print(min(school.students_per_class() for school in schools))
# This works fine and prints the value of the lowest number
print(schools.index(min(school.students_per_class() for school in schools)))
# This doesn't work as it tries to find the index of the value returned
# from the min function as it should.
You can use min's key argument to search by index:
index = min(range(len(schools)), key=lambda i: schools[i].students_per_class())
print(schools[index])
A key provides the values that will be compared instead of the actual sequence. Here, my sequence is range(len(schools)), which is just the indices of all the elements. But instead of finding the minimum index, I am making it so that we find the minimum of schools[i].students_per_class() for each index i.
If you wanted to be able to compare, sort, find the min/ max on the items directly you could use the "dunder" methods. These methods allow you to overload built in functions on classes.
For instance if you had a class like this
class Item:
def __init__(self, value):
self.value = value
def __lt__(self, other):
return self.value < other.value
def __eq__(self, other):
return self.value == other.value
You can then create two instances and compare them directly like this,
A = Item(1)
B = Item(2)
print(A < B) # Prints True
or if you had a list of items
items = [A, B]
You can then get the minimum item by going
min_item = min(items)
or the index of it by going
min_item_index = items.index(min(items))
although it may be enough to just have a reference to the minimum item.
Use enumerate to iterate through lists while keeping track of indices:
min(((i, school.students_per_class()) for i, school in enumerate(schools)), key=lambda x: x[1])
(i, school.students_per_class()) is a tuple and using key parameter of min(), we ask Python to find minimum of school.students_per_class(), which subsequently returns it's index along with it.
Read about lambda here.
I think you may be looking for np.argmin function, if you provide a list as an input it will return the index of the minimal element.
in this case it would be:
import numpy as np
min_ind = np.argmin([school.students_per_class() for school in schools])
print(schools[min_ind])
#Tomas Ordonez
Your answer is here:
def minInt(instanceList):
sorted_instanceList = sorted(instanceList, key=lambda instance: instance.int)
minIndex = instanceList.index(sorted_instanceList[0])
return minIndex

How can I return a single boolean value from a recursive function?

I have this function:
def most(P, S):
def recursion(P,S):
if len(S) == 0:
return []
elif P(S[0]):
return [P(S[0])] + recursion(P, S[1:])
else:
return recursion(P, S[1:])
if len(recursion(P,S)) > len(S)/2:
return True
else:
return False
It takes an input of function, P and list, S. If the result of P(S[i]) is true for most of S, then the function most() should return true. Any idea how I can do this recursively without a function inside of a function? In other words, how can I return a single boolean value from a recursive function that takes a list as its input?
Thanks!
The biggest key to recursion is understanding the "terminal condition." What is the state where the function must stop? In this case, it's the empty list.
def most(pred, lst):
if lst == []:
return # but what do we return?
You will need to keep track of the number of list elements that meet an expectation... so you have to keep track of both the expectation (i.e. how many have to be true in order for "most" to be true), as well as the count so far. Let's add those...
def most(pred, lst, threshold=None, count=0):
if threshold is None:
threshold = len(lst) // 2
if lst == []:
return count > threshold
So, then we need to "deconstruct" the list so that we can recurse over it. Let's add that...
def most(pred, lst, threshold=None, count=0):
if threshold is None:
threshold = len(lst) // 2
if lst == []:
return count > threshold
# Check the 'truth' of the head of the list...
if pred(lst[0]):
count += 1
# ...and pass the tail of the list into the next iteration.
return most(pred, lst[1:], threshold, count)
That should be all that you need. Now, I'll caution you that if your lists are of significant length, Python will blow its stack. This is also significantly slower than a solution using a for loop or reduce, because of all the additional function calls.
If I were implementing most for production code, I would do this:
def most(pred, lst):
return sum(1 for x in lst if pred(x)) > len(lst) // 2

How to write a recursive function in python

I have been stuck on the solution to this question for quite a while i have written a piece of code that works as requested but i seems to get an error at the end of the compilation
You need to design an iterative and a recursive function called
replicate_iter and replicate_recur respectively which will receive two
arguments: times which is the number of times to repeat and data which
is the number or string to be repeated.
The function should return an array containing repetitions of the data
argument. For instance, replicate_recur(3, 5) or replicate_iter(3,5)
should return [5,5,5]. If the times argument is negative or zero,
return an empty array. If the argument is invalid, raise a ValueError.
my code is as below:
def replicate_iter(times,data):
emptyArray = []
if not isinstance(data, int) and not isinstance(data, str):
raise ValueError
if times <= 0:
print emptyArray
if not isinstance(times,int):
raise ValueError
else:
while times > 0:
emptyArray.append(data)
times -= 1
return emptyArray
array = []
def replicate_recur(times,data):
if not isinstance(data,int) and not isinstance(data,str):
raise ValueError
if not isinstance(times,int):
raise ValueError
if times <= 0 and len(array) != 0:
return array
elif times <= 0 and len(array) <=0:
return []
else:
array.append(data)
replicate_recur(times - 1,data)
Kindly assist with suggestions please
error message :
First, think about this:
def f(times,data):
return [] if times == 0 else f(times - 1,data) + [data]
print(f(3,5)) # [5,5,5]
Now, with regard to your recursive solution, (1) in order to access array, replicate_recur would need a declaration at its outset, "global array," since the variable, array, is declared outside of the function's scope; and (2) modify the recursive call, "replicate_recur(times - 1,data)," to "return replicate_recur(times - 1,data)," in order for the function to actually return a value when times is greater than zero. (That said, as I understand, it's generally considered undesirable form to have global accumulators for recursive functions.)
Maybe this is what you want based on the example you gave:
array = []
def replicate_recur(times, val):
if(isinstance(times, int) and times > 0):
array.append(val)
return replicate_recur(times-1, val)
return array
print(replicate_recur(3, 5)) # [5,5,5]
array = []
def replicate_iter(times, val):
if(isinstance(times, int) and times > 0):
for i in range(times):
array.append(val)
return array
raise ValueError
print(replicate_iter(3, 5)) #[5,5,5]
You must not use a global variable. A second call to your function leads to wrong results. Use a internal function or optional parameter instead.
def replicate_recur(times,data, array=None):
if array is None:
array = []
if times <= 0:
return array
array.append(data)
return replicate_recur(times - 1, data, array)
Maybe you should split up the logic, always becomes more readable, so it becomes easier to implement. You should avoid global variables, especially global lists, they will cause you much pain.
def rep_rec(times, data, pack=[]):
pack += [data]
return pack if times < 2 else rep_rec(times-1, data, pack)
def replicate_recur(times, data):
if not times or not data:
return []
if isinstance(times, int) and (isinstance(data, int) or isinstance(data, str)):
return rep_rec(times, data) if times > 0 else []
raise ValueError
"""
A. In recursions, in general, some input is minimized until some minimum condition.
"eg: in f(x-2), x is the input"
B. In the following recursion, multiples of x "eg: x TIMES f(x-2)" are
computed as x gets smaller and smaller by 2 "eg: f(x MINUS 2)",
until x finally reaches 1 "eg: if x==ONE return 1", the minimum CONDITION value.
C. The recursion multiplies by many values generated by calls of function "f",
until mininum is reached.
"eg: x TIMES value-AT-f-CALL_a(x-2) TIMES value-AT-f-CALL_b(x-2)....
D. When mininum CONDITION is reached, or in other words, when x reaches 1, the recursion
multiplies by 1, instead of another value generated by function "f" call.
"eg: x TIMES value-AT-f-CALL_a(x-2) TIMES value-AT-f-CALL_b(x-2) TIMES 1"
NOTE: This is why the recursion ends, as it no longer multiplies by value at f-call.
E. In "TIMES 1" in D above, because 1 is the minimum RETURN value
"eg: if x==1: return ONE", this means the minimum CONDITION is reached.
NOTE: if we had x PLUS f(x-2), then the mininum value would be
ADDED TO (instead of multiplied by) the SUM (instead of the product).
"""
def f(x):
"""This is a recursive function f to generate product of x, as x decreases by 2"""
if x == 1:
return 1
else:
return (x * f(x-2))

Categories

Resources