get all the partitions of the set python with itertools - python

How to get all partitions of a set?
For example, I have array [1, 2, 3]. I need to get [[1], [2], [3]], [[1], [2, 3]], [[2], [1,3]], [[3], [1, 2]], [[1, 2, 3]].
Now, I wrote this code:
def neclusters(S, K):
for splits in itertools.combinations(range(len(S)), K):
yield np.split(S, 1 + np.array(splits))
But that code don't return [[2],[1,3]].
I could take all permutations of the original set and run this code on them. But can this be made easier?

I wrote this one for fun:
def partition(a_list):
yield [[x] for x in a_list]
for i in range(1, len(a_list) + 1):
_l = a_list[:]
yield [_l.pop(i-1), _l]
yield a_list
my_list = [1, 2, 3]
print list(partition(my_list))
#or
for p in partition(my_list):
print p

a = [1, 2, 3]
b = list()
for l in range(len(a)+1): b.append([c for c in combinations(a, l)])
print(b)
check this

Related

How to get all consecutive sequences of numbers from given set of numbers?

I will start the description of the problem with an example so that the question is clear.
List of numbers: [1,2,3,4]
How can I get each successive string: [[1],[1,2],[1,2,3],[1,2,3,4],[2],[2,3],[2,3,4],[3],[3,4],[4]]
I've been trying to solve this problem for a while and managed to get [[1, 2, 3, 4], [2, 3, 4], [3, 4], [4]] with lots of useless repetitions.
list = [1,2,3,4]
i = 0
j = 0
tempList = []
sequancesList = []
while i < len(list):
while j < len(list):
tempList.append(list[j])
sequancesList.append(tempList)
j += 1
i += 1
j = i
tempList = []
def deleteDuplicates(list):
noduplist = []
for element in list:
if element not in noduplist:
noduplist.append(element)
return noduplist
finalSequancesList = deleteDuplicates(sequancesList)
print(finalSequancesList)
Here's how to do it:
list = [1,2,3,4]
sequancesList = []
for i in range(len(list)):
tmp = []
for j in range(i,len(list)):
tmp.append(list[j])
sequancesList.append(tmp[:])
print(sequancesList)
-> [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [2], [2, 3], [2, 3, 4], [3], [3, 4], [4]]
Here is a generator that does exactly that:
def iter_successive(input_list):
for i in range(len(input_list)):
for j in range(i+1,len(input_list)+1):
yield input_list[i:j]
>>> list(iter_successive(input_list))
[[1], [1, 2], [1, 2, 3], [1, 2, 3, 4], [2], [2, 3], [2, 3, 4], [3], [3, 4], [4]]
Comparable one-liner solution:
def iter_successive(input_list):
return (input_list[i:j] for i in range(len(input_list))
for j in range(i+1,len(input_list)+1))
Edit: As was stated in the comments, the approach below works only if the list contains whole, ascending numbers and not in other instances.
There are two ways to do this, either as a nested for-loop or a one-liner using list-comprehension. Both versions below:
Nested for-loop
nrs = list(range(1,5))
result = []
for i in nrs:
for j in range(i, max(nrs)+1):
result.append(list(range(i,j+1)))
print(result)
List-comprehension
result = [list(range(i,j+1)) for i in nrs for j in range(i, max(nrs)+1)]
print(result)

How to merge smaller sub-elements into larger parent-elements in a list?

I have a list of lists, but some lists are "sublists" of other lists. What I want to do is remove the sublists from the larger list so that we only have the largest unique sublists.
For example:
>>> some_list = [[1], [1, 2], [1, 2, 3], [1, 4]]
>>> ideal_list = [[1, 2, 3], [1, 4]]
The code that I've written right now is:
new_list = []
for i in range(some_list)):
for j in range(i + 1, len(some_list)):
count = 0
for k in some_list[i]:
if k in some_list[j]:
count += 1
if count == len(some_list[i]):
new_list.append(some_list[j])
The basic algorithm that I had in mind is that we'd check if a list's elements were in the following sublists, and if so then we use the other larger sublist. It doesn't give the desired output (it actually gives [[1, 2], [1, 2, 3], [1, 4], [1, 2, 3]]) and I'm wondering what I could do to achieve what I want.
I don't want to use sets because duplicate elements matter.
Same idea as set, but using Counter instead. It should be a lot more efficient in sublist check part than brute force
from collections import Counter
new_list = []
counters = []
for arr in sorted(some_list, key=len, reverse=True):
arr_counter = Counter(arr)
if any((c & arr_counter) == arr_counter for c in counters):
continue # it is a sublist of something else
new_list.append(arr)
counters.append(arr_counter)
With some inspiration from #mkrieger1's comment, one possible solution would be:
def merge_sublists(some_list):
new_list = []
for i in range(len(some_list)):
true_or_false = []
for j in range(len(some_list)):
if some_list[j] == some_list[i]:
continue
true_or_false.append(all([x in some_list[j] for x in some_list[i]]))
if not any(true_or_false):
new_list.append(some_list[i])
return new_list
As is stated in the comment, a brute-force solution would be to loop through each element and check if it's a sublist of any other sublist. If it's not, then append it to the new list.
Test cases:
>>> merge_sublists([[1], [1, 2], [1, 2, 3], [1, 4]])
[[1, 2, 3], [1, 4]]
>>> merge_sublists([[1, 2, 3], [4, 5], [3, 4]])
[[1, 2, 3], [4, 5], [3, 4]]
Input:
l = [[1], [1, 2], [1, 2, 3], [1, 4]]
One way here:
l1 = l.copy()
for i in l:
for j in l:
if set(i).issubset(set(j)) and i!=j:
l1.remove(i)
break
This prints:
print(l1)
[[1, 2, 3], [1, 4]]
EDIT: (Taking care of duplicates as well)
l1 = [list(tupl) for tupl in {tuple(item) for item in l }]
l2 = l1.copy()
for i in l1:
for j in l1:
if set(i).issubset(set(j)) and i!=j:
l2.remove(i)
break

how to create list of ints from a factorial number in python

I am trying to write a function that accepts a natural number n and returns a list of lists arranged in ascending order with integers by the number in the input.
For example: factorial_list (4) → [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]
For some reason I'm missing something in the way I wrote the code and would love to get an opinion on how the solution can be completed.
Thank you so much everyone
def f_l(n):
return help([], [], n)
def help(lst, s_l, n):
if n <= 1:
s_l.append(n)
lst.append(s_l)
return lst
return lst + help(lst, s_l, n-1)
def factorial_list(num):
num_range = [i for i in range(1, num+1)]
return [num_range[:num] for num in num_range]
Above is a simple algorithm for your problem.
factorial_list(4)
output: [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]
A naive approach to your problem is
lis = []
def fun(n):
for i in range(1, n + 1):
l = []
for j in range(1, i + 1):
l.append(j)
lis.append(l)
return lis
When called as fun(4), it outputs [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]
To simplfy the answer of #RonMarcelino, I suggest you this one-line styled solution:
def factorial_list(num):
return [list(range(1, n+1)) for n in range(1, num+1)]
print(factorial_list(4))
# [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]]
Extending on my comment, if you want to do with your recursive way, you need to use
def f_l(n):
return help([], [], n)
def help(lst, s_l, n):
if n < 1:
return [1]
help(lst, s_l, n-1)
s_l.append(n)
lst.append(s_l.copy())
return lst
With f_l(4), you will get [[1], [1, 2], [1, 2, 3], [1, 2, 3, 4]].
If the objective is to return only list of lists arranged in ascending order with integers by the number in the input the following code will help:
def fact(n):
fact_list = []
temp = n
while temp:
int_list = []
for i in range(1, temp+1):
int_list.append(i)
else:
int_list.sort()
fact_list.append(int_list)
temp -= 1
else:
fact_list.sort()
return fact_list
print fact(4) ## -> python 2.x
print(fact(4)) ## -> python 3.x

List all contiguous sub-arrays

I have an array [1, 2, 3] of integer and I need to return all the possible combination of contiguous sub-arrays of this array.
[[1],[2],[3],[1,2],[2,3],[1,2,3]]
How can I handle that with python? One way would be to have 2 loops and the array itself but there should be a better way.
One line solution (I don't know what means "better way" for you)
L = [1,2,3]
[L[i:i+j] for i in range(0,len(L)) for j in range(1,len(L)-i+1)]
L=[1,2,3,4]
[L[i:i+j] for i in range(0,len(L)) for j in range(1,len(L)-i+1)]
you get,
[[1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]
[[1],
[1, 2],
[1, 2, 3],
[1, 2, 3, 4],
[2],
[2, 3],
[2, 3, 4],
[3],
[3, 4],
[4]]
Simplifying the Inspector's solution:
def getAllWindows(L):
for w in range(1, len(L)+1):
for i in range(len(L)-w+1):
yield L[i:i+w]
And a solution using no loops at all:
def allSubArrays(L,L2=None):
if L2==None:
L2 = L[:-1]
if L==[]:
if L2==[]:
return []
return allSubArrays(L2,L2[:-1])
return [L]+allSubArrays(L[1:],L2)
def kwindow(L, k):
for i in range(len(L)-k+1):
yield L[i:i+k]
def getAllWindows(L):
for w in range(1, len(L)+1):
yield from kwindow(L, w)
Ouput:
In [39]: for i in getAllWindows([1,2,3]): print(i)
[1]
[2]
[3]
[1, 2]
[2, 3]
[1, 2, 3]
An itertools based approach:
import itertools
def allSubArrays(xs):
n = len(xs)
indices = list(range(n+1))
for i,j in itertools.combinations(indices,2):
yield xs[i:j]
For example:
>>> list(allSubArrays([1,2,3]))
[[1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]
li=[1,2,3]
l=[]
for i in range(length(li)):
for j in range(i,len(li)+1):
if i==j: *cancelling empty sublist item*
continue
else:
subli=li[i:j]
l.append(subli)
print(l)
output:
[[1], [1, 2], [1, 2, 3], [2], [2, 3], [3]]

How to obtain sliced sublists of a list dynamically in python?

Let's say I have a list:
l = [0,1,2,3,4]
And I want to obtain a sequence of lists in this logic:
[[1,2,3,4],[0,1,2,3],[2,3,4],[1,2,3],[0,1,2],[3,4],[2,3],[1,2],[0,1],[0],[1],[2],[3],[4]]
That's it, sublists made of l[1:] and l[:-1]
I started by this recursive function:
l = [0,1,2,3,4]
def sublist(l):
if len(l) == 1:
return l
else:
return [sublist(l[1:]),sublist(l[:-1])]
a = [sublist(l)]
print a
But it's not really what I what as it outputs:
[[[[[[4], [3]], [[3], [2]]], [[[3], [2]], [[2], [1]]]], [[[[3], [2]], [[2], [1]]], [[[2], [1]], [[1], [0]]]]]]
import itertools
[list(itertools.combinations(l, x)) for x in range(1, len(l))]
Here's a very straightforward implementation:
def sublists_n(l, n):
subs = []
for i in range(len(l)-n+1):
subs.extend([l[i:i+n]])
return subs
def sublists(l):
subs = []
for i in range(len(l)-1,0,-1):
subs.extend(sublists_n(l,i))
return subs
>>> l = [0,1,2,3,4]
>>> sublists(l)
[[0, 1, 2, 3], [1, 2, 3, 4], [0, 1, 2], [1, 2, 3], [2, 3, 4], [0, 1], [1, 2], [2, 3], [3, 4], [0], [1], [2], [3], [4]]
[l[x:] for x in range(len(l))] + [l[:x+1] for x in range(len(l))]
Loops through l twice, but you sort of have to no matter what I think (could use zip but same thing).
A simple recursion, doesn't quite order things correctly but its simple.
def sublists(l):
right = l[1:]
left = l[:-1]
result = [right, left]
if len(l) > 2:
result.extend(sublists(right))
result.extend(sublists(left))
return result
print sublists([0,1,2,3,4])

Categories

Resources