Generating K-multisets when order matters and repetition is allowed - combinations

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']

Related

How to match elements from arrays and only print matches?

I have two lists, i am trying to match one item from the first list to another from the second list under a certain condition (for example if they share the same number in the same location). i wrote my code to match the first set ['A','B','C',4,'D'] and only print the set from list2 that has 4 in the same location. so basically my output would be:
['A','B','C',4,'D']
[1, 2, 3, 4, 5]
well i can't figure out how to print only the match
here is my code:
list1 = [['A','B','C',4,'D'],['A','B','C',9,'D'],['A','B','C',5,'D'],['A','B','C',6,'D'],['A','B','C',7,'D']]
list2 = [[1,2,3,2,5],[1,2,3,5,5],[1,2,3,3,5],[1,2,3,4,5],[1,2,3,1,5],[1,2,3,2,5]]
for var in list1:
print var
for i in range(0,len(list2)):
for var1 in list2:
if list1[0][3] == list2[i][3]:
print var1
Your program would become easier, if you used izip of itertools. Assuming you just need to print the elements
from itertools import izip
list1 = [['A','B','C',4,'D'],['A','B','C',9,'D'],['A','B','C',5,'D'],['A','B','C',6,'D'],['A','B','C',7,'D']]
list2 = [[1,2,3,2,5],[1,2,3,5,5],[1,2,3,3,5],[1,2,3,4,5],[1,2,3,1,5],[1,2,3,2,5]]
for item1 in list1:
for item2 in list2:
for i,j in izip(item1, item2):
if i==j:
print i
By using izip two times, it would be much easier
from itertools import izip
list1 = [['A','B','C',4,'D'],['A','B','C',9,'D'],['A','B','C',5,'D'],['A','B','C',6,'D'],['A','B','C',7,'D']]
list2 = [[1,2,3,2,5],[1,2,3,5,5],[1,2,3,3,5],[1,2,3,4,5],[1,2,3,1,5],[1,2,3,2,5]]
for i in izip(list1,list2):
for item1, item2 in izip(i[0],i[1]):
if item1 == item2:
print item1
Almost. I am not sure if that is what you wanted but the following code prints all pairs which have the same number in the 4th location of the array:
list1 = [['A','B','C',4,'D'],['A','B','C',9,'D'],['A','B','C',5,'D'],
['A','B','C',6,'D'],['A','B','C',7,'D']]
list2 = [[1,2,3,2,5],[1,2,3,5,5],[1,2,3,3,5],[1,2,3,4,5],[1,2,3,1,5],
[1,2,3,2,5]]
for t in list1:
print t
for b in list2:
if t[3] == b[3]:
print b
Output is:
['A', 'B', 'C', 4, 'D']
[1, 2, 3, 4, 5]
['A', 'B', 'C', 9, 'D']
['A', 'B', 'C', 5, 'D']
[1, 2, 3, 5, 5]
['A', 'B', 'C', 6, 'D']
['A', 'B', 'C', 7, 'D']
Is that what you were looking for?

Find unique items in a list using a passed value for range of the list (sublists)

I am trying to tie two different things together.
1. Find and print unique items in a list.
2. Pass a int value and print unique items in the first n items
I have two things that work, but not in conjunction, to split the list into sub-lists of n:
def find_uniques(3):
lista = ['a', 'a', 'b','c','d','c','e','d','e','f','f']
lists = [lista[x:x+n] for x in xrange(0, len(lista), n)]
print lists
[['a', 'a', 'b'], ['c', 'd', 'c'], ['e', 'd', 'e'], ['f', 'f']]
# 2nd part works on the whole list
print [a for a in lista if lista.count(a) == 1]
['b']
# How do I get the second part to work on the sub lists, and give me back unique chars from each sub list.
The output I am looking for:
[['b'],['d'], ['d']]
Usually it is easier to just split out these operations instead of merging, but here is a nested list comprehension.
lista = ['a', 'a', 'b','c','d','c','e','d','e','f','f']
n = 3
[[ item for item in sublist if sublist.count(item) == 1] for sublist in [ lista[x:x+n] for x in xrange(0, len(lista), n) ] ]
Personally, although it is longer, I prefer a more readable version like so:
def findunique(lista,n=3):
listoflists = [ lista[x:x+n] for x in xrange(0,len(lista),n) ]
results = []
for sublist in listoflists:
unique = [ item for item in sublist if sublist.count(item) == 1]
if unique:
results.append(unique)
return results
lista = ['a','a','b','c','d','c','e','d','e','f','f']
print findunique(lista,3)

No of ways of placing k distinguishable items into n distinguishable boxes

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)

List to a different output

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')]

Python - Compare two lists in a comprehension

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.