Check if elements occur together in all lists? - python

Say I have a list of lists like so:
l = [[1,2,3],[6,5,4,3,7,2],[4,3,2,9],[6,7],[5,1,0],[6,3,2,7]]
How would I write python code to check if there are elements that always occur together? For example, in the above example 2,3 and 6,7 always occur in the same lists. (there may be others, not sure).
What's the easiest to understand way of achieving this?
My only idea is to convert inner-list1 to set and check intersection with inner-list2 but when I check intersection with inner-list3, those elements may not occur at all in inner-list3.
Could I do something like:
for i in range(0,len(lists)):
a=set(lists[i]).intersection(lists[i+1])
if (len(a))==0:
continue
else:
a.intersection(lists[i+1])
This of course doesn't work but how could I formally code this or is there a better approach to this?

Using itertools.combinations:
I initially thought of using something with itertools.combination, but as this allows elements from a list which are not next to each other, it wasn't going to work for the solution I had in mind.
Turns out that when looking at non-numerical input lists, itertools.combinations is necessary in both cases. I had been confused because I assumed the groups had to be adjacent.
The way I thought would work best for this would be to generate the possible elements that could work and then check each one of these with a function against the list of sub-lists - as opposed to doing some kind of combinatoric work on the list and going down that path.
So to check if a list of possible elements is 'valid' i.e. if all the elements only occur together, I used a simple if with a generator with the all() and any() built-in functions to do this part of the job.
Now this was working, there needed to be a way of generating the potential elements that could occur. I just did this with two nested for-loops - one iterating over the width of the window, and one iterating over where the start of the window is.
Then from here, we just check if that set of elements is valid and add it to another list if it is!
import itertools
def valid(p):
for s in l:
if any(e in s for e in p) and not all(e in s for e in p):
return False
return True
l = [[1,2,3],[6,5,4,3,7,2],[4,3,2,9],[6,7],[5,1,0],[6,3,2,7]]
els = list(set(b for a in l for b in a))
sol = []
for w in range(2,len(els)+1):
for c in itertools.combinations(els, w):
if valid(c):
sol.append(c)
which gives sol as:
[(2, 3), (6, 7)]]
These 2 nested for-loops can actually be thrown together into a nice one-liner (not sure if others think it is Pythonic):
sol = [c for w in range(2, len(els)+1) for c in itertools.combinations(els, w) if valid(c)]
which works just the same but is simply shorter.
Due to popular demand (#Arman), I have updated the answer so that it should now work for other elements apart from 0-9. This was done with the introduction of a unique elements list (els).
And some tests from #thanasisp with the same code from above:
l = [[1, 3, 5, 7],[1, 3, 5, 7]]
gives sol as:
[(1, 3), (1, 5), (1, 7), (3, 5), (3, 7), (5, 7), (1, 3, 5), (1, 3, 7), (1, 5, 7), (3, 5, 7), (1, 3, 5, 7)]
and again with:
l = [[1, 2, 3, 5, 7], [1, 3, 5, 7]]
gives:
[(1, 3), (1, 5), (1, 7), (3, 5), (3, 7), (5, 7), (1, 3, 5), (1, 3, 7), (1, 5, 7), (3, 5, 7), (1, 3, 5, 7)]
which I believe is correct as the 2 shouldn't be in any groups as all other elements are in a different sub-list, so it can never make a group with another element.

An other linear solution with default dicts (tuple is there to make hashable keys) :
from collections import defaultdict
isin,contains = defaultdict(list),defaultdict(list)
for i,s in enumerate(l):
for k in s :
isin[k].append(i)
# isin is {1: [0, 4], 2: [0, 1, 2, 5], 3: [0, 1, 2, 5], 6: [1, 3, 5],
# 5: [1, 4], 4: [1, 2], 7: [1, 3, 5], 9: [2], 0: [4]}
# element 1 is in sets numbered 0 and 4, and so on.
for k,ss in isin.items():
contains[tuple(ss)].append(k)
# contains is {(0, 4): [1], (0, 1, 2, 5): [2, 3], (1, 3, 5): [6, 7],
# (1, 4): [5], (1, 2): [4], (2,): [9], (4,): [0]})
# sets 0 and 4 contains 1, and no other contain 1.
Now if you look for elements which appear by group of n (n=2 here), type :
print ([p for p in contains.values() if len(p)==n])
# [[2, 3], [6, 7]]

You can do this using set intersections, and it also works nicely for 3 or more elements per group: Note that I added an 8 to the 6,7 group.
lists = [[1,2,3], [6,5,4,3,7,2,8], [4,3,2,9], [8,6,7], [5,1,0], [6,3,8,2,7]]
First, we map each element to sets of all the other elements it appears together with:
groups = {}
for lst in lists:
for x in lst:
if x not in groups:
groups[x] = set(lst)
else:
groups[x].intersection_update(lst)
# {0: {0, 1, 5}, 1: {1}, 2: {2, 3}, 3: {2, 3}, 4: {2, 3, 4}, 5: {5},
# 6: {8, 6, 7}, 7: {8, 6, 7}, 8: {8, 6, 7}, 9: {9, 2, 3, 4}}
Next, we retain only those elements where the relationship is bidirectional:
groups2 = {k: {v for v in groups[k] if k in groups[v]} for k in groups}
# {0: {0}, 1: {1}, 2: {2, 3}, 3: {2, 3}, 4: {4}, 5: {5},
# 6: {8, 6, 7}, 7: {8, 6, 7}, 8: {8, 6, 7}, 9: {9}}
Finally, we get the unique groups with more than one element:
groups3 = {frozenset(v) for v in groups2.values() if len(v) > 1}
# {frozenset({8, 6, 7}), frozenset({2, 3})}

First, the data
data = [[1,2,3],[6,5,4,3,7,2],[4,3,2,9],[6,7],[5,1,0],[6,3,2,7]]
Generating combinations is expensive, so I wanted to avoid that as much as possible.
My "Eureka!" moment came when I realized I don't have to generate all the pairs. Instead, I can map each number to all the lists that contain it.
appears_in = defaultdict(set)
for g in groups:
for number in g:
appears_in[number].add(tuple(g))
The resulting dictionary is
{0: {(5, 1, 0)},
1: {(5, 1, 0), (1, 2, 3)},
2: {(4, 3, 2, 9), (6, 3, 2, 7), (6, 5, 4, 3, 7, 2), (1, 2, 3)},
3: {(4, 3, 2, 9), (6, 3, 2, 7), (6, 5, 4, 3, 7, 2), (1, 2, 3)},
4: {(4, 3, 2, 9), (6, 5, 4, 3, 7, 2)},
5: {(5, 1, 0), (6, 5, 4, 3, 7, 2)},
6: {(6, 3, 2, 7), (6, 7), (6, 5, 4, 3, 7, 2)},
7: {(6, 3, 2, 7), (6, 7), (6, 5, 4, 3, 7, 2)},
9: {(4, 3, 2, 9)}}
Look at the entries for 2 and 3
2: {(4, 3, 2, 9), (6, 3, 2, 7), (6, 5, 4, 3, 7, 2), (1, 2, 3)},
3: {(4, 3, 2, 9), (6, 3, 2, 7), (6, 5, 4, 3, 7, 2), (1, 2, 3)},
The set of lists containing 2 is identical to the set of lists containing 3. So I conclude that 2 and 3 always appear together.
Contrast this with 3 and 4
3: {(4, 3, 2, 9), (6, 3, 2, 7), (6, 5, 4, 3, 7, 2), (1, 2, 3)},
4: {(4, 3, 2, 9), (6, 5, 4, 3, 7, 2)},
Notice the gaps where (6, 3, 2, 7) and (1, 2, 3) should be. I conclude that 3 and 4 do NOT always appear together.
Here is the complete code
from collections import defaultdict
from itertools import combinations
from pprint import pprint
def always_appear_together(groups):
appears_in = defaultdict(set)
for g in groups:
for number in g:
appears_in[number].add(tuple(g))
#pprint(appears_in) # for debugging
return [
(i,j)
for (i,val_i),(j,val_j) in combinations(appears_in.items(),2)
if val_i == val_j
]
Running this gives
print(always_appear_together(data))
[(2, 3), (6, 7)]

This is brute force option that comes in my mind now, dct is counter dictionary for each digit , then we check for same lists in dct that means both digit occurs in same list indexes:
l = [[1,2,3],[6,5,4,3,7,2,1],[4,3,2,9,1],[6,7],[5,1,2,3,0],[6,3,2,7,1]]
dct = defaultdict(list)
for i, v in enumerate(l):
for x in v:
dct[x].append(i)
dct # defaultdict(<class 'list'>, {0: [4], 1: [0, 1, 2, 4, 5], 2: [0, 1, 2, 4, 5], 3: [0, 1, 2, 4, 5], 4: [1, 2], 5: [1, 4], 6: [1, 3, 5], 7: [1, 3, 5], 9: [2]})
new_d = defaultdict(list)
for k, v in dct.items():
for k2, v2 in dct.items():
if(v == v2) and k != k2):
new_d[k].append(k2)
new_d # defaultdict(<class 'list'>, {1: [2, 3], 2: [1, 3], 3: [1, 2], 6: [7], 7: [6]})
also it is a very expensive operation , it's O(N*N*M) : N = list elements and M = longest sublist

The following solution has a linear O(n) complexity where n is the total number of numbers in all lists (after flattening). The code is Python2.x
I'm using a bitmap representation (made easy with python's endless numbers) of all the possible patterns. For example if a number is present in list0 and list2 but not list1, the respective pattern will be ...000101. For example in the given input, the value 2 will have the following bitmap pattern: 100111 and so will the value 3
l = [[1,2,3],[6,5,4,3,7,2],[4,3,2,9],[6,7],[5,1,0],[6,3,2,7]]
num_to_pattern = {}
for i, sublist in enumerate(l):
for num in sublist:
# turning ON the respective bit for each value
if not num in num_to_pattern:
num_to_pattern[num] = 1 << i
else:
num_to_pattern[num] |= (1 << i)
pattern_to_num_list = {}
# mapping patterns to all their respective numbers
for num, pattern in num_to_pattern.iteritems():
if not pattern in pattern_to_num_list:
pattern_to_num_list[pattern] = [num]
else:
pattern_to_num_list[pattern].append(num)
print pattern_to_num_list
This code will print:
{4: [9], 6: [4], 39: [2, 3], 42: [6, 7], 16: [0], 17: [1], 18: [5]}
And you can map and filter whichever sublists you'd like (in your case - lists equal or larger than 2):
print filter(lambda x: len(x) >= 2, pattern_to_num_list.values())

What's the easiest to understand way of achieving this?
I tried to make my solution as short as possible. I also worked to optimize it as much as I could. It works for any integer as you prefer.
Here is the code with a lot of comments that explain it, followed by more essential explanations:
Note: In the following code, I used [[1, 2, 3], [2, 1, 4]] as an example of the original list instead of the one in your question, to make explanation easier.
Code
import itertools
# The original list of lists
org_list = [[1, 2, 3], [2, 1, 4]]
# Sort the lists of org_list to ensure that the resulting tuples of
# itertools.combinations below are sorted also, because later, we
# don't want (1, 2) to be not equal to (2, 1)
org_list = [sorted(l) for l in org_list]
# This list will contain the combinations of the original list
list_of_combinations = []
# --Building list_of_combinations--
# Looping through every list in the original list of lists (org_list)
for i, l in enumerate(org_list):
# Create a new set to hold the combinations for the i-th list of org_list
list_of_combinations.append(set())
# Starting with 2 because we want the combination to contain two
# items at least, and ending at len(org_list[i])+1 because we want
# the maximum length of the combination to be equal to the length
# of its original list
for comb_length in range(2, len(l) + 1):
# Update the set with its combinations of length comb_length
list_of_combinations[i].update(
tuple(itertools.combinations(org_list[i], comb_length))
)
# Now list_of_combinations = [
# {(1, 2), (1, 3), (2, 3), (1, 2, 3)},
# {(1, 2), (1, 2, 4), (2, 4), (1, 4)}
# ]
# This will hold the result. In our case: [2, 3], and [6, 7]
# It is a set because we don't want the result to contain duplicate items
combs = set()
# Looping through the sets in list_of_combinations
for s in list_of_combinations:
# s = {(1, 2), (1, 3), (2, 3), (1, 2, 3)} for example
# Looping through the combinations in the set s
for comb in s:
# comb = (1, 2) for example
# Set a flag (f) initially to 1
f = 1
# Loop through the sets in list_of_combinations
for ind, se in enumerate(list_of_combinations):
# See if comb exists in the set se
if comb not in se:
# If not, see if any number in comb exists in the ind-th list of
# the original list
for n in comb:
if n in org_list[ind]:
# If so, set f to 0
f = 0
break
# if f is still 1, then the current comb satisfy our conditions
# so we add it to the result
if f == 1:
combs.add(comb)
print(combs)
Output:
{(1, 2)}
as expected.
For the list in your question, the output of this code is {(2, 3), (6, 7)} which is as expected also.
itertools.combinations?
itertools.combinations(iterable, r): Returns r length tuples of elements from the input iterable. For example:
list(itertools.combinations([1, 2, 3], 2))
gives
[(1, 2), (1, 3), (2, 3)]
Why using sets?
In the code above, you can notice that sets are used to hold the combinations of each list from the original list. This is because checking for membership of a value in a set is very fast, and we do a lot of such checks in the code.
Explaining the main idea
Assume that our original list is [[1, 2, 3], [2, 1, 4]].
Get the required set of combinations for each list in the original:
For [1, 2, 3]: the set of combinations is (1, 2), (1, 3), (2, 3), (1, 2, 3)
For [2, 1, 4]: the set of combinations is (1, 2), (1, 2, 4), (2, 4), (1, 4)
For each of the combinations, and in order to be in the output of our code (meaning that it satisfies our condition), we want to make sure that for each set of combinations, either
it exists in this set (i.e. the items of this combination occur together in this set)
or it does not exist in this set -> none of its items should appear in the corresponding list
For example
Let's take (1, 3) from the first set of combinations. We iterate through the combination sets:
For the first set, we can see that (1, 3) exists into it, so we move forward.
For the second set, we can see that it does not exist into it, so we want to see if any of its items exists in the corresponding list (i.e the second list of the original list: [2, 1, 4]):
Starting with 1, we can see that it exists in the corresponding list -> (1, 3) can't be in the output because it does not satisfy the required condition.

This is more of a brute-force solution, however, it will generate a large list of all elements that occur together by generating permutations of every sublist in l and filtering to find any permutations whose elements of which all appear in a sublist of l. If any permutations pass that condition, the permutation will be added to final_pairs:
l = [[1,2,3],[6,5,4,3,7,2],[4,3,2,9],[6,7],[5,1,0],[6,3,2,7]]
import itertools
final_pairs = []
for i in l:
combos = [list(itertools.permutations(i, b)) for b in range(2, len(i))]
for combo in combos:
for b in combo:
if any(all(c in a for c in b) for a in l):
final_pairs.append(combo)
final_data = list(set(itertools.chain.from_iterable(final_pairs)))
Output:
[(2, 5, 6, 7, 3), (7, 3), (2, 6, 3, 7), (5, 3, 2, 6, 7), (5, 6, 4, 7), (7, 2, 5, 4, 6), (6, 7, 3, 4), (5, 2, 3, 7, 6), (7, 4, 3, 2), (6, 4, 7, 2), (4, 7, 6), (7, 3, 4, 6, 2), (5, 3, 7, 2, 6), (5, 7, 6, 4), (7, 4, 6, 2, 5), (7, 5, 4, 6, 3), (4, 2, 7, 3, 5), (4, 7, 3, 2), (2, 5, 4, 7, 3), (6, 5, 7, 2, 4), (4, 6, 7, 2), (2, 7, 5, 6, 3), (2, 6, 7), (5, 4, 2, 3, 7), (2, 3, 4, 6, 5), (5, 7, 2, 3), (3, 2, 4, 7, 6), (2, 6, 3, 5, 7), (3, 6, 5, 4, 7), (6, 5, 7), (2, 4, 6, 7, 5), (4, 3, 5, 2), (2, 3, 5, 7), (4, 5, 7, 3), (4, 6, 7, 2, 5), (3, 4, 5, 7, 2), (2, 4, 5, 6, 3), (3, 5, 2, 7, 6), (6, 3, 5, 7, 2), (5, 2, 7, 3, 6), (6, 3, 5, 4, 2), (2, 7, 4, 5), (2, 5, 3), (3, 2), (3, 2, 6, 7), (5, 3, 7, 6, 4), (4, 5), (2, 7, 3, 6, 4), (6, 4, 2, 5), (7, 5, 4, 2, 6), (2, 4, 3, 7, 6), (3, 2, 6), (4, 5, 3, 6), (7, 4, 3, 6, 5), (7, 3, 4), (5, 3, 4, 6, 7), (6, 5, 3, 2, 4), (6, 4, 2, 3), (5, 2, 7, 6, 3), (5, 4, 6, 3, 7), (3, 2, 6, 5, 7), (6, 5, 4, 3, 7), (3, 5, 2, 6, 4), (7, 3, 6, 2, 5), (2, 3, 7, 6, 4), (3, 4, 5, 2, 7), (7, 3, 5, 2), (2, 4, 5, 7), (2, 3, 6, 4), (7, 5, 6, 4), (7, 6, 2), (3, 9, 4), (4, 6, 5), (6, 4, 5, 3, 2), (6, 7, 3, 2, 5), (3, 5, 7, 6), (2, 5, 3, 4, 6), (5, 3, 6), (2, 3, 4, 6, 7), (6, 5, 2, 3, 7), (6, 3, 5, 2, 4), (5, 4, 2, 3), (5, 7, 6, 3, 2), (4, 6, 5, 2, 7), (7, 5, 2, 3), (4, 5, 2, 6, 3), (5, 7, 6, 3), (2, 7, 3, 4, 6), (2, 3, 6), (7, 4, 3, 5), (4, 3, 5, 6, 7), (7, 3, 6, 5, 2), (6, 2, 5, 3, 7), (5, 6, 4), (5, 2, 7, 6), (4, 6, 2, 3), (4, 3, 2, 6, 7), (3, 2, 7, 5), (6, 7, 2, 4, 5), (4, 3, 6, 2), (4, 3, 6, 7, 2), (6, 7, 4, 3, 2), (5, 1), (5, 7, 4, 3, 2), (6, 3, 7), (6, 7, 3, 4, 2), (7, 6, 3, 5, 2), (4, 9, 3), (4, 7, 5, 2), (5, 4, 2, 7, 6), (5, 3, 7, 2, 4), (3, 2, 5, 4, 7), (4, 2, 5, 7, 6), (3, 7, 6, 4), (7, 3, 2, 6, 4), (7, 2, 5, 3, 6), (2, 3, 5, 6, 4), (4, 5, 2, 3, 6), (5, 6, 7, 4, 3), (4, 2, 6, 5, 7), (6, 2, 3, 7), (7, 4, 5, 3), (5, 3, 4, 2, 7), (5, 7, 3), (5, 7, 3, 2, 6), (3, 5, 2, 7), (2, 7, 6, 5, 4), (4, 6, 5, 7), (3, 4, 7, 6, 5), (6, 2, 3, 5, 7), (6, 5, 3, 4, 2), (5, 4, 7, 2), (5, 7, 4, 6), (7, 6, 2, 5), (3, 4, 9), (6, 4, 5, 7, 2), (4, 7, 5, 3, 2), (3, 5, 6, 2), (4, 7, 2, 6, 3), (5, 4, 7), (5, 3, 7, 6, 2), (2, 4, 3, 5, 7), (1, 0), (3, 2, 6, 7, 5), (2, 3, 4, 7, 6), (6, 5, 2, 7), (7, 5, 2, 4, 3), (5, 3, 6, 2, 4), (2, 7), (2, 3, 6, 5, 7), (5, 3, 2, 6), (2, 6, 3, 4, 5), (6, 3, 7, 4, 5), (5, 6, 4, 2, 3), (2, 6, 5, 3, 4), (3, 4, 2, 7, 5), (5, 7, 3, 6, 4), (6, 3, 4, 5), (7, 4), (6, 7, 5), (7, 4, 6, 2), (6, 4, 3, 2, 7), (3, 5, 6), (3, 5, 6, 4, 2), (7, 2, 4), (2, 3, 6, 4, 5), (4, 2, 3), (2, 5, 3, 4, 7), (5, 2, 3, 6, 7), (4, 7, 6, 2), (3, 4, 6), (4, 3, 7, 6, 5), (7, 2, 4, 6, 5), (5, 3, 6, 7), (4, 6, 2, 5, 7), (6, 4, 3, 7, 2), (7, 4, 5, 2, 6), (3, 6, 7, 4, 5), (3, 6, 2, 5, 7), (3, 6, 2, 5), (5, 3, 4, 2, 6), (6, 5, 4, 3), (7, 4, 2, 3, 5), (2, 4, 5, 6, 7), (3, 7, 4, 5, 2), (2, 4, 7, 5), (5, 7, 3, 4), (7, 5, 4, 6), (4, 7, 6, 5, 3), (4, 3, 2, 6, 5), (7, 6, 2, 4, 5), (6, 3, 4), (3, 4, 6, 2, 5), (2, 5, 4, 6, 3), (2, 6, 3, 7, 5), (6, 7, 2, 5, 4), (6, 5, 7, 3, 2), (4, 7, 3, 2, 6), (2, 6, 7, 4, 5), (2, 3, 5, 6), (3, 2, 5, 4), (5, 7, 6, 4, 2), (2, 4, 5, 7, 3), (7, 5, 4, 2, 3), (7, 6, 3, 5), (6, 5, 4), (3, 6, 5, 7, 4), (2, 7, 3, 6, 5), (4, 5, 2, 7), (7, 3, 5, 6, 4), (5, 7, 4, 2, 6), (7, 4, 3, 5, 6), (3, 4, 6, 2, 7), (2, 5, 4, 7), (2, 7, 6, 3, 4), (5, 7, 3, 2, 4), (2, 6, 7, 3), (3, 4, 2, 5), (3, 7, 2, 4, 6), (7, 6, 4, 2, 3), (3, 2, 7), (7, 6, 5, 2, 3), (7, 6, 4, 3), (5, 6, 3, 2, 4), (6, 5, 3, 4, 7), (9, 2, 4), (6, 7, 3, 5), (2, 3, 4, 7, 5), (7, 6, 4, 5), (6, 2, 5, 4), (5, 6, 7, 2, 4), (4, 6, 5, 7, 3), (4, 2, 3, 5, 6), (4, 5, 7, 3, 2), (4, 2, 6, 7), (6, 3, 4, 5, 7), (4, 7, 6, 2, 5), (7, 6, 3), (2, 6, 7, 3, 4), (6, 7, 3, 4, 5), (4, 6, 7, 5), (7, 5, 3, 4), (5, 6, 7, 3, 2), (5, 2, 6, 7), (3, 4), (7, 5, 3, 4, 6), (5, 7, 3, 6, 2), (7, 3, 6, 2, 4), (4, 7), (4, 5, 7, 6), (5, 6, 4, 2, 7), (3, 6, 7, 4), (5, 6), (7, 2, 5, 6, 4), (4, 5, 6, 7, 3), (2, 4, 3, 6, 5), (2, 3, 7), (7, 6, 3, 2, 4), (6, 4, 3, 5, 7), (6, 2, 7), (6, 3, 2, 7), (3, 5, 4, 6), (7, 6, 5, 4, 2), (6, 4, 7), (3, 7, 4, 2, 6), (3, 4, 2), (6, 2, 7, 5, 4), (2, 6, 5, 7, 3), (6, 2, 4, 5, 3), (4, 5, 3, 7), (4, 2, 6, 7, 3), (2, 4, 3), (4, 7, 3, 6, 5), (2, 4, 6, 3, 5), (6, 5, 7, 4, 3), (3, 7, 4, 6, 5), (7, 2, 4, 3, 6), (6, 7, 3, 2, 4), (6, 2, 7, 5, 3), (3, 4, 7, 2), (7, 4, 5, 6, 3), (2, 6, 5, 4, 7), (3, 6, 4, 7), (5, 7, 2), (2, 4, 5, 6), (2, 7, 4, 3, 6), (4, 5, 6, 2, 7), (5, 2, 3, 6), (4, 9, 2), (5, 4, 6, 7), (7, 3, 4, 6), (3, 2, 5, 7, 6), (7, 5, 4, 6, 2), (3, 7, 2, 5, 6), (3, 6, 5, 2, 4), (6, 4, 2, 3, 5), (6, 3, 2, 4, 7), (5, 4, 3, 7, 2), (5, 4, 3, 7, 6), (5, 7, 2, 4, 3), (3, 7, 2, 4), (4, 3, 2, 6), (4, 2, 6, 3, 5), (7, 4, 2, 6, 3), (4, 3, 6, 7), (2, 7, 5, 4), (5, 2, 4, 3, 7), (7, 3, 5, 4, 2), (3, 5, 2, 4, 6), (3, 2, 7, 6), (5, 7, 4, 6, 3), (9, 2, 3), (3, 2, 4, 5, 6), (2, 7, 5, 6, 4), (5, 3, 7, 6), (4, 7, 5, 3), (7, 3, 5, 2, 6), (6, 2, 7, 3), (7, 3, 4, 2, 5), (3, 7, 6, 5), (7, 2, 5), (5, 6, 2, 4), (7, 4, 5, 6), (2, 7, 6, 4, 3), (6, 2, 7, 5), (3, 6, 4, 7, 2), (2, 4, 3, 7, 5), (2, 6, 5, 7), (2, 5, 3, 6, 7), (3, 5, 2, 4), (1, 3), (4, 7, 3, 5, 6), (4, 5, 7, 3, 6), (2, 5), (2, 4, 7, 3, 5), (5, 4, 7, 3), (6, 5, 4, 2, 7), (5, 3, 2, 4, 7), (7, 3, 2, 6, 5), (7, 6, 2, 4), (5, 2, 3), (6, 7), (3, 6, 5, 7), (7, 6), (2, 7, 6, 3), (7, 5, 6, 2, 4), (4, 6, 2, 5, 3), (2, 6, 5), (6, 7, 5, 2), (3, 7, 5, 6), (6, 5, 2, 4, 7), (5, 4, 7, 2, 3), (5, 4, 3, 6), (4, 6, 2, 7, 5), (4, 2, 6, 7, 5), (5, 3, 2, 7), (5, 2, 4, 3), (7, 4, 6, 3, 2), (6, 4, 3, 2, 5), (3, 7, 4, 5, 6), (3, 7, 2), (7, 6, 3, 4, 2), (6, 2, 5, 7, 4), (2, 5, 4, 6, 7), (6, 3, 4, 2, 7), (7, 5, 2, 3, 6), (7, 6, 4, 5, 3), (5, 3, 6, 4, 7), (5, 3, 6, 2), (4, 7, 2, 5, 3), (4, 7, 6, 5), (4, 2, 7, 6), (7, 5, 6), (2, 6, 4, 5), (2, 4, 7, 6, 3), (3, 2, 4), (5, 3, 6, 4), (3, 7, 2, 5, 4), (7, 3, 6), (5, 3, 2, 7, 6), (2, 3, 7, 4, 5), (6, 3, 2, 5, 4), (2, 6, 4, 3), (3, 7, 6, 5, 2), (9, 4, 3), (6, 7, 2, 3, 5), (7, 4, 5, 3, 6), (3, 1), (2, 4, 5, 3, 6), (3, 6, 2, 4), (2, 5, 3, 4), (5, 2, 7, 3, 4), (4, 3, 6), (3, 2, 4, 6, 7), (3, 4, 5, 6), (5, 7, 3, 4, 6), (3, 6, 4, 5), (3, 4, 7, 5), (2, 4, 3, 5), (4, 6, 7), (5, 4, 3, 6, 2), (7, 3, 6, 4), (3, 2, 4, 6, 5), (4, 5, 6, 3), (4, 6, 7, 5, 2), (6, 7, 5, 2, 4), (6, 4, 7, 5, 3), (6, 5, 4, 2, 3), (4, 2, 3, 5, 7), (5, 6, 2, 7, 4), (4, 5, 2, 6), (6, 3, 5, 4), (7, 2, 5, 4, 3), (3, 6, 4, 2), (9, 4), (6, 2, 3, 5, 4), (4, 6, 5, 3, 2), (6, 3, 5, 2), (2, 5, 4, 6), (7, 6, 4, 3, 2), (7, 5, 3, 4, 2), (7, 4, 2, 5, 3), (2, 7, 3, 4), (5, 6, 2, 3, 7), (7, 2, 5, 6), (4, 3, 2, 7, 6), (5, 6, 4, 3), (4, 7, 6, 3, 5), (3, 4, 2, 7, 6), (2, 6, 7, 4), (2, 5, 7, 6, 4), (4, 3, 6, 5, 2), (2, 6, 3, 5), (7, 6, 4, 2), (4, 6, 7, 3, 2), (3, 6), (6, 7, 3, 2), (7, 2, 4, 6, 3), (6, 2, 5, 7), (3, 2, 5, 6, 7), (5, 7, 6, 2), (5, 6, 4, 3, 7), (6, 4, 3, 7, 5), (5, 4), (6, 5, 4, 3, 2), (7, 5, 6, 2, 3), (6, 2, 4, 5, 7), (7, 3, 5, 4, 6), (2, 6, 4, 3, 5), (3, 5, 2, 7, 4), (5, 3, 4, 7, 6), (2, 3, 4, 6), (4, 2, 5), (4, 6, 3, 5), (5, 3, 7, 4, 6), (6, 7, 5, 4, 3), (6, 4, 7, 3, 2), (4, 2, 5, 3, 6), (4, 5, 6), (5, 2, 6, 4, 7), (3, 6, 7, 5), (6, 3, 4, 2, 5), (6, 5, 7, 3, 4), (5, 6, 3, 4, 2), (3, 2, 6, 5, 4), (2, 5, 7, 4, 6), (2, 3, 4, 5, 7), (3, 5, 4, 7), (4, 2, 7, 3, 6), (5, 2, 4), (4, 5, 3, 2), (2, 7, 5, 3, 6), (4, 2, 5, 3), (6, 4, 2, 7), (2, 5, 4, 3, 7), (2, 5, 7, 6, 3), (3, 5, 4), (3, 2, 5, 7, 4), (7, 2, 6, 4, 5), (4, 3, 5, 7, 6), (3, 2, 6, 4, 5), (7, 6, 5, 4), (6, 2, 4, 5), (2, 4, 5, 3), (2, 7, 3), (2, 5, 6, 3, 7), (3, 7, 5), (6, 2), (6, 2, 4, 3), (5, 3, 4, 6), (7, 5, 6, 2), (3, 6, 2, 4, 7), (5, 2, 3, 7), (5, 4, 2, 6, 7), (5, 6, 2, 3, 4), (4, 3, 2, 7), (3, 5, 7, 4), (5, 4, 2, 7), (4, 6, 5, 2, 3), (4, 7, 5), (5, 4, 3, 2, 7), (2, 5, 6, 4, 3), (4, 6, 3, 7, 5), (6, 2, 4, 3, 7), (5, 2, 3, 4, 6), (7, 5, 3, 6, 2), (3, 7, 2, 5), (2, 3, 4, 5, 6), (5, 4, 2, 7, 3), (3, 2, 7, 6, 5), (2, 6, 4), (7, 4, 2), (7, 5, 3, 2, 4), (6, 2, 7, 3, 5), (5, 2, 7, 4), (4, 6, 2, 5), (7, 4, 3, 2, 6), (2, 4, 6, 5, 3), (4, 7, 5, 6), (2, 7, 5, 3), (7, 3, 6, 4, 5), (6, 5, 2), (2, 5, 7, 3, 6), (5, 3, 2, 6, 4), (3, 6, 7, 2, 4), (6, 4, 5, 3), (6, 2, 7, 4, 5), (6, 4, 5, 3, 7), (2, 3), (3, 6, 5, 4, 2), (2, 5, 6), (5, 6, 2, 3), (2, 3, 7, 6, 5), (6, 3, 2, 7, 4), (6, 5, 2, 4, 3), (6, 2, 7, 4), (6, 4, 2, 5, 7), (6, 5), (5, 6, 4, 3, 2), (6, 2, 3, 5), (4, 6, 5, 3), (4, 3, 5, 6, 2), (5, 4, 7, 6, 2), (5, 4, 7, 6), (7, 3, 2, 4, 5), (6, 5, 4, 7, 3), (4, 2, 3, 6, 7), (2, 5, 6, 4, 7), (3, 6, 5, 2), (6, 7, 4, 3, 5), (2, 3, 7, 6), (6, 3, 2), (4, 3, 7), (2, 5, 4, 7, 6), (3, 6, 5, 4), (3, 7, 2, 6), (2, 6, 5, 4, 3), (4, 2, 7, 5, 3), (6, 5, 2, 3), (6, 2, 3, 7, 4), (3, 5, 2, 6, 7), (5, 6, 2, 4, 7), (2, 7, 5, 3, 4), (6, 7, 5, 3), (2, 7, 3, 4, 5), (5, 4, 3, 7), (7, 4, 6, 5, 2), (2, 5, 7, 3, 4), (3, 5, 7, 2, 6), (5, 3, 2, 4), (7, 5, 4, 3, 2), (6, 7, 5, 3, 2), (4, 3, 7, 6, 2), (2, 4, 6, 5, 7), (4, 3, 7, 2), (5, 7, 3, 4, 2), (6, 3, 4, 7), (5, 6, 7, 2), (6, 2, 5), (2, 6, 7, 5, 3), (5, 6, 7), (7, 4, 5, 2, 3), (5, 3, 6, 7, 4), (3, 6, 2, 7, 5), (2, 3, 6, 5, 4), (6, 4, 7, 2, 3), (6, 3, 5, 7, 4), (7, 2, 6, 5, 3), (7, 4, 2, 3), (3, 2, 4, 7), (5, 4, 2), (4, 7, 2, 5), (2, 4, 5), (2, 5, 6, 7, 4), (5, 7, 2, 3, 6), (3, 6, 7), (4, 3, 5, 2, 6), (5, 7, 6, 2, 3), (4, 7, 2, 3), (6, 2, 4, 7, 3), (3, 4, 6, 5, 2), (5, 6, 3, 7, 4), (3, 6, 2, 7), (3, 5, 7, 6, 4), (2, 3, 6, 7, 4), (3, 2, 7, 5, 6), (3, 4, 5, 7), (7, 3, 4, 2, 6), (5, 7, 3, 2), (2, 3, 5, 6, 7), (4, 2, 7, 5, 6), (3, 5, 4, 6, 7), (7, 3, 6, 5), (3, 6, 2, 7, 4), (6, 5, 3, 7), (3, 6, 2, 4, 5), (4, 5, 6, 2), (4, 5, 3, 7, 2), (4, 5, 7), (7, 3, 4, 5, 2), (3, 5, 4, 2, 6), (5, 7, 6, 4, 3), (2, 5, 4, 3), (3, 7, 5, 6, 2), (7, 5, 2, 3, 4), (6, 5, 7, 2), (4, 7, 2), (3, 9), (3, 7, 4, 5), (6, 2, 4, 3, 5), (4, 3), (7, 4, 2, 5), (6, 4, 3, 2), (5, 6, 4, 7, 2), (5, 2), (4, 3, 9), (5, 6, 4, 2), (5, 2, 6, 4, 3), (5, 3, 6, 2, 7), (2, 5, 6, 4), (4, 7, 6, 2, 3), (2, 6, 3, 4), (7, 3, 5, 6), (7, 2, 3), (4, 7, 5, 2, 3), (3, 4, 5, 2, 6), (4, 2, 6, 3), (3, 5, 6, 7, 2), (4, 5, 6, 7, 2), (7, 4, 2, 6, 5), (2, 7, 4), (4, 2, 3, 7, 5), (3, 7, 4), (2, 4, 6, 5), (7, 4, 3, 2, 5), (4, 7, 3, 5), (6, 7, 4, 5, 2), (4, 3, 7, 2, 6), (3, 6, 5, 7, 2), (3, 5, 7, 2, 4), (2, 4, 6, 3), (7, 5, 3, 2), (4, 6, 3, 5, 7), (2, 3, 5, 4), (4, 3, 5, 7, 2), (3, 2, 7, 4, 5), (5, 7, 2, 6), (4, 2, 5, 7, 3), (4, 6, 3, 2), (2, 6, 5, 7, 4), (1, 5), (3, 5, 4, 2), (5, 2, 7, 6, 4), (4, 7, 3, 6, 2), (2, 6, 3), (7, 4, 3), (6, 3, 2, 5), (4, 2, 3, 6, 5), (2, 6), (2, 7, 4, 6), (2, 6, 5, 4), (5, 2, 7, 4, 6), (2, 7, 3, 5, 6), (4, 6, 3, 2, 7), (5, 7, 2, 3, 4), (7, 2, 6, 5), (2, 3, 7, 5, 6), (6, 5, 3), (6, 2, 4, 7, 5), (7, 5), (7, 2, 6, 3), (4, 3, 5, 2, 7), (2, 6, 4, 5, 7), (3, 5, 7, 6, 2), (5, 3, 2), (5, 6, 7, 4, 2), (2, 5, 7), (3, 5, 6, 2, 4), (3, 2, 7, 4, 6), (2, 3, 5, 4, 7), (2, 3, 6, 7), (7, 6, 5, 3, 4), (7, 6, 3, 2, 5), (4, 5, 2, 3, 7), (7, 5, 4), (6, 5, 7, 2, 3), (5, 4, 6, 3), (7, 3, 4, 2), (5, 3, 4, 7), (5, 4, 2, 3, 6), (7, 5, 6, 3), (5, 2, 3, 4), (2, 3, 9), (5, 4, 2, 6), (3, 4, 5), (4, 7, 2, 5, 6), (3, 6, 4, 5, 2), (3, 2, 6, 7, 4), (6, 4, 2, 5, 3), (2, 7, 4, 5, 3), (4, 5, 6, 2, 3), (4, 6, 5, 7, 2), (7, 5, 2, 6), (6, 4, 5, 7, 3), (6, 3, 7, 4), (5, 2, 7, 3), (2, 5, 3, 7, 6), (2, 1), (5, 2, 6, 3, 7), (2, 7, 5, 6), (7, 2, 3, 4), (2, 6, 4, 7, 5), (2, 3, 7, 4, 6), (3, 4, 5, 6, 7), (4, 6, 3, 5, 2), (4, 5, 6, 3, 7), (3, 6, 7, 4, 2), (7, 2), (5, 3, 7, 4), (2, 4, 7, 5, 6), (6, 4, 5, 2), (6, 2, 4), (4, 3, 6, 2, 7), (5, 6, 2, 4, 3), (4, 2, 5, 3, 7), (2, 4, 7, 3, 6), (2, 5, 6, 7), (7, 2, 5, 6, 3), (2, 6, 7, 4, 3), (2, 6, 5, 3), (2, 6, 5, 3, 7), (2, 5, 4, 3, 6), (4, 6, 7, 3, 5), (5, 2, 3, 6, 4), (5, 6, 7, 2, 3), (6, 5, 7, 4, 2), (6, 2, 3, 4), (5, 4, 3), (4, 6, 5, 2), (7, 2, 6, 4, 3), (6, 4, 3, 5, 2), (2, 7, 4, 6, 3), (3, 6, 4), (6, 3, 4, 7, 2), (7, 5, 2, 6, 4), (4, 5, 2, 7, 3), (3, 4, 2, 6, 5), (3, 4, 7, 2, 6), (4, 2, 5, 6, 7), (5, 3, 4, 6, 2), (3, 7, 5, 2, 6), (4, 7, 5, 6, 3), (4, 3, 7, 2, 5), (3, 6, 2, 5, 4), (6, 5, 3, 2, 7), (3, 4, 2, 6, 7), (3, 4, 6, 7, 2), (3, 7, 6, 2, 5), (3, 5, 2), (6, 3, 2, 4, 5), (6, 7, 4, 2, 3), (2, 3, 7, 5, 4), (3, 5), (4, 2, 7), (5, 2, 4, 7), (4, 5, 2, 7, 6), (4, 6), (2, 3, 7, 5), (7, 2, 4, 6), (5, 7), (3, 2, 5, 4, 6), (5, 4, 6, 3, 2), (4, 5, 7, 6, 2), (5, 2, 4, 7, 3), (5, 6, 7, 3), (4, 2, 3, 5), (7, 2, 4, 3), (4, 7, 3), (4, 7, 5, 2, 6), (7, 6, 2, 3), (5, 2, 6), (7, 2, 4, 5, 6), (2, 6, 3, 4, 7), (2, 5, 7, 3), (4, 3, 7, 5, 6), (6, 4, 5, 2, 3), (2, 6, 4, 7), (7, 4, 3, 5, 2), (7, 3, 2, 5), (5, 2, 7, 4, 3), (5, 2, 6, 7, 3), (4, 7, 2, 3, 6), (3, 7, 2, 6, 5), (3, 2, 6, 4, 7), (3, 4, 7, 5, 6), (5, 4, 3, 2), (2, 3, 6, 7, 5), (3, 4, 5, 2), (2, 5, 7, 4, 3), (2, 3, 4, 5), (2, 7, 5), (5, 4, 6, 2, 3), (3, 7, 2, 6, 4), (4, 3, 6, 2, 5), (2, 4, 7, 6), (3, 5, 6, 7), (2, 4, 3, 7), (2, 6, 7, 3, 5), (6, 2, 3, 4, 7), (6, 5, 3, 7, 2), (3, 5, 7, 4, 2), (3, 5, 6, 4), (3, 6, 4, 5, 7), (7, 6, 3, 2), (5, 7, 4, 6, 2), (7, 3, 4, 6, 5), (2, 7, 6, 5, 3), (2, 7, 6, 4, 5), (6, 7, 5, 4), (4, 3, 6, 5, 7), (2, 7, 6, 5), (3, 7, 5, 4), (2, 6, 3, 5, 4), (6, 5, 7, 3), (2, 7, 6, 4), (6, 7, 5, 3, 4), (4, 3, 2, 7, 5), (2, 9, 4), (3, 5, 7, 4, 6), (6, 4, 3, 5), (7, 6, 5, 4, 3), (3, 4, 7, 5, 2), (6, 5, 2, 3, 4), (7, 3, 2, 5, 6), (7, 2, 5, 4), (2, 4, 6, 7, 3), (3, 7, 5, 2, 4), (6, 4, 2, 7, 5), (6, 2, 5, 3), (3, 2, 7, 5, 4), (7, 6, 2, 4, 3), (2, 5, 4), (7, 3, 5, 2, 4), (2, 4, 6, 3, 7), (7, 4, 3, 6), (6, 5, 2, 7, 3), (4, 6, 7, 5, 3), (4, 7, 6, 5, 2), (0, 5), (7, 5, 3), (4, 7, 2, 6, 5), (7, 4, 2, 5, 6), (4, 7, 3, 6), (4, 7, 3, 2, 5), (5, 3, 6, 4, 2), (5, 3, 7, 4, 2), (5, 6, 3, 7, 2), (2, 4), (7, 5, 6, 4, 2), (2, 6, 4, 5, 3), (5, 2, 6, 4), (4, 6, 3, 7), (7, 3, 6, 4, 2), (6, 5, 4, 2), (4, 3, 5), (6, 3, 2, 5, 7), (3, 2, 5), (7, 3, 6, 5, 4), (4, 3, 5, 6), (2, 7, 4, 3), (2, 4, 3, 6, 7), (6, 7, 3, 5, 2), (2, 3, 6, 4, 7), (4, 5, 7, 6, 3), (3, 2, 6, 5), (6, 3, 2, 4), (4, 2, 5, 7), (4, 5, 3, 6, 7), (3, 5, 2, 4, 7), (5, 7, 6), (7, 2, 6, 4), (7, 4, 6, 3), (3, 2, 4, 5, 7), (2, 9, 3), (5, 6, 3, 2, 7), (5, 6, 7, 4), (7, 2, 6, 3, 4), (7, 6, 4, 2, 5), (6, 2, 3), (2, 6, 4, 7, 3), (6, 5, 2, 7, 4), (4, 2, 3, 7, 6), (6, 4, 3), (5, 2, 6, 3, 4), (5, 6, 2, 7, 3), (7, 6, 5, 2), (6, 2, 4, 7), (5, 3, 4, 2), (3, 7, 5, 6, 4), (5, 7, 2, 6, 4), (4, 3, 7, 6), (5, 4, 6, 2), (6, 3, 7, 4, 2), (9, 3), (2, 4, 7), (3, 5, 4, 2, 7), (3, 6, 5), (4, 2, 6, 5, 3), (7, 3, 4, 5, 6), (6, 7, 4, 5), (7, 3, 4, 5), (5, 3, 2, 7, 4), (3, 5, 7, 2), (9, 3, 4), (6, 7, 2, 5, 3), (3, 5, 6, 4, 7), (2, 5, 7, 4), (5, 4, 7, 3, 6), (6, 7, 4, 3), (4, 3, 2, 5), (3, 6, 4, 2, 5), (7, 4, 6, 5), (6, 3, 7, 5), (3, 7, 4, 2, 5), (6, 4, 7, 2, 5), (7, 3, 2, 5, 4), (4, 2, 6), (4, 2, 3, 6), (7, 2, 3, 5), (2, 7, 4, 5, 6), (4, 6, 2, 7), (2, 7, 6, 3, 5), (7, 4, 5, 3, 2), (2, 6, 3, 7, 4), (6, 4, 5, 7), (5, 3, 6, 7, 2), (7, 6, 2, 3, 4), (7, 4, 2, 3, 6), (3, 7, 6, 2), (5, 6, 2, 7), (5, 7, 6, 2, 4), (5, 2, 4, 6, 3), (4, 3, 6, 7, 5), (5, 4, 2, 6, 3), (5, 2, 7), (9, 4, 2), (2, 7, 4, 3, 5), (7, 2, 4, 3, 5), (4, 6, 3, 2, 5), (6, 3, 7, 2, 5), (6, 7, 2), (3, 7, 6, 4, 5), (4, 5, 3, 7, 6), (6, 3, 7, 2, 4), (7, 2, 3, 5, 4), (3, 7), (7, 6, 5, 3, 2), (4, 5, 3, 2, 6), (3, 7, 5, 4, 2), (5, 6, 4, 7, 3), (4, 5, 2, 6, 7), (2, 5, 3, 7, 4), (2, 7, 6), (5, 7, 4, 2), (7, 6, 3, 4), (3, 7, 6), (4, 3, 7, 5, 2), (5, 4, 7, 6, 3), (5, 2, 4, 3, 6), (6, 4, 2, 3, 7), (6, 4, 5, 2, 7), (7, 6, 5, 2, 4), (7, 3, 2, 4), (3, 6, 7, 5, 4), (2, 6, 7, 5, 4), (3, 2, 4, 6), (5, 2, 4, 6), (7, 5, 6, 4, 3), (7, 2, 3, 6, 4), (6, 3, 7, 5, 2), (6, 2, 7, 4, 3), (7, 2, 4, 5), (3, 6, 4, 2, 7), (5, 2, 4, 7, 6), (2, 7, 5, 4, 6), (7, 5, 2, 4, 6), (2, 3, 5, 7, 6), (7, 4, 5), (3, 5, 4, 7, 6), (2, 5, 7, 6), (3, 4, 6, 5, 7), (4, 2, 7, 5), (7, 6, 3, 5, 4), (6, 7, 2, 3), (4, 2, 7, 3), (7, 4, 6, 2, 3), (4, 6, 3), (7, 3, 2, 6), (2, 4, 5, 3, 7), (6, 7, 2, 5), (5, 6, 3, 7), (5, 3, 2, 4, 6), (5, 7, 2, 6, 3), (4, 7, 5, 6, 2), (3, 4, 5, 6, 2), (2, 4, 7, 3), (5, 7, 3, 6), (2, 5, 3, 7), (7, 5, 2), (4, 5, 7, 2, 3), (4, 6, 2, 7, 3), (6, 2, 5, 3, 4), (2, 3, 4), (7, 3, 2), (7, 5, 4, 2), (7, 5, 4, 3, 6), (5, 6, 2), (7, 5, 3, 2, 6), (3, 2, 5, 6), (3, 4, 7), (6, 3, 5, 2, 7), (3, 7, 4, 6, 2), (7, 4, 5, 6, 2), (7, 2, 3, 6, 5), (6, 3, 5), (4, 3, 2), (3, 4, 6, 7, 5), (6, 7, 4, 2, 5), (7, 6, 4), (4, 5, 2, 3), (6, 3, 5, 7), (7, 6, 4, 5, 2), (6, 4, 2, 7, 3), (6, 5, 7, 4), (2, 4, 5, 7, 6), (7, 2, 5, 3), (6, 2, 5, 4, 3), (4, 2, 7, 6, 3), (7, 2, 3, 5, 6), (6, 4, 7, 5), (4, 6, 2, 3, 5), (3, 4, 6, 2), (2, 5, 3, 6), (6, 7, 2, 3, 4), (4, 6, 3, 7, 2), (6, 4, 7, 3), (6, 2, 5, 4, 7), (7, 3, 5, 4), (3, 7, 6, 5, 4), (6, 4, 2), (4, 2, 6, 5), (4, 5, 3, 6, 2), (4, 5, 2), (6, 4), (7, 5, 2, 6, 3), (4, 7, 2, 3, 5), (3, 5, 6, 7, 4), (3, 7, 6, 2, 4), (2, 4, 6, 7), (4, 6, 7, 3), (7, 5, 3, 6), (2, 4, 6), (3, 6, 2), (6, 7, 5, 2, 3), (6, 4, 7, 5, 2), (4, 7, 3, 5, 2), (6, 5, 4, 7), (7, 2, 6, 5, 4), (5, 2, 6, 3), (3, 6, 7, 2), (6, 3, 4, 5, 2), (5, 7, 2, 4), (2, 3, 5, 7, 4), (4, 5, 7, 2), (6, 5, 3, 7, 4), (5, 2, 3, 4, 7), (4, 3, 5, 7), (3, 2, 4, 7, 5), (7, 6, 4, 3, 5), (3, 4, 2, 5, 6), (7, 2, 6), (2, 5, 3, 6, 4), (9, 2), (3, 2, 6, 4), (3, 2, 5, 6, 4), (4, 2, 5, 6), (6, 2, 3, 4, 5), (7, 5, 6, 3, 4), (3, 5, 4, 6, 2), (5, 4, 7, 3, 2), (3, 6, 5, 2, 7), (7, 6, 2, 5, 3), (2, 4, 3, 6), (2, 7, 3, 5, 4), (2, 7, 4, 6, 5), (5, 7, 4, 2, 3), (5, 4, 6, 7, 2), (4, 6, 5, 3, 7), (7, 2, 3, 4, 5), (7, 6, 5, 3), (3, 4, 7, 6), (6, 3, 2, 7, 5), (2, 3, 6, 5), (5, 3, 4), (3, 4, 5, 7, 6), (7, 2, 6, 3, 5), (6, 7, 3), (5, 4, 6, 2, 7), (6, 7, 5, 4, 2), (6, 4, 7, 3, 5), (7, 3, 2, 4, 6), (5, 2, 6, 7, 4), (4, 2, 9), (7, 6, 2, 5, 4), (2, 6, 4, 3, 7), (6, 7, 4, 2), (9, 3, 2), (4, 3, 6, 5), (2, 4, 7, 5, 3), (7, 5, 2, 4), (6, 3, 7, 2), (4, 2, 7, 6, 5), (6, 2, 3, 7, 5), (3, 2, 7, 4), (3, 7, 6, 4, 2), (4, 6, 2, 3, 7), (7, 2, 3, 6), (3, 7, 5, 4, 6), (5, 7, 2, 4, 6), (4, 3, 2, 5, 6), (5, 0), (7, 3, 5), (3, 6, 4, 7, 5), (2, 3, 7, 4), (5, 3, 7, 2), (4, 2, 5, 6, 3), (2, 5, 6, 3), (5, 2, 4, 6, 7), (4, 5, 7, 2, 6), (7, 4, 6), (3, 6, 7, 2, 5), (4, 3, 2, 5, 7), (5, 4, 3, 6, 7), (4, 2), (2, 4, 7, 6, 5), (7, 4, 5, 2), (5, 3), (4, 2, 6, 3, 7), (2, 4, 9), (3, 5, 2, 6), (3, 4, 2, 5, 7), (6, 3, 5, 4, 7), (4, 5, 3, 2, 7), (4, 6, 2), (0, 1), (7, 2, 3, 4, 6), (2, 3, 5, 4, 6), (5, 4, 3, 2, 6), (5, 3, 7), (4, 7, 6, 3, 2), (3, 5, 4, 7, 2), (3, 7, 4, 2), (3, 9, 2), (5, 7, 4, 3, 6), (4, 6, 7, 2, 3), (5, 2, 3, 7, 4), (7, 4, 6, 5, 3), (5, 7, 4, 3), (3, 6, 7, 5, 2), (3, 2, 7, 6, 4), (2, 3, 5), (2, 7, 5, 4, 3), (6, 2, 7, 3, 4), (3, 5, 6, 2, 7), (6, 5, 2, 4), (5, 6, 3), (7, 5, 6, 3, 2), (6, 4, 5), (7, 3, 5, 6, 2), (3, 2, 4, 5), (3, 7, 5, 2), (7, 2, 4, 5, 3), (5, 7, 6, 3, 4), (6, 3, 4, 2), (7, 6, 5), (4, 3, 7, 5), (1, 2), (5, 4, 7, 2, 6), (6, 7, 2, 4, 3), (2, 4, 3, 5, 6), (4, 9), (4, 2, 3, 7), (2, 9), (7, 2, 5, 3, 4), (4, 7, 6, 3), (7, 4, 2, 6), (5, 3, 4, 7, 2), (4, 7, 5, 3, 6), (5, 7, 4), (6, 3), (5, 4, 6, 7, 3), (6, 2, 5, 7, 3), (5, 6, 3, 2), (6, 5, 4, 7, 2), (4, 7, 2, 6), (3, 4, 2, 7), (6, 7, 2, 4), (5, 6, 3, 4), (7, 6, 2, 3, 5), (4, 5, 6, 3, 2), (5, 6, 3, 4, 7), (3, 2, 9), (5, 6, 7, 3, 4), (7, 5, 3, 6, 4), (4, 5, 3), (2, 3, 4, 7), (2, 7, 3, 6), (5, 4, 6), (7, 4, 3, 6, 2), (7, 3, 6, 2), (6, 5, 3, 4), (7, 5, 4, 3), (6, 7, 4, 5, 3), (3, 4, 7, 6, 2), (3, 2, 5, 7), (6, 5, 3, 2), (4, 5, 6, 7), (7, 4, 6, 3, 5), (3, 7, 2, 4, 5), (6, 7, 3, 5, 4), (6, 3, 4, 7, 5), (7, 6, 3, 4, 5), (2, 7, 3, 5), (6, 7, 4), (2, 5, 6, 3, 4), (3, 4, 7, 2, 5), (3, 5, 7), (3, 7, 4, 6), (6, 3, 7, 5, 4), (3, 4, 2, 6), (3, 4, 6, 5), (3, 4, 6, 7), (6, 4, 3, 7), (2, 6, 7, 5)]

Related

Get all possible combinations from a list of lists by picking one item from each list

I have a list of lists, and I would like to get all possible combinations by picking one item from each list.
For example the following list:
l = [[1,2],[3],[4,5,6],[7],[8,9]]
The output should be:
1,3,4,7,8
1,3,5,7,8
1,3,6,7,8
1,3,4,7,9
1,3,5,7,9
1,3,6,7,9
2,3,4,7,8
2,3,5,7,8
2,3,6,7,8
2,3,4,7,9
2,3,5,7,9
2,3,6,7,9
The number of lists and their items is random
Use itertools.product:
>>> l = [[1,2],[3],[4,5,6],[7],[8,9]]
>>> from itertools import product
>>> list(product(*l))
[(1, 3, 4, 7, 8), (1, 3, 4, 7, 9), (1, 3, 5, 7, 8), (1, 3, 5, 7, 9), (1, 3, 6, 7, 8), (1, 3, 6, 7, 9), (2, 3, 4, 7, 8), (2, 3, 4, 7, 9), (2, 3, 5, 7, 8), (2, 3, 5, 7, 9), (2, 3, 6, 7, 8), (2, 3, 6, 7, 9)]
itertools do the job for you
In [1]: from itertools import product
In [2]: l = [[1,2],[3],[4,5,6],[7],[8,9]]
In [3]: product(*l)
Out[3]: <itertools.product at 0x7f012ba3e780>
In [4]: list(product(*l))
Out[4]:
[(1, 3, 4, 7, 8),
(1, 3, 4, 7, 9),
(1, 3, 5, 7, 8),
(1, 3, 5, 7, 9),
(1, 3, 6, 7, 8),
(1, 3, 6, 7, 9),
(2, 3, 4, 7, 8),
(2, 3, 4, 7, 9),
(2, 3, 5, 7, 8),
(2, 3, 5, 7, 9),
(2, 3, 6, 7, 8),
(2, 3, 6, 7, 9)]

