I have a written the code here but it is taking much time. I need to optimize it more. The k here varies, it can be 2 or 3 or 4, depends on the user. Please help me out here.
from itertools import combinations
def get_all_combinations(input_list, k):
for item in combinations(input_list, k):
yield list(set(list(item)))
input_list = [1, 2, 1, 2, 3]
k = 3
lst = []
for i in range(1, k + 1):
for item in get_all_combinations(input_list, i):
if len(item) > i - 1:
lst.append(item)
print(len(lst))
>>17
#[[1], [2], [1], [2], [3], [1, 2], [1, 2], [1, 3], [1, 2], [2, 3], [1, 2], [1, 3], [2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
Try this one:
>>> input_list = [1, 2, 1, 2, 3]
>>> k = 3
>>> [list(set(el)) for i in range(1, k+1) for el in itertools.combinations(input_list, i) if len(set(el))>i-1]
[[1], [2], [1], [2], [3], [1, 2], [1, 2], [1, 3], [1, 2], [2, 3], [1, 2], [1, 3], [2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
With the following version your processing will go nearly twice as fast:
from itertools import combinations
def get_all_combinations(input_list, k):
for i in range(1, k + 1):
for item in combinations(input_list, i):
s = set(item)
if len(s) >= i:
yield list(s)
input_list = [1, 2, 1, 2, 3]
k = 3
lst = list(get_all_combinations(input_list, k))
print(lst)
The output remains the same:
[[1], [2], [1], [2], [3], [1, 2], [1, 2], [1, 3], [1, 2], [2, 3], [1, 2], [1, 3], [2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3]]
Test this:
from itertools import combinations
def get_all_combinations(input_list,k):
l = []
for item in combinations(input_list, k):
l.append( list(set(list(item))))
return l
input_list = [1, 2, 1, 2, 3]
k = 3
lst = []
for i in range(1,k+1):
gac = []
gac = get_all_combinations(input_list, i)
for item in gac:
if len(item) > i-1:
lst.append(item)
print(len(lst))
base on link
If this is meant to be homework, your instructor is probably looking for this.
lst = [list(c) for i in range(k) for c in combinations(input_list, i+1) if len(set(c)) > i]
Related
This is what i have-
def merge_list(mylist)
list1 = []
one_len = len(mylist)
two_len = len(mylist[0][0])
for index in range(two_len):
combine_list = []
for index2 in range(one_len):
combine_list.extend([a[index] for a in mylist[
index2]])
list1.append(combine_list)
return list1
But i have a problem with the output-
for example:
input-
mylist=[[[1, 1, 1], [1, 1, 1], [1, 1, 1], [1, 1, 1]], [[2, 2, 2], [2, 2, 2], [2, 2, 2], [2, 2, 2]], [[3, 3, 3], [3, 3, 3], [3, 3, 3], [3, 3, 3]]]
in short-
[[[1]*3]*4, [[2]*3]*4, [[3]*3]*4]
the output is -
[[[1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3], [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3], [1, 1, 1, 1, 2, 2, 2, 2, 3, 3, 3, 3]]]
and not -
[[[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]], [[1, 2, 3], [1, 2, 3], [1, 2, 3]]]
in short-
[[[1, 2, 3]]*3]*4
I would be happy to solve the problem and advise how to shorten the code.
In order to fix your code, you just need to update the return statement like this:
return [list1]
Though there is still a hidden problem when your inner lists lengths are longer than one element. Check your outputs with sample inputs like [[[2,1], [3,1]]].
One further - more compact - solution may be obtained by concatenating the inner lists within a cycle, then recreate the number of dimensions you need, moving the complexity from O(n^2) to O(n).
mylist = [[[2,1]],[[3,1]]]
def merge_list(mylist):
l_out = []
for l in mylist:
l_out += l[0]
return [[l_out]]
EDIT: In case of more complex inputs, you can extract first all elements and eventually fix the dimensions. This will still bring O(n^2) complexity though:
def merge_list(lst):
elements = [[] for _ in range(len(mylist[0]))]
for l1 in mylist:
for idx, l2 in enumerate(l1):
elements[idx] += l2
return [elements]
merge_list(mylist)
Input:
[[[1], [1]], [[2], [2]], [[3], [3]]]
Output:
[[[1, 2, 3], [1, 2, 3]]]
I am trying to tranform
[[1, 2, 3], [1, 2]]
into
[[1, 2, 3], [3, 2, 1], [2, 3, 1], [1, 2], [2, 1]]
But instead of the correct output, I am getting this:
[[1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2], [1, 2]]
Here is my code
def listReorder(list1):
List2 = []
for list in list1:
listTemp = list
for item in list:
List2.append(listTemp)
t=listTemp.pop()
listTemp.insert(0, t)
return List2
List = [[1, 2, 3], [1, 2]]
listReorder(List)
In your for loop, you are adding the same list again and again, but instead, you should make a copy of the list in the iteration.
def listReorder(list1):
List2 = []
for list in list1:
listTemp = list
for item in list:
List2.append([x for x in listTemp])
t=listTemp.pop()
listTemp.insert(0, t)
return List2
List = [[1, 2, 3], [1, 2]]
listReorder(List)
Output:
[[1, 2, 3], [3, 1, 2], [2, 3, 1], [1, 2], [2, 1]]
Is there a simple algorithm (most likely recursive algorithm) that finds all combinations of a list and of all sizes (from combo of size 1 to combo of size length of a list)?
For example: if I have a list = [1, 2, 3, 4], the combinations of all sizes I should get are:
[1], [2], [3], [4], [1,2], [1,3], [1,4], [2,3], [2,4], [3,4], [1,2,3], [1,2,4], [1,3,4], [2,3,4], [1,2,3,4].
So I only know a recursive algorithm I found online that finds a combination of size n but not for all sizes from 1 to length of the list. Order doesn't matter in combinations.
Here is the code I found online:
def n_length_combo(lst, n):
if n == 0:
return [[]]
l =[]
for i in range(0, len(lst)):
m = lst[i]
remLst = lst[i + 1:]
for p in n_length_combo(remLst, n-1):
l.append([m]+p)
return l
This is good only for combinations of size n. But I want to find combinations for all sizes from 1 to the length of a list.
Any ideas here?
Call it with the length of the list using len function:
n_length_combo(lst, len(lst))
Even better, if you don't want to always pass the second argument you can assign a default value:
def n_length_combo(lst, n=len(lst)):
See below (using itertools)
from itertools import combinations
lst = [1, 2, 3, 4]
final_lst = []
for x in lst[1:]:
final_lst.extend(combinations(lst, r=x))
print(final_lst)
output
[(1, 2), (1, 3), (1, 4), (2, 3), (2, 4), (3, 4), (1, 2, 3), (1, 2, 4), (1, 3, 4), (2, 3, 4), (1, 2, 3, 4)]
For every element of the list: you can either take that element, or not take it.
This gives us a recurrence formula:
combinations(l) = combinations(l[:-1]) + [add l[-1] to every element of combinations(l[:-1])
This gives us a recursive algorithm:
def combinations(l):
if not l:
return [[]]
else:
c = combinations(l[:-1])
return c + [r+[l[-1]] for r in c]
print(combinations(range(4)))
# [[], [0], [1], [0, 1], [2], [0, 2], [1, 2], [0, 1, 2], [3], [0, 3], [1, 3], [0, 1, 3], [2, 3], [0, 2, 3], [1, 2, 3], [0, 1, 2, 3]]
Of course there is no need for recursion:
def combinations(l):
c = [[]]
for x in l:
c = c + [r+[x] for r in c]
return c
print(combinations(range(4)))
# [[], [0], [1], [0, 1], [2], [0, 2], [1, 2], [0, 1, 2], [3], [0, 3], [1, 3], [0, 1, 3], [2, 3], [0, 2, 3], [1, 2, 3], [0, 1, 2, 3]]
Use the function you have, but collect the results for all the combo lengths you need:
L = [1,2,3,4]
result = []
for n in range(1,len(L) + 1):
result.extend(n_length_combo(L,n))
print(result)
Output:
[[1], [2], [3], [4], [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4], [1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]]
Here's a complete recursive generator:
def all_combo(lst):
def n_combo(lst,n):
if n == 1:
yield from ([n] for n in lst)
for i,item in enumerate(lst):
for combo in n_combo(lst[i+1:],n-1):
yield [item] + combo
for n in range(1,len(lst)+1):
yield from n_combo(lst,n)
L = list(all_combo([1,2,3,4]))
print(L)
Output:
[[1], [2], [3], [4], [1, 2], [1, 3], [1, 4], [2, 3], [2, 4], [3, 4], [1, 2, 3], [1, 2, 4], [1, 3, 4], [2, 3, 4], [1, 2, 3, 4]]
Hi I'm trying to make a list of all possible cohesive combinations of another list, so from [0, 1, 2, 3] I'd like to get [[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]. So far I've got this:
def expandArray(arr):
result = []
for x in range(0, len(arr)):
subArray = [arr[x]]
result.append(subArray)
for y in range(x + 1, len(arr)):
subArray.append(arr[y])
result.append(subArray)
return(result)
But this returns: [[0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [0, 1, 2, 3], [1, 2, 3], [1, 2, 3], [1, 2, 3], [2, 3], [2, 3], [3]].
What am I doing wrong ?
subArray is a list that you modify in your for loop. When you append to it, you do not create a new list, but you modify it, and then put it in the list again, so will in the end get a result with several copies of the same list. Compare this code:
a = []
b = [5]
a.append(b)
b.append(1)
a.append(b)
print(a)
would output:
[[5, 1], [5, 1]]
Here is a way to have your desired output using list slicing:
def get_combs(iterable):
for k, _ in enumerate(iterable):
elm = k
while elm <= len(iterable):
data = iterable[k:elm]
elm += 1
if data:
yield data
combs = list(get_combs([0, 1, 2, 3]))
print(combs)
Output:
[[0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]
I have written python code to permute a list of numbers.
class Solution:
def __init__(self):
self.permutations = []
def permute_helper(self, nums, chosen):
if nums == []:
print chosen
self.permutations.append(chosen)
else:
for num in nums:
#choose
chosen.append(num)
temp = nums[:]
temp.remove(num)
#explore
self.permute_helper(temp, chosen)
#un-choose
chosen.remove(num)
def permute(self, nums):
"""
:type nums: List[int]
:rtype: List[List[int]]
"""
self.permute_helper(nums, [])
return self.permutations
s = Solution()
input = [1,2,3]
print s.permute(input)
It returns:
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
[[], [], [], [], [], []]
I want all the permutations to appear in the returned list like this
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
I think it has something to do with scoping but I have no idea what I've done wrong to make the list returning nothing.
When you append chosen to self.permutations, any change you make to chosen after the fact will also affect each element of self.permutations. By calling chosen.remove later, you remove numbers from self.permutations as well. Consider this simpler example:
>>> a = [1,2,3]
>>> b = []
>>> b.append(a)
>>> b.append(a)
>>> b.append(a)
>>> a.remove(2)
>>> b
[[1, 3], [1, 3], [1, 3]]
You could append a shallow copy of chosen to self.permutations instead, in which case changes made to chosen afterwards will have no effect on self.permutations.
if nums == []:
print chosen
self.permutations.append(chosen[:])
Result:
[1, 2, 3]
[1, 3, 2]
[2, 1, 3]
[2, 3, 1]
[3, 1, 2]
[3, 2, 1]
[[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]