Generating combinations follow by each element - python

I have a list of chars chrs = ['A','B','C','D']. How can I generate the outputs like this ['A','AB','ABC','ABCD','B','BC','BCD','C','CD','D'] in python?
Thank you so much!

Try this
s = ''.join(chrs)
res = [s[i: j+1] for i in range(len(s)) for j in range(i, len(s))]
print(res)
Output:
['A', 'AB', 'ABC', 'ABCD', 'B', 'BC', 'BCD', 'C', 'CD', 'D']

A one liner is to use function powerset() from package more_itertools.
Like the following:
from more_itertools import powerset
l = ['A','B','C','D']
list(powerset(l))
# [(), ('A',), ('B',), ('C',), ('D',), ('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D'), ('A', 'B', 'C'), ('A', 'B', 'D'), ('A', 'C', 'D'), ('B', 'C', 'D'), ('A', 'B', 'C', 'D')]
Then you can join it to strings, and sort to get the desired output.
ll = ["".join(x) for x in list(powerset(l))]
sorted(ll)
# ['', 'A', 'AB', 'ABC', 'ABCD', 'ABD', 'AC', 'ACD', 'AD', 'B', 'BC', 'BCD', 'BD', 'C', 'CD', 'D']
You can also easily get read from the empty string by ll[1:]

chrs = ['A','B','C','D']
all_combinations = []
for current_start_index in range(len(chrs)):
for current_combinations_lengh in range(current_start_index, len(chrs)):
all_combinations.append(''.join(list(chrs[current_start_index:current_combinations_lengh+1])))
# Sort, if neccesary
# all_combinations.sort()
# ['A', 'AB', 'ABC', 'ABCD', 'B', 'BC', 'BCD', 'C', 'CD', 'D']
print(all_combinations)

A simple solution without using any package or module and with basic idea:
chrs=['a','b','c','d']
chrs=''.join(chrs)
a2=[]
i=0
j=1
while(i<len(a) and j<len(a)):
a2.append(a[i:j+1])
j+=1
if j>=len(a):
i+=1
j+=i
a2.append(chrs[-1])
print(a2)

Related

How can I rearrange a set of values into new pattern on python and print results

so I will do my best to explain what I'm looking for,
at the moment I have a 100 item list that I want to repetitively shuffle using a set pattern to first check if the pattern will eventually bring me back to where I began
and 2 to print the result of each loop to a text file.
so using a 3 item list as my example
[a,b,c]
and the shuffle pattern [3 1 2]
where the 3rd item becomes the first.
the first item becomes the second
and the second item becomes the 3rd
on a loop would generate the following patterns
[a,b,c]
[3,1,2]
[c,a,b]
[b,c,a]
[a,b,c]
but I have a list at the moment of 100 items that I need to find every single arrangement for a few different patterns I would like to test out.
does anyone know of a way to do this in python please.
You can define function and call this function multi times like below:
>>> def func(lst, ptr):
... return [lst[idx-1] for idx in ptr]
>>> lst = ['a','b','c']
>>> ptr = [3,1,2]
>>> for _ in range(5):
... lst = func(lst, ptr)
... print(lst)
['c', 'a', 'b']
['b', 'c', 'a']
['a', 'b', 'c']
['c', 'a', 'b']
['b', 'c', 'a']
You could use numpy advanced integer indexing if your list contains a numeric type:
import numpy as np
original_list=[1,2,3]
numpy_array = np.array(original_list)
pattern = [2,1,0]
print(numpy_array[pattern])
>>> array([3, 2, 1])
def rearrange(pattern : list,L:list):
new_list = []
for i in pattern :
new_list.append(L[i-1])
return new_list
print(rearrange([3,1,2],['a','b','c']))
output :
['c', 'a', 'b']
Itertools could be what you need.
import itertools
p = itertools.permutations(['a','b','c', 'd'])
list(p)
Output:
[('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')]
​

How to simplify this code about iteration combination in python

So i have this code below that i created. This code will list every possible combination of a certain value, in this example is "a" "b" "c" "d". If i use this code, the result would be like this: a, aa, ab, ac, ad, aaa, aab, aac, aad, aba, abb, abc, etc. How to simplify this for loop code, so that i can input more values without createing more for loop?
n = "abcd"
for c in n:
print(c)
for c1 in n:
print(c+c1)
for c2 in n:
print(c+c1+c2)
for c3 in n:
print(c+c1+c2+c3)
https://docs.python.org/2/library/itertools.html
Itertools permutations and combinations is what you're after.
itertools.permutations([1, 2, 3])
from itertools import combinations
n = "abcd"
print ([''.join(l) for i in range(len(n)) for l in combinations(n, i+1)])
output:
['a', 'b', 'c', 'd', 'ab', 'ac', 'ad', 'bc', 'bd', 'cd', 'abc', 'abd', 'acd', 'bcd', 'abcd']
edit:
from itertools import combinations_with_replacement
n = "abcd"
comb = []
for i in range(1, len(n)+1):
comb += list(combinations_with_replacement(n, i))
print([''.join(c) for c in comb])
output:
['a', 'b', 'c', 'd', 'aa', 'ab', 'ac', 'ad', 'bb', 'bc', 'bd', 'cc', 'cd', 'dd', 'aaa', 'aab', 'aac', 'aad', 'abb', 'abc', 'abd', 'acc', 'acd', 'add', 'bbb', 'bbc', 'bbd', 'bcc', 'bcd', 'bdd', 'ccc', 'ccd', 'cdd', 'ddd', 'aaaa', 'aaab', 'aaac', 'aaad', 'aabb', 'aabc', 'aabd', 'aacc', 'aacd', 'aadd', 'abbb', 'abbc', 'abbd', 'abcc', 'abcd', 'abdd', 'accc', 'accd', 'acdd', 'addd', 'bbbb', 'bbbc', 'bbbd', 'bbcc', 'bbcd', 'bbdd', 'bccc', 'bccd', 'bcdd', 'bddd', 'cccc', 'cccd', 'ccdd', 'cddd', 'dddd']
To get the same result of 340 elements you can use itertools.product:
product(n, repeat=1)
product(n, repeat=2)
...
product(n, repeat=4)
To print the result you can use the following loop:
from itertools import product
n = "abcd"
for i in range(1, 5):
for prod in product(n, repeat=i):
print(''.join(prod))
To get an extra level you can easily increase the 5 in range. Note: the order of printing is slightly different than in your code.
You can use itertools module to solve your problem. You need combinations_with_replacement function with all possible lengths:
import itertools as it
n = "abcd"
result = []
for l in range(len(n)):
result += list(it.combinations_with_replacement(n, l+1))
print(result)
[('a',), ('b',), ('c',), ('d',), ('a', 'a'), ('a', 'b'), ('a', 'c'), ('a', 'd'), ('b', 'b'), ('b', 'c'), ('b', 'd'), ('c', 'c'), ('c', 'd'), ('d', 'd'), ('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')]

What is the difference between these two List in Python?

I have two Lists in my program list1 and list2 which looks like the following:
list1 = ['ABC',
'ABD',
'ABE',
'ABF',
'ABG',
'ABH',
'ABI',
...]
list2 = [('A', 'B', 'C'),
('A', 'B', 'D'),
('A', 'B', 'E'),
('A', 'B', 'F'),
('A', 'B', 'G'),
('A', 'B', 'I'),
...]
Both the Lists are 2D because they return the same result on the same operation.
list1[0][1] returns 'B'
list2[0][1] also returns 'B'
What is the difference between list1 and list2 if they return the same result? How do I convert list2 in the format of list1?
Thank you.
The first list is list of strings and second list is list of tuples containing strings.
To convert list2 to list1 you can use:
list2 = [('A', 'B', 'C'),
('A', 'B', 'D'),
('A', 'B', 'E'),
('A', 'B', 'F'),
('A', 'B', 'G'),
('A', 'B', 'I'),]
new_list = [''.join(v) for v in list2]
print(new_list)
Output:
['ABC', 'ABD', 'ABE', 'ABF', 'ABG', 'ABI']

Python create many-to-many relationships from a list

I have a list, say terms = ['A', 'B', 'C', 'D']
Which is the best way to create a list-of-lists or list-of-tuples of many-to-many relationships like this;
[['A','B'],['A','C'],['A','D'],['B','C'],['B','D'],['C','D']]
Using itertools.combinations():
from itertools import combinations
list(combinations(terms, r=2))
Demo:
>>> from itertools import combinations
>>> terms = ['A', 'B', 'C', 'D']
>>> list(combinations(terms, r=2))
[('A', 'B'), ('A', 'C'), ('A', 'D'), ('B', 'C'), ('B', 'D'), ('C', 'D')]
These are tuples, not lists, but that's easily remedied if that is a problem:
>>> map(list, combinations(terms, r=2))
[['A', 'B'], ['A', 'C'], ['A', 'D'], ['B', 'C'], ['B', 'D'], ['C', 'D']]

All strings with list of characters?

I'm making a specialized utility similar to John the Ripper, and I'd like to use a loop that returns all strings up to x characters that can be formed from the string. For example, if the "seed" string is abcd, it should return:
a
b
c
d
aa
ab
ac
and so on. If the character limit is 10, it would generate aaaaaaaaaa, abcddcbaaa, and so on. Is there a simple for loop to do this, or is it more complicated than that?
I'll self-plagiarize from this answer and add a maximum length:
from itertools import product
def multiletters(seq, max_length):
for n in range(1, max_length+1):
for s in product(seq, repeat=n):
yield ''.join(s)
which gives
>>> list(multiletters("abc", 2))
['a', 'b', 'c', 'aa', 'ab', 'ac', 'ba', 'bb', 'bc', 'ca', 'cb', 'cc']
>>> list(multiletters("abcd", 4))[:8]
['a', 'b', 'c', 'd', 'aa', 'ab', 'ac', 'ad']
and so on.
def all_strings(alphabet, length_limit=None):
n_letters = len(alphabet)
length = 0
n_strings = 1
buf = []
while True:
for i in xrange(0, n_strings):
k = i
for j in xrange(length - 1, -1, -1):
buf[j] = alphabet[k % n_letters]
k /= n_letters
yield ''.join(buf)
length += 1
if length == length_limit:
break
n_strings *= n_letters
buf.append(alphabet[0])
for s in all_strings('abcd', length_limit=4):
print s
As pointed out in the comment's use itertools.premutations or even better take a look #DSM's answer, as this one misses the doubles:
In [194]: from itertools import chain, permutations
In [195]: s = 'abcd'
In [196]: map(''.join,chain.from_iterable(permutations(s,x)
for x in range(1,len(s)+1)))
Out[196]:
['a',
'b',
'c',
'd',
'ab',
'ac',
'ad',
'ba',
'bc',
'bd',
...
'dbca',
'dcab',
'dcba']
Anyway, here's a version of #DSM's answer that returns a list:
from itertools import product
def ms(seq, max_length):
return [''.join(s) for n in range(1, max_length+1)
for s in product(seq,repeat=n)]
Use itertools.permuataions.
for i in range(2,4):
tuples = itertools.permutations('abca' , i)
print( list(tuples))
The example code sequence generates:
[('a', 'b'), ('a', 'c'), ('a', 'a'), ('b', 'a'), ('b', 'c'), ('b', 'a'), ('c', 'a'), ('c', 'b'), ('c', 'a'), ('a', 'a'), ('a', 'b'), ('a', 'c')]
[('a', 'b', 'c'), ('a', 'b', 'a'), ('a', 'c', 'b'), ('a', 'c', 'a'), ('a', 'a', 'b'), ('a', 'a', 'c'), ('b', 'a', 'c'), ('b', 'a', 'a'), ('b', 'c', 'a'), ('b', 'c', 'a'), ('b', 'a', 'a'), ('b', 'a', 'c'), ('c', 'a', 'b'), ('c', 'a', 'a'), ('c', 'b', 'a'), ('c', 'b', 'a'), ('c', 'a', 'a'), ('c', 'a', 'b'), ('a', 'a', 'b'), ('a', 'a', 'c'), ('a', 'b', 'a'), ('a', 'b', 'c'), ('a', 'c', 'a'), ('a', 'c', 'b')]

Categories