Last active
January 8, 2019 19:17
-
-
Save YontiLevin/bd32815a0ec62b920bed214921a96c9d to your computer and use it in GitHub Desktop.
Shuffling with constraints on pairs
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# stackoverflow q | |
# https://stackoverflow.com/questions/54041705/shuffling-with-constraints-on-pairs?fbclid=IwAR1WT2KRYX2YHcgwb1MPt8mRHMZbcLFonWlIwGvpcSCnb5yh9LxYKqdw_X4 | |
from random import randint | |
from operator import itemgetter | |
def pop(tmp_d, last_g=1e6): | |
tmp = [] | |
lens = {} | |
for it, t in enumerate(tmp_d): | |
tmp += t | |
lens[it] = len(t) | |
lens_list = sorted(lens.items(), key=itemgetter(1), reverse=True) | |
max_idx, max_len = lens_list[0] | |
others_lens = sum(lens.values()) - max_len | |
if max_len > others_lens: | |
rint = randint(0, max_len - 1) | |
sh_group, sh = tmp_d[max_idx].pop(rint) | |
return sh, sh_group, tmp_d | |
tmp_len = len(tmp) | |
rint = randint(0, tmp_len-1) | |
sh_group, sh = tmp.pop(rint) | |
pad = 0 | |
if sh_group > last_g: | |
sh_group -= 1 | |
pad = 1 | |
t = tmp_d[sh_group] | |
if sh_group == 0: | |
t.pop(rint) | |
lt = [t] | |
for w in tmp_d[1:]: | |
lt.append(w) | |
else: | |
lr = rint - sum([len(x) for x in tmp_d[:sh_group]]) | |
t.pop(lr) | |
lt = tmp_d[:sh_group] | |
lt.append(t) | |
for w in tmp_d[sh_group + 1:]: | |
lt.append(w) | |
return sh, sh_group + pad, lt | |
def shuffle_and_pop(lists): | |
stop = sum([len(x) for x in lists]) | |
list_of_lists = list() | |
for i, l in enumerate(lists): | |
list_of_lists.append([(i, item) for item in l]) | |
n = 0 | |
while n < stop: | |
if n % 2 != 0: | |
exc = list_of_lists.pop(sh_group) | |
sh, new_sh_group, tmp_d = pop(list_of_lists, sh_group) | |
list_of_lists.insert(sh_group, exc) | |
print(sh, end=' ') | |
assert new_sh_group != sh_group, 'even pair error' | |
else: | |
sh, sh_group, list_of_lists = pop(list_of_lists) | |
print(sh, end=' ') | |
n += 1 | |
print() | |
if __name__ == '__main__': | |
alphabet = 'abc' #defghijk' | |
N = 2 # 10 | |
for w in range(10000): | |
all_lists = list() | |
for l in alphabet: | |
all_lists.append([f'{l}{j}' for j in range(N)]) | |
shuffle_and_pop(all_lists) | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
an attempt to solve this stackoverflow question:
https://stackoverflow.com/questions/54041705/shuffling-with-constraints-on-pairs?fbclid=IwAR1WT2KRYX2YHcgwb1MPt8mRHMZbcLFonWlIwGvpcSCnb5yh9LxYKqdw_X4
important - how to avoid deadlocks?
a deadlock can occur if all the remaining items are from one group only.
to avoid that, check in each iteration the lengths of all the lists
and check if the longest list is longer than the sum of all the others.
if true - pull for that list
that way you are never left with only one list full