Using itertools product but needing combination behavior - python

I am trying to generate a list of possible strings of characters from input, accounting for wildcards "?" and "*". The ordering of list items should not matter, meaning if ABC already exists in the list, then I do not want to add ACB, or any other ordering (processing speed issue). The code I am using is below:
import itertools
from itertools import permutations
#####################################################
def getWordsFromTiles(tiles, word):
#####################################################
return all(word.count(i) <= tiles.count(i) for i in word)
#####################################################
Main
#####################################################
chars = A?*
wilds = [
('A','B','C','D','E','F','G','H','I','J','K',
'L','M','N','O','P','Q','R','S','T','U','V',
'W','X','Y','Z')
if char == "?" or char == "*" else (char) for char in chars]
for p in itertools.product(*wilds):
x = ''.join(p)
hits.extend([word for word in data if getWordsFromTiles(x.upper(), word) and word not in hits])
This generates a list like the following:
A,A,A
A,A,B
A,A,C
.....
A,B,A
I actually do not care about the order of these list, so I would like to not have A,B,A when I have already generated "A,A,B. Any ideas how to implement this?

actually do not care about the order of these list, so I would like to not have A,B,A when I have already generated "A,A,B".
Is this what you are looking for?
from itertools import combinations_with_replacement
s = ['A','B','C','D']
list(combinations_with_replacement(s,3))
[('A', 'A', 'A'),
('A', 'A', 'B'),
('A', 'A', 'C'),
('A', 'A', 'D'),
('A', 'B', 'B'),
('A', 'B', 'C'),
('A', 'B', 'D'),
('A', 'C', 'C'),
('A', 'C', 'D'),
('A', 'D', 'D'),
('B', 'B', 'B'),
('B', 'B', 'C'),
('B', 'B', 'D'),
('B', 'C', 'C'),
('B', 'C', 'D'),
('B', 'D', 'D'),
('C', 'C', 'C'),
('C', 'C', 'D'),
('C', 'D', 'D'),
('D', 'D', 'D')]

Related

Python - How to get all Combinations of names from a list: TypeError: 'list' object is not callable

