I am currently in an introduction to Python and computational theory class, and there was recently a difficult question on the midterm that I simply was not able to solve. It involves writing code for a program that adds numbers. I believe the question is supposed to use recursion. I don't remember how exactly the question was worded, but here is the basic idea.
Implement the multiadder(n)
function, which takes in a nonnegative integer n
and adds n
arbitrary values together. Each value to be added must be written as a separate call. For example:
>>> multi_three = multiadder(3)
>>> multi_three(1)(2)(3)
6
>>> multiadder(5)(1)(2)(3)(4)(5)
15
The code must be written by filling in the blanks.
def multiadder(n):
assert n > 0
if _________________________ :
return _________________________
else:
return _________________________
The topics we have covered in class are higher order functions, recursion, lambdas, and control statements. We are not allowed to use data structure like lists and sets, nor are we allowed to import anything.
Someone please help. It's the only problem I couldn't get on the test!
Try this:
For
n == 1
, the result must be a function returning the input.For
n > 1
, wrap the result ofn-1
, by adding input.This also works for concatenating strings, and other accumulating operations:
You could also define an internal auxiliary function (
loop
) which keeps track of the sum state (acc
) as the counter state (n
) decrementsIt's not nearly as elegant as DarkKnight's answer, but it might be easier for a beginner to conceptualize. In fact, this pattern is so useful and versatile that I use it to define almost all of my recursive procedures.
The only adaptation we made to this pattern is wrapping the recursive branch of the
if
expression in inlambda x: ...
– this is becausemultiadd
is meant to return functions untiln
returned functions have been applied.One more, just for fun using the legendary Y-combinator. This probably doesn't meet the criteria provided by your instructor, but it's cool to see it nonetheless. Multiline lambdas in python are not really a thing so readability suffers a little bit.
Or you could still have defined
multiadder
usingdef
syntax if you wantedIt works the same way.
I highly encourage you to trace the evaluation step-by-step to understand how it works. There are some tremendous insights to be gained in understanding these higher-order functions.
At first it seemed liked multiadder needed two inputs for this to work, but the answer is quite straightforward. I wouldn't think an "Introduction to Python" class would need lamba functions and so on.
This is final answer:
The graph below explains how it works for n = 4:
So the final result for n = 4 ends up being 4 + 3 + 2 + 1 = 10.
You could do it like this, but it is almost unreadable. I hope the explanations are helpful:
See it run on repl.it.
How it works
The return value consists of three major parts:
In short, this function assigns a name to a function, so it can be called recursively. In more detail: It takes a function
f
that must itself accept 4 arguments, of which the first should be a self-reference. The function that is returned here takes the three other arguments, and returns the recursive call off
.Part two is the real core:
This is passed as argument to the first function above, making recursion possible. This function takes the 4 arguments mentioned above, and applies the specific logic:
i
is the number that must be addedn
is the number of values still expected after this onesm
is the so far accumulated sum (excludingi
)Depending on whether more values are expected this function returns the final result (
sm+i
) or a function with one argument that will do the same as described here (recursion) with decreasedn
, and adapted sum.Finally, the initial values are passed to the above:
Meaning, we start with number 0 (dummy),
n
expected values, and a current sum of 0.Note
As the recursion in the above code does not involve a call to
multiladder
, and the assertion really excludes theif
condition to be true, we can do without thatif...else
: