actually I'm looking for combinatory with a limited number of repetitions, I know in python in itertools we already have for no repetitions and with ANY repetition, but I can't found anything for this.
Lets remember, a Combinatory we pick n elements, with a max repetitions, and in the elements, we don't care the order, (A, B, C) is the same as (B, C, A).
Here an example:
A B, C
picking 2, repeated 0:
A, B
A, C
B, C
picking 2, repeated 1:
A, A
A, B
A, C
B, B
B, C
C, C
The functions combinations and combinations_with_replacement doesn't give this behavior, is like what I'm looking for is the mix of both.
Lets be clear, the number of repetitions is the max, so with ABCD, pick 3 and repeat 2, AAB would be valid.
Is there a lib or module with somthing like this?
Considerations:
I use big list to apply this, so even If I can filter the results from combinations_with_replacement is not very efficient one by one, I need a generator to not overload the ram.
I would like to avoid this method, or some other more efficient:
def Combs2(data, pick, rep):
for i in itertools.combinations_with_replacement(data, pick):
s = set(i)
show = True
for j in s:
if i.count(j) > (rep+1):
show = False
break
if show:
yield i
I test this code, is soo slow that kills every multiprocessing that I'm using, instead using the cores ends using 1....
Edited:
To show the difference with combinations_with_replacement
We have ABCDE, lets pick 3 elements with 1 rep.
here example, AAB, BBC, BCA
AAA would be not valid.
We can't get this with combinations_with_replacement or combinations.
There is a one-to-one correspondence between the combinations that you seek and k-tuples of bounded non-negative integers with a given target sum. For example,
AAB, when drawn from ABC consists of 2 A, 1 B and 0 C, so the correspondence is AAB <=> (2,1,0).
One strategy is to write a generator for such tuples and then decode it as it generates to get the output that you want:
#generates multisets of a given size but with bounded multiplicity
#The following generator generates all tuples of
#non-negative integers of length k
#bounded by d and summing to n
#shouldn't be called if n > k*d
def f(n,k,d,path = ()):
if n == 0:
yield path + (0,)*k
elif k == 1:
yield path + (n,)
else:
lower = max(0,n - (k-1)*d)
upper = min(n,d)
for i in range(lower,upper+1):
yield from f(n-i,k-1,d,path + (i,))
def bounded_combos(items,count,bound):
for t in f(count,len(items),bound):
combo = []
for item,count in zip(items,t):
combo.extend([item]*count)
yield combo
For example,
>>> for c in bounded_combos('ABC',3,2): print(c)
['B', 'C', 'C']
['B', 'B', 'C']
['A', 'C', 'C']
['A', 'B', 'C']
['A', 'B', 'B']
['A', 'A', 'C']
['A', 'A', 'B']
In terms of the number tuples:
>>> for t in f(3,3,2): print(t)
(0, 1, 2)
(0, 2, 1)
(1, 0, 2)
(1, 1, 1)
(1, 2, 0)
(2, 0, 1)
(2, 1, 0)
As far as how many goes, you can work out a recursive formula for the number of combinations with the key idea that if
a_1 + a_2 + ... + a_k = n
then
a_2 + a_3 + ... + a_k = n - a_1
hence the count for a given k and n can be reduced to counts for k-1 and smaller n. A naive implementation of this recursion would involve repeatedly evalauting the same expression, but memoization makes it feasible for large k,n:
def g(n,k,d):
memo = {} #memoization dictionary
def h(n,k):
if (n,k) in memo:
return memo[(n,k)]
else:
if n == 0:
count = 1
elif k == 1:
count = 1
else:
lower = max(0,n - (k-1)*d)
upper = min(n,d)
count = sum(h(n-i,k-1) for i in range(lower,upper+1))
memo[(n,k)] = count
return count
return h(n,k)
Examples:
>>> g(3,3,2)
7
>>> g(10,5,5)
651
>>> g(100,20,10)
18832730699014127291
I don't know of any closed-form formula for these. As an experiment, I evaluated
','.join(str(g(n,n,2)) for n in range(1,11))
and pasted it into the search bar of the On-Line Encyclopedia of Integer Sequences and got a very interesting hit: A002426, the central trinomial coefficients, which are discussed here. If you rerun this experiment with different choices of n,k,d, you might stumble upon a nice formula for the overall function.
Related
I have implemented this algorithm for the Longest common subsequence, I have tested it for every possible test case, it works, but when I submit it to the online grader of the course, it says it failed on case 11, I can't think of any possible test case that would break it down. Can you help? It returns idx longest subsequence.
def lcs2(a, b):
idx = 0
for i in a:
if i not in b:
a.remove(i)
if len(a) <= len(b):
for i in a:
if i in b:
idx += 1; b = b[b.index(i)+1:]
else:
for i in b:
if i in a:
idx += 1; a = a[a.index(i)+1:]
return idx
I can hack you with a sample:
a = [1,2,3,4,5]
b = [2,3,4,1,5]
one correct solution is Dynamic Programming
What you seem to be searching for is not the longest common subsequence, but the length of this longest common subsequence. However, the wrong assumption is that the first of the two lists contains the start of this subsequence at an earlier index than the second list.
The answer supplied already gives an example of where this happens:
a = [1,2,3,4,5]
b = [2,3,4,1,5]
I will expand with:
c = [3,4,2,1,5]
You will see that:
import itertools as it
rets = [lcs2(x,y) for x,y in it.permutations([a,b,c],2)]
combis = [(x,y) for x,y in it.permutations(['a','b','c'],2)]
print(*zip(rets, combis), sep='\n')
#(2, ('a', 'b'))
#(2, ('a', 'c'))
#(4, ('b', 'a'))
#(3, ('b', 'c'))
#(3, ('c', 'a'))
#(4, ('c', 'b'))
In other words, the lcs2 function you defined is a-symmetrical and therefore not correct.
We have to accept a list and find the subsequent from the list such that number in subsequence are in increasing order.
Find sum of each subsequence
return maximum sum
For example
Input=[1, 4,2]
Possible subsequence will be [1][4][2][1,4][1,2]
Here [4,2] will not come as 4 is greater. And order should not change. Means first position elements if it comes in sublist it should be first
Sum of each subsequence will be 1,4,2,5,3
Output will be 5.
What will be your logic to solve it?
You can use itertools.combinations and itertools.chain to do this easily
>>> from itertools import combinations, chain
>>> Input=[1, 4,2]
>>> max(map(sum, (filter(lambda x: sorted(x) == list(x), chain(*[combinations(Input, i) for i in range(1, len(Input)+1)])))))
5
Explanation
>>> possibilities = chain(*[combinations(Input, i) for i in range(1, len(Input)+1)])
>>> filtered_possibilities = filter(lambda x: sorted(x) == list(x), possibilities)
>>> sum_of_each_possibility = map(sum, filtered_possibilities)
>>> max_sum = max(sum_of_each_possibility)
>>> print (max_sum)
5
You can break down the question into three steps:
1) Find the power_set(all sub lists) of list.
2) Filter out unwanted list (list with decreasing order).
3) Find the max sum.
Step1:
def powerset(s):
x = len(s)
res=[]
for i in range(1 << x):
res.append([s[j] for j in range(x) if (i & (1 << j))])
return res
lst=[1,4,2]
res=powerset(lst)
Step 2&3:
def max_sub(lsts):
max_out=0
def helper(lsts): #Step2: to filter out decreasing lists.
if lsts==[]:
return False
else:
for i in range(len(lsts)-1):
if lsts[i]>lsts[i+1]:
return False
return True
filtered_lst=list(filter(lambda x:helper(x),lsts))
for lst in filtered_lst:
max_out=max(max_out,sum(lst)) #step3: Find out the max sub list sum.
return max_out
print(max_sub(res))
Result:
5
Drako already mentioned, that this is not free coding service. Show some effort yourself and tell us, what you already tried and how it didn't work. also provide output to help us analyze the problem. I'll help anyway; also welcome to StackOverflow.
What you are looking for is a "power set". An exhaustive set M of sets s, where each s is a subset of M and there is in fact no subset of M which is not already contained in a s. As sets are unordered by definition, you don't have to care about duplicates because of different ordering. Looking at this question
There is a nice answer to get the power set of a given set. Assuming your input list/set/iterable is i, you can use the following code to get the power set list.
from itertools import chain, combinations
def get_power_set(i):
i.sort() # Sorted input --> sorted output
ps_iterable = chain.from_iterable(combinations(i, r) for r in range(len(i)+1))
return list(ps_iterable)
def get_highest_sum(input_list):
maximum = 0
for s in input_list:
sum_of_set = sum(s)
if sum_of_set > maximum:
maximum = sum_of_set
return maximum
i = [1,2,3] # Assign your input list here
power_set = get_power_set(i)
highest_sum = get_highest_sum(power_set)
print(power_set)
# >>> [(), (1,), (2,), (3,), (1, 2), (1, 3), (2, 3), (1, 2, 3)]
print("Highest sum is {}".format(highest_sum))
# >>> 6
I need help writing some Python code that input is a list A that represents a set and whose output is a list of the subsets of A that have cardinality of 2. I want to do this using an import, my professor wants me to understand where the numbers come from.
For instance:
if A = [a, b, c], then
listPairs(A) = [[a, b], [a, c], [b, c]].
Try itertools.combinations. The following returns all subsequences of length 2 of A.
import itertools
[set(x) for x in itertools.combinations(A, 2)]
Examples:
# AB AC AD BC BD CD
[set(x) for x in itertools.combinations('ABCD', 2)]
# 012 013 023 123
[set(x) for x in itertools.combinations(range(4), 3)]
This is the syntax for the functional equivalent:
list(map(set, itertools.combinations(A, 2)))
You are essentially after the most standard combinations function. As
already pointed out, this can be done easily with itertools.combinations, or you can implement it yourself with recursion:
def combos(l, n):
if n == 1:
return [[e] for e in l]
cs = []
for i, e in enumerate(l):
for c in combos(l[i+1:], n-1):
cs.append([e] + c)
return cs
and a test demonstrates its functionality:
>>> combos(['a', 'b', 'c'], 2)
[['a', 'b'], ['a', 'c'], ['b', 'c']]
I have a problem to find the max of sum of count of set bits in any k-elements from the given list.
Given :
n = 4 # length of list
k = 2 # choose only k elements of list whose count(sum(set bits)) is max
list l= 6 2 1 0
so If I choose numbers 6 (110) and 1 (001) with 2 and 1 set bits respectively, adding them gives me max count of set bits i.e . 3
What I tried is :
from itertools import combinations
s = list(map(int,raw_input().split()))
n = s[0]
k = s[1]
l = list(map(int,raw_input().split()))
comb = list(combinations(l, k))
# print comb
ad = []
for i in comb:
x = bin(i[0])[2:].count('1')+bin(i[1])[2:].count('1')
ad.append(x)
# print ad
print max(ad)
My problem is with line :
x = bin(i[0])[2:].count('1')+bin(i[1])[2:].count('1')
As k = 2, I took this manually i[0] and i[1].
But how to do this dynamically.
Also I am looking for a answer without using list comprehension,as my list size may vary to 2 to 10^18 which cause memory exceeding.
If you can suggest any other logic,that will be much useful.
I would expect that there is a sort in there. I really think that combinations isn't needed because only the the items with the most bits set can make up the result. Consider the following:
Given your input, the following I think computes the result:
n = 4 # length of list
k = 2 # choose only k elements of list whose count(sum(set bits)) is max
l = [6, 2, 1, 0]
like this:
>>> sorted(l, key=lambda v: bin(v)[2:].count('1'), reverse=True)[:2]
[6, 2]
This can be made to stream over the input by using a heapq of size k and inserting (bin(v)[2:].count('1'), v) then the result can be product by extracting the numbers. The heapq function nlargest will work nicely
>>> import heapq
>>> heapq.nlargest(k, l, key=lambda v: bin(v)[2:].count('1'))
[6, 2]
Note that l can be a iterator. This operates in constant space. The memory usage depends on k not on the length of the iterator.
Then you can compute the sum of the bits set as in the other answers:
>>> sum(bin(v)[2:].count('1') for v in [6,2])
3
I think
x = sum([bin(i[kk])[2:].count('1') for kk in range(k)])
could work
I have two lists:
a = ['a', 'b', 'c']
b = [1]
I want my output as:
a, 1
b, 1
c, 1
Tried doing this:
for i, j in zip(a, b):
print i, j
I get only a, 1. How can I make it right?
This is my actual scenario:
if request.POST.get('share'):
choices = request.POST.getlist('choice')
person = request.POST.getlist('select')
person = ''.join(person)
person1 = User.objects.filter(username=person)
for i, j in izip_longest(choices, person1, fillvalue=person1[-1]):
start_date = datetime.datetime.utcnow().replace(tzinfo=utc)
a = Share(users_id=log_id, files_id=i, shared_user_id=j.id, shared_date=start_date)
a.save()
return HttpResponseRedirect('/uploaded_files/')
You should probably use itertools.izip_longest() here:
In [155]: a = ['a', 'b', 'c']
In [156]: b = [1]
In [158]: for x,y in izip_longest(a,b,fillvalue=b[-1]):
.....: print x,y
.....:
a 1
b 1
c 1
In case of zip() as the length of b is just one, so it is going to return only one result.
i.e it's result length equals min(len(a),len(b))
But in case of izip_longest the result length is max(len(a),len(b)), if fillvalue is not provided then it returns None.
OK, i'm late by at least one hour, but what about this idea:
a = ['a', 'b', 'c']
b = [1]
Since the docs on zip state
The returned list is truncated in length to the length of the shortest argument sequence.
what about turning the list a to the shorter argument? And since everything is shorter than a cycle that runs forever, let's try
import itertools
d = zip(a, itertools.cycle(b))
Thanks to Ashwini Chaudhary for bringing the itertools to my attention ;)