Combining arrays of diff sizes - python

I have this code that creates permutations of a given number. It also give the permuatations based on the number of specified digits, so 2 would give the permutations of all possible 2 digit values. I have this looped so for a 4 digit number, it would loop giving all permutations scenarios, like 4,3,2 and 1 digit permutations scenarios. The problem im having is how to store the perm variable which stores the permutations. I tried making a multi array perm, then as the loop iterates it adds the new array to the perm. Didn't work because the arrays are different sizes. How can I continue?
def fp(number):
# A Python program to print all
# permutations using library function
from itertools import permutations
# Get all permutations of [1, 2, 3]
c= list(map(int,str(number)))
print(c, len(c))
i=1
while i <= len(c):
perm= permutations(c,i) #permuate the number c to the number of specified digits i
i+=1
# Print the obtained permutations
for i in list(perm):
print (i)

You are searching for a powerset, search in these functions by itertools for powerset. I just changed the combinations to permutations.
Then loop through all permutations and append them to a list (you could also use a dictionary)
import itertools
def powerset(iterable):
s = list(iterable)
return itertools.chain.from_iterable(itertools.permutations(s, r) for r in range(1,len(s)+1))
lst_of_numbers = [1, 2, 3]
out = []
for perm in powerset(lst_of_numbers):
out.append(perm)
print(out)
[(1,), (2,), (3,), (1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2), (1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)]

Use another variable to hold all the permutations. Extend it with the list returned by each call to permutations().
def fp(number):
# A Python program to print all
# permutations using library function
from itertools import permutations
all_perms = []
c= list(map(int,str(number)))
print(c, len(c))
i=1
while i <= len(c):
perm= permutations(c,i) #permuate the number c to the number of specified digits i
all_perms.extend(perm)
i+=1
# Print the obtained permutations
for i in all_perms:
print (i)

Related

How to I calculate permutations without memory problems

