Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- import math, random
- def get_pool(items, y, z):
- slots = y*z
- use_each_times = slots/len(items)
- exceptions = slots - use_each_times*len(items)
- if (use_each_times > y or
- exceptions > 0 and use_each_times+1 > y):
- raise Exception("Impossible.")
- pool = {}
- for n in items:
- pool[n] = use_each_times
- for n in random.sample(items, exceptions):
- pool[n] += 1
- return pool
- def rebalance(ret, pool, z):
- max_item = None
- max_times = None
- for item, times in pool.items():
- if times > max_times:
- max_item = item
- max_times = times
- next, times = max_item, max_times
- candidates = []
- for i in range(len(ret)):
- item = ret[i]
- if next not in item:
- candidates.append( (item, i) )
- swap, swap_index = random.choice(candidates)
- swapi = []
- for i in range(len(swap)):
- if swap[i] not in pool:
- swapi.append( (swap[i], i) )
- which, i = random.choice(swapi)
- pool[next] -= 1
- pool[swap[i]] = 1
- swap[i] = next
- ret[swap_index] = swap
- def plist(items, y, z):
- pool = get_pool(items, y, z)
- ret = []
- while len(pool.keys()) > 0:
- while len(pool.keys()) < z:
- rebalance(ret, pool, z)
- selections = random.sample(pool.keys(), z)
- for i in selections:
- pool[i] -= 1
- if pool[i] == 0:
- del pool[i]
- ret.append( selections )
- return ret
- print plist([0,1,2,3], 6, 2)
- import math, random
- def get_pool(items, y, z):
- slots = y*z
- use_each_times = slots/len(items)
- exceptions = slots - use_each_times*len(items)
- if (use_each_times > y or
- exceptions > 0 and use_each_times+1 > y):
- raise Exception("Impossible.")
- pool = {}
- for n in items:
- pool[n] = use_each_times
- for n in random.sample(items, exceptions):
- pool[n] += 1
- return pool
- def rebalance(ret, pool, z):
- max_item = None
- max_times = None
- for item, times in pool.items():
- if times > max_times:
- max_item = item
- max_times = times
- next, times = max_item, max_times
- candidates = []
- for i in range(len(ret)):
- item = ret[i]
- if next not in item:
- candidates.append( (item, i) )
- swap, swap_index = random.choice(candidates)
- swapi = []
- for i in range(len(swap)):
- if swap[i] not in pool:
- swapi.append( (swap[i], i) )
- which, i = random.choice(swapi)
- pool[next] -= 1
- pool[swap[i]] = 1
- swap[i] = next
- ret[swap_index] = swap
- def plist(items, y, z):
- pool = get_pool(items, y, z)
- ret = []
- while len(pool.keys()) > 0:
- while len(pool.keys()) < z:
- rebalance(ret, pool, z)
- selections = random.sample(pool.keys(), z)
- for i in selections:
- pool[i] -= 1
- if pool[i] == 0:
- del pool[i]
- ret.append( selections )
- return ret
- print plist([0,1,2,3], 6, 2)
- # list is the elements to be permuted
- # y is the number of results desired
- # z is the number of elements per result
- # equalizer keeps track of who got used how many times
- def constrained_permutations list, y, z
- list.uniq! # Never trust the user. We want no repetitions.
- equalizer = {}
- list.each { |element| equalizer[element] = 0 }
- results = []
- # Do this until we get as many results as desired
- while results.size < y
- pool = []
- puts pool
- least_used = equalizer.each_value.min
- # Find how used the least used element was
- while pool.size < z
- # Do this until we have enough elements in this resultset
- element = nil
- while element.nil?
- # If we run out of "least used elements", then we need to increment
- # our definition of "least used" by 1 and keep going.
- element = list.shuffle.find do |x|
- !pool.include?(x) && equalizer[x] == least_used
- end
- least_used += 1 if element.nil?
- end
- equalizer[element] += 1
- # This element has now been used one more time.
- pool << element
- end
- results << pool
- end
- return results
- end
- constrained_permutations [0,1,2,3,4,5,6], 6, 2
- => [[4, 0], [1, 3], [2, 5], [6, 0], [2, 5], [3, 6]]
- constrained_permutations [0,1,2,3,4,5,6], 6, 2
- => [[4, 5], [6, 3], [0, 2], [1, 6], [5, 4], [3, 0]]
- enter code here
Add Comment
Please, Sign In to add comment