Find rows in which sum of column values have a specific result

I have the following dataframe:
value
0 2
1 3
2 10
3 1
4 12
I need to build a formula that identifies which rows that, when values are summed, result is 23.
In this case the output should be something like [2,3,4] (10+1+12).
I believe it is something in the permutation/combination field however the option I found that led me closer to that target demands an specific length of combinations, and that wouldn't be the case since the combination could be composed of n values (I will never know the exact size of n upfront).
Is there a way to do that?
from pandas import Series
import itertools
s = Series([2, 3, 10, 1, 12])
result = []
for a, b, c in itertools.combinations(s.index, 3):
combination_sum = s.iloc[[a, b, c]].sum()
if combination_sum == 23:
result.append((a, b, c))
result
you can generalize this and make it into a function for n values.
This is how you will generalize it
In example series I have added some more values for better understanding
from pandas import Series
import itertools
s = Series([2, 3, 10, 1, 12, 4, 5, 6, 7, 8])
def get_column_whose_sum_is(sum_value=23, combination_of_columns=3, data_as_series=s):
result = []
for columns in itertools.combinations(data_as_series.index, combination_of_columns):
combination_sum = data_as_series.iloc[list(columns)].sum()
if combination_sum == sum_value:
result.append(columns)
return result
get_column_whose_sum_is(sum_value = 33, combination_of_columns = 4, data_as_series = s)
# [(1, 2, 4, 9), (2, 4, 5, 8), (2, 4, 6, 7), (4, 7, 8, 9)]
get_column_whose_sum_is(sum_value = 23, combination_of_columns = 3, data_as_series = s)
# [(1, 4, 9), (2, 3, 4), (2, 6, 9), (2, 7, 8), (4, 5, 8), (4, 6, 7)]
#for loop to find all combinations possibilities
c=[]
for i in range(len(s.index)):
c=c+get_column_whose_sum_is(sum_value = 23, combination_of_columns = i, data_as_series = s)
print(c)
#[(1, 4, 9), (2, 3, 4), (2, 6, 9), (2, 7, 8), (4, 5, 8), (4, 6, 7), (0, 1, 2, 9), (0, 1, 4, 7), (0, 2, 5, 8), (0, 2, 6, 7), (0, 3, 4, 9), (0, 4, 5, 6), (0, 7, 8, 9), (1, 2, 5, 7), (1, 3, 4, 8), (1, 6, 8, 9), (2, 3, 5, 9), (2, 3, 6, 8), (3, 4, 5, 7), (5, 6, 7, 9), (0, 1, 2, 3, 8), (0, 1, 3, 4, 6), (0, 1, 5, 7, 9), (0, 1, 6, 7, 8), (0, 2, 3, 5, 7), (0, 3, 6, 8, 9), (1, 2, 3, 5, 6), (1, 3, 5, 8, 9), (1, 3, 6, 7, 9), (3, 5, 6, 7, 8), (0, 1, 3, 5, 6, 9), (0, 1, 3, 5, 7, 8)]
Be aware that a subset sum like that might incur in performance problems even with small samples.