Hello I need all permutations of a List l = [1,2,...,n] with length m.
from itertools import permutations
def calcPerm(l:list,m: int)
perm=[]
for i in permutations(l, m):
perm.append(list((i)))
But like u see for n great enough the memory will explode.
Is there a way where I do not have to save does permutations, so i can use every single one
immediately but not get them twice( e.g [1,2] and [2,1] ?
You must use combinations instead of permutations:
from itertools import combinations, permutations
my_list = [1,2,3]
print(list(permutations(my_list, 2)))
#[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)]
print(list(combinations(my_list, 2)))
#[(1, 2), (1, 3), (2, 3)]
Use itertools.combinations and to save memory use yield:
from itertools import combinations
def calcPerm(l: list, m: int):
for i in combinations(l, m):
yield list((i))
for p in calcPerm(range(10), 5):
print(p)

Sum element of numbers to get desired result

By using the snippet
import itertools
numbers = [1,2,3,4,5]
results = [7,8]
allcombs = [seq for i in range(len(numbers), 0, -1) for seq in itertools.combinations(numbers, i) if sum(seq) in results]
print(allcombs)
I'm able to get all combinations which give me the desire results. Major problem here is that the number must not repeat. So, instead of result
[(1, 2, 4), (1, 2, 5), (1, 3, 4), (2, 5), (3, 4), (3, 5)]
I need to get
[(1, 2, 4),(3, 5)]
All elements of results doesnt needs to be contained in combination of numbers.
Edit:
1 Solution
usednumbers = []
newresult = []
for comb in allcombs:
if not any(a in usednumbers for a in comb):
newresult.append(comb)
for n in comb:
usednumbers.append(n)
print(newresult)
I would suggest a recursive function that will find the largest combination first and then call itself with the remaining numbers to add other combinations that match the results.
Also, the combinations should be generated with indexes in addition to the numbers themselves to make it easier to determine the remaining values when the list contains duplicates numbers.
from itertools import combinations
def comboToSums(numbers,results,size=None):
if size is None: size = len(numbers)
if size == 0: return []
for combo in combinations(enumerate(numbers),size):
indexes,values = zip(*combo)
if sum(values) not in results: continue
remaining = [n for i,n in enumerate(numbers) if i not in indexes]
return [values] + comboToSums(remaining,results)
return comboToSums(numbers,results,size-1)
output:
numbers = [1,2,3,4,5]
results = [7,8]
c = comboToSums(numbers,results)
print(c) # [(1, 2, 4), (3, 5)]

Generate all vector that respect a condition in Python

Is there a way to generate a list of all the vector of length n witch the element are between 1 and 6 like this : this ? I only know how to do it for a specific n with nested for loop. Thank you
A function which takes a pool and a length:
from itertools import product
def generate_vectors(pool, length):
return list(product(pool, repeat=length))
generate_vectors(range(1,7), 3)
# [(1, 1, 1), (1, 1, 2), (1, 1, 3), ...]

how to find combinations of elements with minimum length of N using itertools-Python

from itertools import combinations
a = [1,2,3]
combinations(a,2) #will give me ((1,2),(1,3),(2,3))
combinations(a,3) #will give me ((1,2,3),)
but what if I want results of different length which is in a array
e.g.
I want to find all combinations of given array[1,2,3] of length more than or equal to 2
so result should be ((1,2),(1,3),(2,3),(1,2,3))
something like c = combinations(a,>=2)
I tried to use lambda but its not working
c = combinations(a,lambda x: x for x in [2,3])
as well list comprehensive c = combinations(a,[x for x in [2,3]])
I know I can use a simple loop and then find out the combinations of diff length.
for l in [2,3]:
combinations(a,l)
But Is there any pythonic way to do this?
You could combine combinations and chain.from_iterable:
>>> from itertools import chain, combinations
>>> a = [1,2,3]
>>> n = 2
>>> cc = chain.from_iterable(combinations(a, i) for i in range(n, len(a)+1))
>>> list(cc)
[(1, 2), (1, 3), (2, 3), (1, 2, 3)]
chain.from_iterable here is flattening what the generator expression (combinations(a, i) for i in range(n, len(a)+1)) is producing. Otherwise you'd wind up with something like
>>> [list(combinations(a,i)) for i in range(n, len(a)+1)]
[[(1, 2), (1, 3), (2, 3)], [(1, 2, 3)]]
which is fine, but not quite in the format you were looking for.

Return a sequence of a variable length whose summation is equal to a given integer

In the form f(x,y,z) where x is a given integer sum, y is the minimum length of the sequence, and z is the maximum length of the sequence. But for now let's pretend we're dealing with a sequence of a fixed length, because it will take me a long time to write the question otherwise.
So our function is f(x,r) where x is a given integer sum and r is the length of a sequence in the list of possible sequences.
For x = 10, and r = 2, these are the possible combinations:
1 + 9
2 + 8
3 + 7
4 + 6
5 + 5
Let's store that in Python as a list of pairs:
[(1,9), (2,8), (3,7), (4,6), (5,5)]
So usage looks like:
>>> f(10,2)
[(1,9), (2,8), (3,7), (4,6), (5,5)]
Back to the original question, where a sequence is return for each length in the range (y,x). I the form f(x,y,z), defined earlier, and leaving out sequences of length 1 (where y-z == 0), this would look like:
>>> f(10,1,3)
[{1: [(1,9), (2,8), (3,7), (4,6), (5,5)],
2: [(1,1,8), (1,2,7), (1,3,6) ... (2,4,4) ...],
3: [(1,1,1,7) ...]}]
So the output is a list of dictionaries where the value is a list of pairs. Not exactly optimal.
So my questions are:
Is there a library that handles this already?
If not, can someone help me write both of the functions I mentioned? (fixed sequence length first)?
Because of the huge gaps in my knowledge of fairly trivial math, could you ignore my approach to integer storage and use whatever structure the makes the most sense?
Sorry about all of these arithmetic questions today. Thanks!
The itertools module will definately be helpful as we're dealing with premutations - however, this looks suspiciously like a homework task...
Edit: Looks like fun though, so I'll do an attempt.
Edit 2: This what you want?
from itertools import combinations_with_replacement
from pprint import pprint
f = lambda target_sum, length: [sequence for sequence in combinations_with_replacement(range(1, target_sum+1), length) if sum(sequence) == target_sum]
def f2(target_sum, min_length, max_length):
sequences = {}
for length in range(min_length, max_length + 1):
sequence = f(target_sum, length)
if len(sequence):
sequences[length] = sequence
return sequences
if __name__ == "__main__":
print("f(10,2):")
print(f(10,2))
print()
print("f(10,1,3)")
pprint(f2(10,1,3))
Output:
f(10,2):
[(1, 9), (2, 8), (3, 7), (4, 6), (5, 5)]
f(10,1,3)
{1: [(10,)],
2: [(1, 9), (2, 8), (3, 7), (4, 6), (5, 5)],
3: [(1, 1, 8),
(1, 2, 7),
(1, 3, 6),
(1, 4, 5),
(2, 2, 6),
(2, 3, 5),
(2, 4, 4),
(3, 3, 4)]}
The problem is known as Integer Partitions, and has been widely studied.
Here you can find a paper comparing the performance of several algorithms (and proposing a particular one), but there are a lot of references all over the Net.
I just wrote a recursive generator function, you should figure out how to get a list out of it yourself...
def f(x,y):
if y == 1:
yield (x, )
elif y > 1:
for head in range(1, x-y+2):
for tail in f(x-head, y-1):
yield tuple([head] + list(tail))
def f2(x,y,z):
for u in range(y, z+1):
for v in f(x, u):
yield v
EDIT: I just see it is not exactly what you wanted, my version also generates duplicates where only the ordering differs. But you can simply filter them out by ordering all results and check for duplicate tuples.

Categories