0

I found this code online, in this website (All combinations of a list of lists), that gets the permutation of a list of lists but i need it to have only one parameter instead of two but i dont know how. Any help? Thanks in advance! I must have the function combine(terms) instead of combine(terms,accum).

def combine(terms, accum):
    last = (len(terms) == 1)
    n = len(terms[0])
    for i in range(n):
        item = accum + terms[0][i]
        if last:
            combinations.append(item)
        else:
            combine(terms[1:], item)
  • what do you want to achieve? what parameters do you have? just pass an empty string as your second argument – Alexander Riedel Nov 07 '20 at 13:00
  • Hi! yep i did that but it requires me to only have combine(terms) only. Im having a really hard time because i dont know how to recurssively call it in the else: statement without the second parameter – Aeden Schmidt Nov 07 '20 at 13:07
  • @AedenSchmidt--did you try changing the function signature so accum has empty string as default value, i.e. `def combine(terms, accum = ''):` Also, this function is poorly written in that it should have combinations as a default argument rather than a global, but that's a different issue than your problem. – DarrylG Nov 07 '20 at 13:18
  • you can also just define `item = '' + terms[0][i]` and then `def combine(terms):` – Alexander Riedel Nov 07 '20 at 13:27
  • @DarrylG yes i tried that but im not allowed to do so – Aeden Schmidt Nov 07 '20 at 14:09
  • @AlexanderRiedel Im not exactly sure what you mean, https://pastebin.com/bzALFfwv is it like this? But when i do this the output is wrong – Aeden Schmidt Nov 07 '20 at 14:18
  • @AedenSchmidt--are you saying you're not allowed to change the function signature? – DarrylG Nov 07 '20 at 14:49
  • what do you mean by function signature? basically i need f(index) only, deleting one parameter which is accum. – Aeden Schmidt Nov 07 '20 at 14:54
  • @AedanSchmidt--fyi--function signature is commonly used to refer to the general information about a function, such as name & pameters. In your case you could use: `combinations, accum = [], ''` before calling combine (i.e. since the signature must only have one parameter). – DarrylG Nov 07 '20 at 14:58
  • i quite dont get what you mean, can you post the code? – Aeden Schmidt Nov 07 '20 at 15:05
  • @AedenSchmidt--posted a solution that described what I mean. – DarrylG Nov 07 '20 at 15:12

2 Answers2

1

You can create a wrapper function which calls the combine function with the proper arguments.

def combine_wrapper(terms):
    accum = ...
    return combine(terms, accum)

Or you can use partial functions (again it's similar to above):

from functools import partial

accum = ...
combine_wrapper = partial(combine, terms)

The partial function takes the function to be called as a reference and the rest of the arguments passed to it are directly passed to the function.


PS: I believe you might have the constraint to keep the name as it is. So maybe you could rename your original combine function to something else like _combine or combine_main and then name the wrapper function as combine.

Melvin Abraham
  • 2,870
  • 5
  • 19
  • 33
  • this definitely works but it feels kind off cheat-y, i'll ask if its allowed thank you! Edit: this might pose as a problem because it is stated that the combine function must be the one the uses a recurssive function and has only one parameter – Aeden Schmidt Nov 07 '20 at 17:25
0

Constraints

  1. Your function can only have one parameter
  2. You can't have default parameters

Strategy

We change accum into a stack (i.e. list) that contains the values it would
have at various levels of a recursive function

Meets Constraints

def combine(terms):
 
    last = (len(terms) == 1)
    n = len(terms[0])
    
    for i in range(n):
        # use top value in accum stack i.e. accum[-1]
        item = accum[-1] + terms[0][i]
        if last:
            combinations.append(item)
        else:
            # append to accum stack 
            # (similar to what woould happen if we where passing it as a recursive parameter)
            accum.append(item)
            combine(terms[1:])
            
    accum.pop()  # returning from recursive function so remove top
                 # value from stack
     

Usage

# Initializations
a = [['ab','cd','ef'],['12','34','56']]
combinations = []
accum = ['']        # stack which will hold accum for diferent levels of recursion
combine(a)
print(combinations)
   

Output

['ab12', 'ab34', 'ab56', 'cd12', 'cd34', 'cd56', 'ef12', 'ef34', 'ef56']

Caveat

I don't understand your constraint, but the function is simpler written as follows.

def combine(terms, accum = None, combinations = None):
    # Assign values for default parameters
    if accum is None:
        accum = ''
    if combinations is None:
        combinations = []
        
    last = (len(terms) == 1)
    n = len(terms[0])
    for i in range(n):
        item = accum + terms[0][i]
        if last:
            combinations.append(item)
        else:
            combine(terms[1:], item, combinations)
            
    return combinations   # we return the combinations rather than using an external global

Test

a = [['ab','cd','ef'],['12','34','56']]
print(combine(a))
# ['ab12', 'ab34', 'ab56', 'cd12', 'cd34', 'cd56', 'ef12', 'ef34', 'ef56']
DarrylG
  • 16,732
  • 2
  • 17
  • 23
  • my constraint is the function combine() must only have one parameter – Aeden Schmidt Nov 07 '20 at 15:28
  • i checked your first code, it doesnt quite get the output im looking for, ie it doesnt permute the first list, only the second. and i cant use your caveat code as it has a bunch of default parameters whereas only 1 parameter is what is required – Aeden Schmidt Nov 07 '20 at 15:51
  • @AedenSchmidt--I'll see if I can set up a way for us to chat. The code I created should be equivalent to the code you want to use, but it allows you to use only one parameter. – DarrylG Nov 07 '20 at 16:56
  • @AedenSchmidt--looks like I can't invite you into a chat room since 20 reputations points are required to enable that feature. I guess we can exchange messages here. Since I'm using the code you identified I don't understand why you say you're not getting the desired output. – DarrylG Nov 07 '20 at 17:14
  • with the code you sent following the restraints, your output was '# ['12', '34', '56', '12', '34', '56', '12', '34', '56']' whereas the one you made the second was '['ab12', 'ab34', 'ab56', 'cd12', 'cd34', 'cd56', 'ef12', 'ef34', 'ef56']', which in this case, is the correct one – Aeden Schmidt Nov 07 '20 at 17:17
  • @AedenSchmidt--sorry, updated the code so they now produce the same output. – DarrylG Nov 07 '20 at 17:30
  • Its still wrong i think, strings on the same list should not be permuted with each other `['ab12', 'ab34', 'ab56', 'cd12', 'cd34', 'cd56', 'ef12', 'ef34', 'ef56']` should be the output but it outputed `'abcd12', 'abcd34', 'abcd56', 'abcdef12', 'abcdef34', 'abcdef56'] ` that should not be in the output – Aeden Schmidt Nov 07 '20 at 17:37