Last month, I was interviewed by InfinitelyBeta recruitment team. Interview was really cool, and I really enjoyed every part of it. One of the tasks given to me was to implement a simple function called reduce with the following characteristics:
- first parameter of reduce should be name of a function, defined earlier.
- second parameter should be a list of arguments, which is to be passed to the first parameter.
- should return the result of executing first parameter
for eg:
1 2 3 4 5 | def add(a, b): return a+b ''' reduce function should called as : reduce(add, [1,2]) and should return 3 ''' |
Let’s see how to write a function, which will call another function using the parameters specified.
In python, we can write a function as follows:
Container Function
1 2 3 4 5 6 7 | # container function will call the function func with the parameter args def container(func, args): func(args) # generic function to print def printer(a): print a |
If we call
1 | container(printer, "hello") |
it will print hello. If we try to pass the second parameter as a list, for eg:
1 | container(printer, [1, 2, "hello"]) |
,it will just print the same list for you. (Remember that print function will just print the complete list when a list is passed to it as argument).
Now, let’s try something more deeper into this container function. Redefining the container function as follows :
1 2 | def container(func, *args): #line 1 return func(*args) #line 2 |
- RULE 1 : asterisk before args in the first line means to “take the rest of the parameters given and put them in a list called args.”
- RULE 2 : asterisk before args in the second line mean “take this list called args and unwrap it into the rest of the parameters.”
Now, let’s see what happens:
Python 2.6.1 (r261:67515, Jun 24 2010, 21:47:49) [GCC 4.2.1 (Apple Inc. build 5646)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> def container(fun, *args): ... return fun(*args) ... >>> def add(a, b): ... return a+b ... >>> container(add, 1,2) 3
Here, we got 3 as output, which is correct. How?
When we called the container function with add, 1, 2 as arguments, 1, 2 where added to the tuple args (see RULE 1). Thus, in container function, func => add and args = [1, 2]. Then, according to RULE 2, the tuple args was expanded into parameters for add and add(1, 2) was called. We could easily find the values in args as:
>>> def container(func, *args): ... print args ... >>> container(add, 1,2) (1, 2) >>>
Now see what happens when we try to pass a list as the argument to second parameter:
>>> container(add, [1, 2]) Traceback (most recent call last): File "", line 1, in File "", line 2, in container TypeError: add() takes exactly 2 arguments (1 given) >>>
This time, the entire list [1, 2] was taken as a single argument. We may solve this issue by making a minor change to our container function as follows:
>>> def container(fun, args): ... return fun(*args) ... >>> container(add, [1,2]) 3 >>>
Here, we’ve specified that container will take exactly 2 arguments, and the second argument args should be unwraped into a list of parameters.
So, what if we need to call the container function as follows?
container(function-name, [1,2], [4, 5])
Here we have 3 parameters, in which second and third are lists. We shall define the container function as:
>>> def container(fun, *args): ... return fun(*args) >>> >>> >>> container(add, [1,2], [4,5]) [1, 2, 4, 5]
Now, we have enough background to implement the reduce function. I was asked to do it for the add function, so, I did it as follows:
def reduce(fun, args): k = args[0] if len(args) == 2: k = fun(arg[0], arg[1]) return k return k + reduce(fun, args[1:])
Since this was only for add, I was asked to make it generic for any function. After some corrections to it, I changed it as follows:
Reduce function
1 2 3 4 5 6 | def reduce(fun, args): k = args[0] if len(args) == 2: k = fun(arg[0], arg[1]) return k return fun(k, reduce(fun, args[1:])) |
Tail recursive implementation
1 2 3 4 5 | def reduce(fun, args): if len(args)==1: return args[0] args.insert(args[2:], fun(args[0],args[1]) return reduce(fun, args ) |
Bottom line:
Infinitely Beta recruited me, and received the offer letter 2 days after my interview
Recent Comments