Distinguishable objects into distinguishable boxes
It is very similar to this question posted.
I'm trying to get python code for this question.
Note although it is similar there is a key difference. i.e.
A bucket can be empty, while the other buckets contain all the items. Even this case will be considered as a separate case.
for example:
Consider I have 3 items A,B,C and 3 buckets B1, B2, B3
The table below will show the expected result:
B1 B2 B3
(A,B,C) () ()
() (A,B,C) ()
() () (A,B,C)
(A) (B) (C)
(A) (C) (B)
(B) (A) (C)
(B) (C) (A)
(C) (B) (A)
(C) (A) (B)
(A,B) (C) ()
(A,B) () (C)
(B,C) (A) ()
(B,C) () (A)
(A,C) (B) ()
(A,C) () (B)
() (A,B) (C)
(C) (A,B) ()
() (B,C) (A)
(A) (B,C) ()
() (A,C) (B)
(B) (A,C) ()
() (C) (A,B)
(C) () (A,B)
() (A) (B,C)
(A) () (B,C)
() (B) (A,C)
(B) () (A,C)
Length is 27.
>>def make_sets(items, num_of_baskets=3):
pass
>>make_sets(('A', 'B', 'C', 'D', 'E'), 3)
I'm expecting the output of a function to give me these combinations in a form of list of lists of tuples. I'm saying this again the number of items is variable and the number of buckets is variable too.
** Please provide python code for the make_sets function.
If someone can explain the math combinatorics. I'd greatly appreciate that too. I spent more than 2 days on this problem without reaching a definite solution.
Think about bringing in the items one by one, and each of them having to select a box to land on.
Start with the first item, it has n possible choices. Now the second item comes in, it also has n possible box choices. Since items and boxes are all distinguishable, we do not need to worry about discounting permutations (as one usually needs to do for indistinguishable items). The total number of different possibilities up to this point is n x n.
Bring in the third item, it also has n choices, and so the total number of possibilities is now n x n x n.
You may have noticed by now that the answer is n^k when you have k items.
In the example mentioned, n=3 and k=3, so we have 3^3 = 27 possible ways of placing the items.
The code to get a list with all of the actual combinations is shown below:
import itertools
def make_sets(items, num_of_boxes=3):
allpossible = []
for tup in itertools.product(range(num_of_boxes), repeat=len(items)):
boxes = [list() for _ in range(num_of_boxes)]
for item, box in zip(items, tup):
boxes[box].append(item)
allpossible.append(boxes)
return allpossible
for p in make_sets(('A', 'B', 'C')):
for box in p:
print str(box).ljust(20),
print
Running the above prints out:
['A', 'B', 'C'] [] []
['A', 'B'] ['C'] []
['A', 'B'] [] ['C']
['A', 'C'] ['B'] []
['A'] ['B', 'C'] []
['A'] ['B'] ['C']
['A', 'C'] [] ['B']
['A'] ['C'] ['B']
['A'] [] ['B', 'C']
['B', 'C'] ['A'] []
['B'] ['A', 'C'] []
['B'] ['A'] ['C']
['C'] ['A', 'B'] []
[] ['A', 'B', 'C'] []
[] ['A', 'B'] ['C']
['C'] ['A'] ['B']
[] ['A', 'C'] ['B']
[] ['A'] ['B', 'C']
['B', 'C'] [] ['A']
['B'] ['C'] ['A']
['B'] [] ['A', 'C']
['C'] ['B'] ['A']
[] ['B', 'C'] ['A']
[] ['B'] ['A', 'C']
['C'] [] ['A', 'B']
[] ['C'] ['A', 'B']
[] [] ['A', 'B', 'C']
Notice that this corresponds to base-n numbers (I hope you can beautify the output). This solution is independent of n and k:
n = 3
k = 4
a = [0] * k
def to_base_n(x):
num = 0
while x is not 0:
num *= 10
num += x % n
x //= n
return num
for i in range(0, n ** k):
s = ('%0' + str(k) + 'd') % (to_base_n(i))
x = [list() for _ in range(n)]
for i in range(k):
x[int(s[i])].append(str(i))
print(x)
Related
Sorry if my question is basic but I have not coded in the past 15 years although I am trying to learn to code again for a research project. I have a set of 12 objects [A B C D E F G H I J K L] and I want to create a list of any possible K-multiset for any K between 1 and 6. (I do have a list of selection probabilities for them but at this stage of the project I can assume an equal probability of selection for all). Order matters and repetition is allowed (so they are just k-tuples). For example: [A], [A A] [B A A] [A B A], [B A A A A A] etc. I tried to use weighted-n-of-with-repeats in the RND extension of NetLogo but it seems that order does not matter in it so [B A] and [A B] are the same thing and are reported as [A B]. Can you please help with the NetLogo code?
This is what I have tried so far but unfortunately it does not recognize order:
to k-multiset
let n 0
let pairs [[ "A" 0.1 ] [ "B" 0.1 ] ["C" 0.1] [“D” 0.1] [“E” 0.1] [“F” 0.1] [“G” 0.1] [“H” 0.1] [“I” 0.1] [“J” 0.1] [“K” 0.1]]
while [n < 7] [print map first rnd:weighted-n-of-list-with-repeats n pairs [[p] -> last p ]]
end
Note that every multiset containing K items can be represented as integer value in 12-ary numeral system, where A corresponds to 0, B corresponds to 1 and so on until L=11.
So you can just walk through all integers in range 0..12^K-1 (about 3 millions for K=6) and get 12-ary digits as indexes of items.
python code for smaller item list and output range:
List = list('ABC')
L = len(List)
for K in range(1,4):
for i in range(L**K):
j = i
output = []
for n in range(K): #K digits
d = j % L #integer modulo for n-th digit
j = j // L #integer division
output.insert(0,List[d])
print(output)
part of output:
['A']
['B']
['C']
['A', 'A']
['A', 'B']
['A', 'C']
...
['C', 'C']
['A', 'A', 'A']
['A', 'A', 'B']
['A', 'A', 'C']
...
['C', 'B', 'C']
['C', 'C', 'A']
['C', 'C', 'B']
['C', 'C', 'C']
Example:
a = ['a', 'c'] # first test
b = ['a', 'b', 'c']
a = ['a','e'] # second test
b = ['a','b','c']
list_final = compare(a,b) # we tried this not working
We have to create the following logic: if both elements of list a are in list b, it will proceed further, whereas if one element of list a is not available in list b it has to terminate. Please suggest me a solution.
Is this what you are looking for?
def compare(x, y):
"Return True if all the elements of x are in y, False otherwise"
return all([item in y for item in x])
You can use the function above in conditional branching:
def wrapper(x, y):
if compare(x, y):
print 'Proceed further'
else:
print 'Break'
Give this code a try to figure out how it works:
>>> a1 = ['a','c']
>>> a2 = ['a','e']
>>> b = ['a','b','c']
>>> wrapper(a1, b)
Proceed further
>>> wrapper(a2, b)
Break
Make this as your compare method using all keyword of python :-
def compare(x,y):
if all(i in y for i in x):
print "Proceed"
# Call the next code piece
else:
print "Terminate"
break
Now pass a as x and b as y in the call :-
>>> # Test 1
>>> a = ['a', 'c'] # first test
>>> b = ['a', 'b', 'c']
>>> compare(a, b)
Proceed
>>> # Test 2
>>> a = ['a', 'e'] # first test
>>> b = ['a', 'b', 'c']
>>> compare(a, b)
Terminate
In Python I'm trying to take:
mylist=[a,a,a,b,b,c]
and make it into:
mylist=[(a,0),(a,1),(a,2),(b,0),(b,1),(c,0)]
Here is a solution using Counter:
from collections import Counter
c = Counter()
l = ['a', 'a', 'a', 'b', 'b', 'c', 'c']
out = []
for e in l:
out.append((e, c[e]))
c[e] += 1
print(out)
Here is another one, which assumed that input list is sorted:
from itertools import groupby
print(tuple((e, idx) for _, group in groupby(l) for idx, e in enumerate(group)))
I am doing a minor structure manipulation using python, and have a few issues.
Currently my output is the data below.
[['a', ['b', 'c'], ['d', 'e']], ['h', ['i'], ['j']]]
I want to get into this structure below, but my data structure comes out a bit wrong. There could be multiple lists with different entry per list.
(a, b, a, d), (a, c, a, e), (h, i, h, j)
What would be the best approach?
Here's a quick one:
from itertools import product, izip
data = [['a', ['b', 'c'], ['d', 'e']], ['h', ['i'], ['j']]]
result = []
for d in data:
first = d[0]
for v in izip(*d[1:]):
tmp = []
for p in product(*[first, v]):
tmp.extend(p)
result.append(tuple(tmp))
print result
Output:
[('a', 'b', 'a', 'd'), ('a', 'c', 'a', 'e'), ('h', 'i', 'h', 'j')]
I'm trying to understand how comprehensions work.
I would like to loop through two lists, and compare each to find differences.
If one/or-more word(s) is different, I would like to print this word(s).
I'd like this all in one nice line of code, which is why I'm interested in comprehensions.
Doing it in "one nice line of code" is code golf, and misguided. Make it readable instead.
for a, b in zip(list1, list2):
if a != b:
print(a, "is different from", b)
This is not different in any significant way from this:
[print(a, "is different from", b) for a, b in zip(list1, list2) if a!=b]
Except that the expanded version easier to read and understand than the comprehension.
Like kriegar suggested using sets is probably the easiest solution. If you absolutely need to use list comprehension, I'd use something like this:
list_1 = [1, 2, 3, 4, 5, 6]
list_2 = [1, 2, 3, 0, 5, 6]
# Print all items from list_1 that are not in list_2 ()
print(*[item for item in list_1 if item not in list_2], sep='\n')
# Print all items from list_1 that differ from the item at the same index in list_2
print(*[x for x, y in zip(list_1, list_2) if x != y], sep='\n')
# Print all items from list_2 that differ from the item at the same index in list_1
print(*[y for x, y in zip(list_1, list_2) if x != y], sep='\n')
If you want to compare two lists for differences, I think you want to use a set.
s.symmetric_difference(t) s ^ t new set with elements in either s or t but not both
example:
>>> L1 = ['a', 'b', 'c', 'd']
>>> L2 = ['b', 'c', 'd', 'e']
>>> S1 = set(L1)
>>> S2 = set(L2)
>>> difference = list(S1.symmetric_difference(S2))
>>> print difference
['a', 'e']
>>>
one-line form?
>>> print list(set(L1).symmetric_difference(set(L2)))
['a', 'e']
>>>
if you really want to use a list comprehension:
>>> [word for word in L1 if word not in L2] + [word for word in L2 if word not in L1]
['a', 'e']
much less efficient as the size of the lists grow.