How to increment i in the loop for using python to select different column

I would like to know how could be possible to create a loop for in Python 3 to increment the values of i, j, k ... for a specific application.
I need to select different columns but they cannot be select with themselves. Let's suppose that my dataframe has 7 columns. I will put an example bellow.
The idea is to create a selection like that:
[0, 1]
[0, 2]
[0, 3]
[0, 4]
[0, 5]
[0, 6]
...
[0, 3, 6]
[0, 3, 7]
[0, 4, 5]
[0, 4, 6]
[0, 4, 7]
[0, 5, 6]
[0, 5, 7]
[0, 6, 7]
[0, 1, 2, 3]
[0, 1, 2, 4]
[0, 1, 2, 5]
[0, 1, 2, 6]
[0, 1, 2, 7]
[0, 1, 2, 3, 4]
[0, 1, 2, 3, 5]
[0, 1, 2, 3, 6]
[0, 1, 2, 3, 7]
...
[0, 1, 2, 3, 4, 7]
[0, 1, 2, 3, 4, 5, 6]
[0, 1, 2, 3, 4, 5, 7]
[0, 1, 2, 3, 4, 5, 8]
[0, 1, 2, 3, 4, 5, 6, 7]
After some replies, I could be able to create the following code:
from itertools import combinations
numbers = []
A = [0,1,2,3,4,5,6,7]
for i in range(8):
for combo in combinations(A, i+2):
numbrs.append(combo)
The output is:
[(0, 1),
(0, 2),
(0, 3),
(0, 4), ...
How could I use those numbers as index of a iloc iterator ?
For examples, the numbers generated must substitute the code:
df.iloc[:,[i, j, k, ...]]
Then I will be able to interact among the columns
You can solve this using itertools.combinations and itertools.chain:
import itertools as it
list(it.chain(*(it.combinations(range(8), r) for r in range(2, 9))))
Or using a list comprehension if you prefer:
[x for r in range(2, 9) for x in it.combinations(range(8), r)]
This produces the following output:
[(0, 1),
(0, 2),
(0, 3),
(0, 4),
(0, 5),
(0, 6),
(0, 7),
(1, 2),
(1, 3),
(1, 4),
(1, 5),
(1, 6),
(1, 7),
(2, 3),
(2, 4),
(2, 5),
(2, 6),
(2, 7),
(3, 4),
(3, 5),
(3, 6),
(3, 7),
(4, 5),
(4, 6),
(4, 7),
(5, 6),
(5, 7),
(6, 7),
(0, 1, 2),
(0, 1, 3),
(0, 1, 4),
(0, 1, 5),
(0, 1, 6),
(0, 1, 7),
(0, 2, 3),
(0, 2, 4),
(0, 2, 5),
(0, 2, 6),
(0, 2, 7),
(0, 3, 4),
(0, 3, 5),
(0, 3, 6),
(0, 3, 7),
(0, 4, 5),
(0, 4, 6),
(0, 4, 7),
(0, 5, 6),
(0, 5, 7),
(0, 6, 7),
(1, 2, 3),
(1, 2, 4),
(1, 2, 5),
(1, 2, 6),
(1, 2, 7),
(1, 3, 4),
(1, 3, 5),
(1, 3, 6),
(1, 3, 7),
(1, 4, 5),
(1, 4, 6),
(1, 4, 7),
(1, 5, 6),
(1, 5, 7),
(1, 6, 7),
(2, 3, 4),
(2, 3, 5),
(2, 3, 6),
(2, 3, 7),
(2, 4, 5),
(2, 4, 6),
(2, 4, 7),
(2, 5, 6),
(2, 5, 7),
(2, 6, 7),
(3, 4, 5),
(3, 4, 6),
(3, 4, 7),
(3, 5, 6),
(3, 5, 7),
(3, 6, 7),
(4, 5, 6),
(4, 5, 7),
(4, 6, 7),
(5, 6, 7),
(0, 1, 2, 3),
(0, 1, 2, 4),
(0, 1, 2, 5),
(0, 1, 2, 6),
(0, 1, 2, 7),
(0, 1, 3, 4),
(0, 1, 3, 5),
(0, 1, 3, 6),
(0, 1, 3, 7),
(0, 1, 4, 5),
(0, 1, 4, 6),
(0, 1, 4, 7),
(0, 1, 5, 6),
(0, 1, 5, 7),
(0, 1, 6, 7),
(0, 2, 3, 4),
(0, 2, 3, 5),
(0, 2, 3, 6),
(0, 2, 3, 7),
(0, 2, 4, 5),
(0, 2, 4, 6),
(0, 2, 4, 7),
(0, 2, 5, 6),
(0, 2, 5, 7),
(0, 2, 6, 7),
(0, 3, 4, 5),
(0, 3, 4, 6),
(0, 3, 4, 7),
(0, 3, 5, 6),
(0, 3, 5, 7),
(0, 3, 6, 7),
(0, 4, 5, 6),
(0, 4, 5, 7),
(0, 4, 6, 7),
(0, 5, 6, 7),
(1, 2, 3, 4),
(1, 2, 3, 5),
(1, 2, 3, 6),
(1, 2, 3, 7),
(1, 2, 4, 5),
(1, 2, 4, 6),
(1, 2, 4, 7),
(1, 2, 5, 6),
(1, 2, 5, 7),
(1, 2, 6, 7),
(1, 3, 4, 5),
(1, 3, 4, 6),
(1, 3, 4, 7),
(1, 3, 5, 6),
(1, 3, 5, 7),
(1, 3, 6, 7),
(1, 4, 5, 6),
(1, 4, 5, 7),
(1, 4, 6, 7),
(1, 5, 6, 7),
(2, 3, 4, 5),
(2, 3, 4, 6),
(2, 3, 4, 7),
(2, 3, 5, 6),
(2, 3, 5, 7),
(2, 3, 6, 7),
(2, 4, 5, 6),
(2, 4, 5, 7),
(2, 4, 6, 7),
(2, 5, 6, 7),
(3, 4, 5, 6),
(3, 4, 5, 7),
(3, 4, 6, 7),
(3, 5, 6, 7),
(4, 5, 6, 7),
(0, 1, 2, 3, 4),
(0, 1, 2, 3, 5),
(0, 1, 2, 3, 6),
(0, 1, 2, 3, 7),
(0, 1, 2, 4, 5),
(0, 1, 2, 4, 6),
(0, 1, 2, 4, 7),
(0, 1, 2, 5, 6),
(0, 1, 2, 5, 7),
(0, 1, 2, 6, 7),
(0, 1, 3, 4, 5),
(0, 1, 3, 4, 6),
(0, 1, 3, 4, 7),
(0, 1, 3, 5, 6),
(0, 1, 3, 5, 7),
(0, 1, 3, 6, 7),
(0, 1, 4, 5, 6),
(0, 1, 4, 5, 7),
(0, 1, 4, 6, 7),
(0, 1, 5, 6, 7),
(0, 2, 3, 4, 5),
(0, 2, 3, 4, 6),
(0, 2, 3, 4, 7),
(0, 2, 3, 5, 6),
(0, 2, 3, 5, 7),
(0, 2, 3, 6, 7),
(0, 2, 4, 5, 6),
(0, 2, 4, 5, 7),
(0, 2, 4, 6, 7),
(0, 2, 5, 6, 7),
(0, 3, 4, 5, 6),
(0, 3, 4, 5, 7),
(0, 3, 4, 6, 7),
(0, 3, 5, 6, 7),
(0, 4, 5, 6, 7),
(1, 2, 3, 4, 5),
(1, 2, 3, 4, 6),
(1, 2, 3, 4, 7),
(1, 2, 3, 5, 6),
(1, 2, 3, 5, 7),
(1, 2, 3, 6, 7),
(1, 2, 4, 5, 6),
(1, 2, 4, 5, 7),
(1, 2, 4, 6, 7),
(1, 2, 5, 6, 7),
(1, 3, 4, 5, 6),
(1, 3, 4, 5, 7),
(1, 3, 4, 6, 7),
(1, 3, 5, 6, 7),
(1, 4, 5, 6, 7),
(2, 3, 4, 5, 6),
(2, 3, 4, 5, 7),
(2, 3, 4, 6, 7),
(2, 3, 5, 6, 7),
(2, 4, 5, 6, 7),
(3, 4, 5, 6, 7),
(0, 1, 2, 3, 4, 5),
(0, 1, 2, 3, 4, 6),
(0, 1, 2, 3, 4, 7),
(0, 1, 2, 3, 5, 6),
(0, 1, 2, 3, 5, 7),
(0, 1, 2, 3, 6, 7),
(0, 1, 2, 4, 5, 6),
(0, 1, 2, 4, 5, 7),
(0, 1, 2, 4, 6, 7),
(0, 1, 2, 5, 6, 7),
(0, 1, 3, 4, 5, 6),
(0, 1, 3, 4, 5, 7),
(0, 1, 3, 4, 6, 7),
(0, 1, 3, 5, 6, 7),
(0, 1, 4, 5, 6, 7),
(0, 2, 3, 4, 5, 6),
(0, 2, 3, 4, 5, 7),
(0, 2, 3, 4, 6, 7),
(0, 2, 3, 5, 6, 7),
(0, 2, 4, 5, 6, 7),
(0, 3, 4, 5, 6, 7),
(1, 2, 3, 4, 5, 6),
(1, 2, 3, 4, 5, 7),
(1, 2, 3, 4, 6, 7),
(1, 2, 3, 5, 6, 7),
(1, 2, 4, 5, 6, 7),
(1, 3, 4, 5, 6, 7),
(2, 3, 4, 5, 6, 7),
(0, 1, 2, 3, 4, 5, 6),
(0, 1, 2, 3, 4, 5, 7),
(0, 1, 2, 3, 4, 6, 7),
(0, 1, 2, 3, 5, 6, 7),
(0, 1, 2, 4, 5, 6, 7),
(0, 1, 3, 4, 5, 6, 7),
(0, 2, 3, 4, 5, 6, 7),
(1, 2, 3, 4, 5, 6, 7),
(0, 1, 2, 3, 4, 5, 6, 7)]

Creating specific permutations Python

I have values for a 2-dimensional list:
# 4 x 4, 2-dimensional list
values = [[4, 7, 8],
[1, 3, 4],
[7, 5, 6],
[2, 9, 1]]
I want to create tuples containing all possible permutations of these values (Cartesian product) for each list.
# example for the list at index 0 of values
args0 = [(4, 7, 8), (7, 4, 8), (4, 8, 7), (8, 4, 7), (7, 8, 4), (8, 7, 4)]
Is there an easy way to go about this? I have tried itertools but cannot get it to work with "specific values".
What you want is the permutations of each element in the list, so just map itertools.permutations:
import itertools
values = [[4, 7, 8],
[1, 3, 4],
[7, 5, 6],
[2, 9, 1]]
perms = map(itertools.permutations, values)
for v in perms:
print(list(v))
Result:
[(4, 7, 8), (4, 8, 7), (7, 4, 8), (7, 8, 4), (8, 4, 7), (8, 7, 4)]
[(1, 3, 4), (1, 4, 3), (3, 1, 4), (3, 4, 1), (4, 1, 3), (4, 3, 1)]
[(7, 5, 6), (7, 6, 5), (5, 7, 6), (5, 6, 7), (6, 7, 5), (6, 5, 7)]
[(2, 9, 1), (2, 1, 9), (9, 2, 1), (9, 1, 2), (1, 2, 9), (1, 9, 2)]
Here you have a live example

Python - List Comprehension of List of Lists [duplicate]

This question already has answers here:
how to get all possible combination of items from 2-dimensional list in python?
(3 answers)
Closed 9 years ago.
I have a list of lists, and would like to generate a list of lists consisting of one element from each list.
For example, given the lists [[1, 2], [3, 4], [5, 6], [7, 8], I would execute the following code [(i, j, k, h) for i in [1, 2] for j in [3, 4] for k in [5, 6] for h in [7, 8]] and gets as output
[(1, 3, 5, 7), (1, 3, 5, 8), (1, 3, 6, 7), (1, 3, 6, 8), (1, 4, 5, 7), (1, 4, 5, 8), (1, 4, 6, 7), (1, 4, 6, 8), (2, 3, 5, 7), (2, 3, 5, 8), (2, 3, 6, 7), (2, 3, 6, 8), (2, 4, 5, 7), (2, 4, 5, 8), (2, 4, 6, 7), (2, 4, 6, 8)]
This code does not adapt for list of lists with different number of sub-lists. Is there a way to use nested list comprehensions to achieve the desired result? (My sub-lists are not always of the same length).
Use itertools.product, and unpack the list when pass as argument:
In [40]: from itertools import product
In [41]: list(product(*[[1, 2], [3, 4], [5, 6], [7, 8]]))
Out[41]:
[(1, 3, 5, 7),
(1, 3, 5, 8),
(1, 3, 6, 7),
(1, 3, 6, 8),
(1, 4, 5, 7),
(1, 4, 5, 8),
(1, 4, 6, 7),
(1, 4, 6, 8),
(2, 3, 5, 7),
(2, 3, 5, 8),
(2, 3, 6, 7),
(2, 3, 6, 8),
(2, 4, 5, 7),
(2, 4, 5, 8),
(2, 4, 6, 7),
(2, 4, 6, 8)]

Categories

Resources