0

I want to take an arbitrary number of lists and return list of combinations of elements, but only combining one element from each list. All I have is sudo code because I don't know where to start.

I did find the solution to this program in the question of Combining the elements of 2 lists but I don't understand that scala code. I'm writing my program in Tcl but if you're able to help me feel free to write your answer in anything like java or python or pseudo code or whatever. Can anyone help me bring the following pseudo code to life?

for example:

  # example: {a b} {c} {d e}
  # returns: {a c d} {a c e} {b c d} {b c e}
  # how?
  # example: {a b} {c} {d e}
  # iters:    0     0   0 
  #           0     0     1
  #             1   0   0
  #             1   0     1
  #
  #  
  #  set done false
  #
  #  while {!done} {
  #  
  #    list append combination_of_list due to iteration counts
  #  
  #    foreach list $lists {
  #      increment the correct count (specifically {0->1} {0->0} {0->1}) } 
  #      reset the approapraite counts to 0
  #    }
  #  
  #    if all the counts in all the lists are at or above their max {
  #      set done true
  #    }
  #  }  
Community
  • 1
  • 1
MetaStack
  • 3,266
  • 4
  • 30
  • 67

2 Answers2

1

Here is a pseudocode describing an algorithm that generates all the combinations:

list_of_lists = {{a b}{c}{d e}}

def copy(list):
   copy = {}
   for element in list:
       copy.add(element)
   return copy;
def combine(list1, list2):
    combinations = {}
    for item1 in list1:
        for item2 in list2:
            combination = copy(item1)
            combination.add(item2)
            combinations.add(combination)
    return combinations

results = {{}}
while list_of_lists.length>0:
   results = combine(results, list_of_lists[0])
   list_of_lists.remove(0)

It starts by combining {{}} with {a b c} which produces {{a} {b}} which will be combined with {c} to generate {{a c} {b c}} on the next iteration etc.

Update: Javascript version:

var list_of_lists = [["a", "b"],["c"],["d", "e"]];

function copy(list) {
    var copy = [];
    for (element of list) {
        copy.push(element);
    }
    return copy;
}

function combine(list1, list2) {
    var combinations = [];
    for (let item1 of list1) {
        var combination = copy(item1);
        for (let item2 of  list2){
            combination.push(item2);
            combinations.push(combination);
        }

    }
    return combinations;
}

results = [[]]
while (list_of_lists.length>0) {
    results = combine(results, list_of_lists[0]);
    list_of_lists.splice(0,1);
}
console.log(results);
Frank Bessou
  • 632
  • 5
  • 8
  • I hope I implemented this right; I'm not sure. The final output I got wasn't correct, it was: `{a c d} {a c d e} {a b c d} {a b c d e}` but I'll look through the code and see if I implemented it correctly. – MetaStack Sep 09 '16 at 14:35
1

Various Tcl solutions are discussed on this page: Cartesian product of a list of lists

Donal Fellows presents this variation at the end of the page:

proc product args {
    set xs {{}}
    foreach ys $args {
        set result {}
        foreach x $xs {
            foreach y $ys {
                lappend result [list {*}$x $y]
            }
        }
        set xs $result
    }
    return $xs
}

Running that like this gives you the result:

% product {a b} {c} {d e}
{a c d} {a c e} {b c d} {b c e}

Documentation: foreach, lappend, list, proc, return, set, {*} (syntax)

Peter Lewerin
  • 13,140
  • 1
  • 24
  • 27