Given a list of size n, Write a program that returns all possible combination of elements contained in each list.
Example:
Edit: I'm answering this in python, because, although it's currently tagged language-agnostic, python is a good, executable pseudo-pseudocode.
If you can write the function in a form that is Tail-recursive, i.e. in a form that looks like def f(x): return f(g(x))
, it's easy to turn it into an iterative form. Unfortunately, you usually won't end up with a tail-recursive call, so you need to know a couple of tricks.
First of all, let's say we have a function that looks like this:
def my_map(func, my_list):
if not my_list:
return []
return [func(my_list[0])] + change_my_list(my_list[1:])
Ok, so it's recursive, but not tail recursive: it's really
def my_map(func, my_list):
if not my_list:
return []
result = [func(my_list[0])] + change_my_list(my_list[1:])
return result
Instead, we need to adjust the function slightly, adding what is traditionally known as an accumulator:
def my_map(func, my_list, acc = [])
if not my_list: return acc
acc = acc + func(my_list[0])
return my_map(func, my_list[1:], acc + func(my_list[0]))
Now, we have a truly tail-recursive function: we've gone from def f(x): return g(f(x))
to def f(x): return f(g(x))
Now, it's quite simple to turn that function into a non-recursive form:
def my_map(func, my_list, acc=[]):
while True: #added
if not my_list: return acc
#return my_map(func, my_list[1:], acc + func(my_list[0])) #deleted
func, my_list, acc = func, my_list[1:], acc + func(my_list[0]) #added
Now, we just tidy up a little bit:
def my_map(func, my_list):
acc = []
while my_list:
acc.append(func(my_list[0])
my_list = my_list[1:]
return acc
Note you can clean it up even further using a for
loop or a list comprehension, but that's left as an exercise for the reader.
Ok, so this was a pathological example, hopefully you'd know that python has a builtin map
function, but the process is the same: transform into a tail recursive form, replace the recursive call with argument reassignment, and tidy up.
So, if you have:
def make_products(list_of_lists):
if not list_of_lists: return []
first_list = list_of_lists[0]
rest = list_of_lists[1:]
return product_of(first_list, make_products(rest))
You can convert it into a tail recursive form
def make_products(list_of_lists, acc=[]):
if not list_of_lists: return acc
first_list = list_of_lists[0]
rest = list_of_lists[1:]
acc = product_of(acc, first_list)
return make_products(rest, acc)
Then, that simplifies to:
def make_products(list_of_lists):
acc=[]
while list_of_lists:
first_list = list_of_lists[0]
rest = list_of_lists[1:]
acc = product_of(acc, first_list)
list_of_lists = rest
return acc
Again, this can be cleaned up further, into a for
loop:
def make_products(list_of_lists):
acc=[]
for lst in list_of_lists:
acc = product_of(acc, lst)
return acc
If you've looked at the builtin functions, you might notice this is somewhat familiar: it's essentially the reduce
function:
def reduce(function, iterable, initializer):
acc = initializer
for x in iterable:
acc = function(acc, x)
return acc
So, the final form is something like
def make_products(list_of_lists):
return reduce(product_of, list_of_lists, []) # the last argument is actually optional here
You then just have to worry about writing the product_of
function.