I get an error when trying to print the permutation/combination of a user generated list of names.
I tried a couple of things from itertools, but can't get either permutations or combinations to work. Ran into some other errors along the way regarding concatenating strings, but currently getting a: TypeError: 'list' object not callable.
I know I'm making a simple mistake, but can't sort it out. Please help!
from itertools import combinations
name_list = []
for i in range(0,20):
name = input('Add up to 20 names.\nWhen finished, enter "Done" to see all first and middle name combinations.\nName: ')
name_list.append(name)
if name != 'Done':
print(name_list)
else:
name_list.remove('Done')
print(name_list(combinations))
I expect:
1) the user adds a name to list
2) the list prints showing user contents of list
3) when finished the user inputs "Done":
a) 'Done' is removed from the list
b) all the combinations of the remaining items on the list printed
Permutations and combinations are two different beasts. Look:
>>> from itertools import permutations,combinations
>>> from pprint import pprint
>>> l = ['a', 'b', 'c', 'd']
>>> pprint(list(combinations(l, 2)))
[('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'c'), ('b', 'd'), ('c', 'd')]
>>> pprint(list(permutations(l)))
[('a', 'b', 'c', 'd'),
('a', 'b', 'd', 'c'),
('a', 'c', 'b', 'd'),
('a', 'c', 'd', 'b'),
('a', 'd', 'b', 'c'),
('a', 'd', 'c', 'b'),
('b', 'a', 'c', 'd'),
('b', 'a', 'd', 'c'),
('b', 'c', 'a', 'd'),
('b', 'c', 'd', 'a'),
('b', 'd', 'a', 'c'),
('b', 'd', 'c', 'a'),
('c', 'a', 'b', 'd'),
('c', 'a', 'd', 'b'),
('c', 'b', 'a', 'd'),
('c', 'b', 'd', 'a'),
('c', 'd', 'a', 'b'),
('c', 'd', 'b', 'a'),
('d', 'a', 'b', 'c'),
('d', 'a', 'c', 'b'),
('d', 'b', 'a', 'c'),
('d', 'b', 'c', 'a'),
('d', 'c', 'a', 'b'),
('d', 'c', 'b', 'a')]
>>>
for use combinations , you need to give the r as argument.this code give all combinations for all numbers(0 to length of list),
from itertools import combinations
name_list = []
for i in range(0,20):
name = raw_input('Add up to 20 names.\nWhen finished, enter "Done" to see all first and middle name combinations.\nName: ')
name_list.append(name)
if name != 'Done':
print(name_list)
else:
name_list.remove('Done')
break
for i in range(len(name_list) + 1):
print(list(combinations(name_list, i)))
print("\n")

how to do a in depth permutation of some given letters in python?

So i have been trying to permutate some letters in python using the permutation library but i saw that it only return the given letters so that no letters are a duplicate, if i have the letters a, b and c the permutation will be as following.
abc
acb
bac
bca
cab
cba
Now i have been trying for a way for a sort of more in depth way i guess so i have it like.
aaa
aab
aac
aba
abc
abc
aca
Is there a proper way to do this in python?
It could be that i'm wrong but that's the way i saw it.
Edit after solve:
People who wondered what i tried, i used the permutation part of the itertools library:
>>>print([x for x in itertools.permutations('1234')])
>>>[('1', '2', '3', '4'), ('1', '2', '4', '3'), ('1', '3', '2', '4') ... ]
Perhaps you want something like itertools.product
from itertools import product
print(list(product('abc', repeat = 3)))
# [('a', 'a', 'a'), ('a', 'a', 'b'), ('a', 'a', 'c'), ('a', 'b', 'a'), ('a', 'b', 'b'), ('a', 'b', 'c'), ('a', 'c', 'a'), ('a', 'c', 'b'), ('a', 'c', 'c'), ('b', 'a', 'a'), ('b', 'a', 'b'), ('b', 'a', 'c'), ('b', 'b', 'a'), ('b', 'b', 'b'), ('b', 'b', 'c'), ('b', 'c', 'a'), ('b', 'c', 'b'), ('b', 'c', 'c'), ('c', 'a', 'a'), ('c', 'a', 'b'), ('c', 'a', 'c'), ('c', 'b', 'a'), ('c', 'b', 'b'), ('c', 'b', 'c'), ('c', 'c', 'a'), ('c', 'c', 'b'), ('c', 'c', 'c')]

All combinations of list wIthout itertools

I'm trying to make a recursive function that finds all the combinations of a python list.
I want to input ['a','b','c'] in my function and as the function runs I want the trace to look like this:
['a','b','c']
['['a','a'],['b','a'],['c','a']]
['['a','a','b'],['b','a','b'],['c','a','b']]
['['a','a','b','c'],['b','a','b','c'],['c','a','b','c']]
My recursive function looks like this:
def combo(lst,new_lst = []):
for item in lst:
new_lst.append([lst[0],item])
print([lst[0],item])
return combo(new_lst,lst[1:])
The right answer is that you should use itertools.combinations. But if for some reason you don't want to, and want to write a recursive function, you can use the following piece of code. It is an adaptation of the erlang way of generating combinations, so it may seem a bit weird at first:
def combinations(N, iterable):
if not N:
return [[]]
if not iterable:
return []
head = [iterable[0]]
tail = iterable[1:]
new_comb = [ head + list_ for list_ in combinations(N - 1, tail) ]
return new_comb + combinations(N, tail)
This a very elegant way of thinking of combinations of size N: you take the first element of an iterable (head) and combine it with smaller (N-1) combinations of the rest of the iterable (tail). Then you add same size (N) combinations of the tail to that. That's how you get all possible combinations.
If you need all combinations, of all lengths you would do:
for n in range(1, len(iterable) + 1):
print(combinations(n, iterable))
Seems that you want all the product of a list, you can use itertools.product within the following function to return a list of generators:
>>> from itertools import product
>>> def pro(li):
... return [product(l,repeat=i) for i in range(2,len(l)+1)]
...
>>> for i in pro(l):
... print list(i)
...
[('a', 'a'), ('a', 'b'), ('a', 'c'), ('b', 'a'), ('b', 'b'), ('b', 'c'), ('c', 'a'), ('c', 'b'), ('c', 'c')]
[('a', 'a', 'a'), ('a', 'a', 'b'), ('a', 'a', 'c'), ('a', 'b', 'a'), ('a', 'b', 'b'), ('a', 'b', 'c'), ('a', 'c', 'a'), ('a', 'c', 'b'), ('a', 'c', 'c'), ('b', 'a', 'a'), ('b', 'a', 'b'), ('b', 'a', 'c'), ('b', 'b', 'a'), ('b', 'b', 'b'), ('b', 'b', 'c'), ('b', 'c', 'a'), ('b', 'c', 'b'), ('b', 'c', 'c'), ('c', 'a', 'a'), ('c', 'a', 'b'), ('c', 'a', 'c'), ('c', 'b', 'a'), ('c', 'b', 'b'), ('c', 'b', 'c'), ('c', 'c', 'a'), ('c', 'c', 'b'), ('c', 'c', 'c')]

How to use itertools to compute all combinations with repeating elements? [duplicate]

This question already has an answer here:
Which itertools generator doesn't skip any combinations?
(1 answer)
Closed 8 years ago.
I have tried to use itertools to compute all combinations of a list ['a', 'b', 'c'] using combinations_with_replacement with repeating elements. The problem is in the fact that the indices seem to be used to distinguish the elements:
Return r length subsequences of elements from the input iterable allowing individual elements to be repeated more than once.
Combinations are emitted in lexicographic sort order. So, if the input
iterable is sorted, the combination tuples will be produced in sorted
order.
Elements are treated as unique based on their position, not on their
value. So if the input elements are unique, the generated combinations
will also be unique.
Sot this code snippet:
import itertools
for item in itertools.combinations_with_replacement(['a','b','c'], 3):
print (item)
results in this output:
('a', 'a', 'a')
('a', 'a', 'b')
('a', 'a', 'c')
('a', 'b', 'b')
('a', 'b', 'c')
('a', 'c', 'c')
('b', 'b', 'b')
('b', 'b', 'c')
('b', 'c', 'c')
('c', 'c', 'c')
And what I need is the combination set to contain elements like: ('a', 'b', 'a') which seem to be missing. How to compute the complete combination set?
It sounds like you want itertools.product:
>>> from itertools import product
>>> for item in product(['a', 'b', 'c'], repeat=3):
... print item
...
('a', 'a', 'a')
('a', 'a', 'b')
('a', 'a', 'c')
('a', 'b', 'a')
('a', 'b', 'b')
('a', 'b', 'c')
('a', 'c', 'a')
('a', 'c', 'b')
('a', 'c', 'c')
('b', 'a', 'a')
('b', 'a', 'b')
('b', 'a', 'c')
('b', 'b', 'a')
('b', 'b', 'b')
('b', 'b', 'c')
('b', 'c', 'a')
('b', 'c', 'b')
('b', 'c', 'c')
('c', 'a', 'a')
('c', 'a', 'b')
('c', 'a', 'c')
('c', 'b', 'a')
('c', 'b', 'b')
('c', 'b', 'c')
('c', 'c', 'a')
('c', 'c', 'b')
('c', 'c', 'c')
>>>
For such small sequences you could use no itertools at all:
abc = ("a", "b", "c")
print [(x, y, z) for x in abc for y in abc for z in abc]
# output:
[('a', 'a', 'a'),
('a', 'a', 'b'),
('a', 'a', 'c'),
('a', 'b', 'a'),
('a', 'b', 'b'),
('a', 'b', 'c'),
('a', 'c', 'a'),
('a', 'c', 'b'),
('a', 'c', 'c'),
('b', 'a', 'a'),
('b', 'a', 'b'),
('b', 'a', 'c'),
('b', 'b', 'a'),
('b', 'b', 'b'),
('b', 'b', 'c'),
('b', 'c', 'a'),
('b', 'c', 'b'),
('b', 'c', 'c'),
('c', 'a', 'a'),
('c', 'a', 'b'),
('c', 'a', 'c'),
('c', 'b', 'a'),
('c', 'b', 'b'),
('c', 'b', 'c'),
('c', 'c', 'a'),
('c', 'c', 'b'),
('c', 'c', 'c')]

Python fastest method to group pairs from a list of items

As a part of my project, I need to group characters as pairs (unique). I have more than 1000 of these characters in a list. What would be the fastest and optimized method to create unique pairs out of these list of characters. I am using itertools currently and my code seems to perform pretty badly.
My Code using itertools:
import itertools
characters = ['A', 'B', 'C', 'D', 'E']
relations = []
for character in range(len(characters) + 1):
for combination in itertools.combinations(characters, character):
if len(combination) == 2:
relations.append(combination)
print relations
Expected Output:
[('A', 'B'), ('A', 'C'), ('A', 'D'), ('A', 'E'), ('B', 'C'),
('B', 'D'), ('B', 'E'), ('C', 'D'), ('C', 'E'), ('D', 'E')]
All you need are combinations of length 2?
In [48]: characters = ['A', 'B', 'C', 'D', 'E']
In [50]: list(itertools.combinations(characters, 2))
Out[50]:
[('A', 'B'),
('A', 'C'),
('A', 'D'),
('A', 'E'),
('B', 'C'),
('B', 'D'),
('B', 'E'),
('C', 'D'),
('C', 'E'),
('D', 'E')]
You are also generating combinations of length 3 to len(characters) and throwing them all away.
characters = ['A', 'B', 'C', 'D', 'E']
relations = list(itertools.combinations(characters, 2))

Categories

Resources