I have to use functional programming to implement the following function takes in a list of numbers from 0 to 9. The goal is to find the five consecutive elements of the list that have the greatest product. The function should return tuple of the index of the greatest product and the value of the greatest product without using the max function.
I can easily implement this without functional programming but I am having trouble implementing it without any loops. This is my approach so far but the part that I am stuck on is how to loop through the array to find those consecutive five numbers without loops. I am trying to use map to do that but I don't think it is correct. Is it possible to incorporate enumerate in any way? Any help is appreciated.
def find_products(L):
val = map(lambda a: reduce(lambda x,y: x*y, L),L)
print (val)
Python offers two built-in functions, map() and filter() , that fit the functional programming paradigm. A third, reduce() , is no longer part of the core language but is still available from a module called functools . Each of these three functions takes another function as one of its arguments.
Neither of your iterators is purely functional, because they do maintain mutable state, although treated as a black box you can use them functionally because the user of the iterator cannot affect that state directly.
Lisp, C++, and Python are multi-paradigm; you can write programs or libraries that are largely procedural, object-oriented, or functional in all of these languages.
Predicate functions are functions that return a single TRUE or FALSE . You use predicate functions to check if your input meets some condition. For example, is. character() is a predicate function that returns TRUE if its input is of type character and FALSE otherwise.
This doesn't have any explicit loops or call the max
function. The function assumes that there're at least five elements in the input list and outputs a tuple (start_index, max_product)
.
from functools import reduce, partial
import operator
def f(l):
win = zip(l, l[1:], l[2:], l[3:], l[4:])
products = map(partial(reduce, operator.mul), win)
return reduce(lambda x, y: x if x[1] > y[1] else y, enumerate(products))
In [2]: f([1, 2, 3, 4, 7, 8, 9])
Out[2]: (2, 6048)
In [3]: f([2, 6, 7, 9, 1, 4, 3, 5, 6, 1, 2, 4])
Out[3]: (1, 1512)
win = zip(l, l[1:], l[2:], l[3:], l[4:])
creates a sliding window iterator of size 5 over the input list. products = map(partial(reduce, operator.mul), win)
is an iterator calling partial(reduce, operator.mul)
(translates to reduce(operator.mul, ...)
) on every element of win
. reduce(lambda x, y: x if x[1] > y[1] else y, enumerate(products))
adds a counter to products
and returns the index-value pair with the highest value.
If you need a more general version and/or the input list is large you'd use itertools.islice
:
from itertools import islice
def f(l, n=5):
win = zip(*(islice(l, i, None) for i in range(n)))
...
The code above uses a generator expression which is a loop, technically. A pure functional version of that might look like
from itertools import islice
def f(l, n=5):
win = zip(*map(lambda i: islice(l, i, None), range(n)))
...
from functools import reduce #only for python3, python2 doesn't need import
def find_products(L):
if len(L)==0:
return 0
if len(L) <= 5:
return reduce( lambda x,y:x*y, L)
pdts = ( reduce(lambda a,b:a*b,L[pos:pos+5]) for pos in range(len(L)-4)) # or pdts = map(lambda pos: reduce(lambda a,b:a*b,L[pos:pos+5],0),range(len(L)-4))
mx = reduce(lambda x,y: x if x>y else y, pdts)
return mx
pdts
contains all the possible 5 tuple products, and then using reduce
to mimic the max
function, we find the maximum among the products.
You could do the following:
range(0, len(L) - 5)
start
and the product of items L[start:start + 5]
L[result:result + 5]
This algorithm could be further improved to avoid re-calculating sub-products, but use a "rolling product", that is updated as you reduce from left to right, dividing by the element that was dropped, and multiplying by the new element that was added.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With