March 15th, 2013, 12:16 PM

Uncomfortably Merging Together Two Sets
Okay, this is mostly a dev question.
I have a system for generating weighted randoms the simple way, i.e. assign each item a weight, run a random number against the total of all weights, see where it falls.
I'm hoping to return, instead of the current return that only gives an index value for the list of weights, the result of a dictionary that matches up to that list.
Here's what I got so far:
Code:
def roll_odds(tabl):
from random import randrange
cnt,cap,roll = int(),int(),randrange(0,sum(tabl))
while cnt<len(tabl):
cap += tabl[cnt]
if roll < cap:
return cnt
break
else:
cnt += 1
def get_sample(tabl,sampsize=1000):
results = list(0 for c in tabl)
for i in range(0,sampsize):
nValue = roll_odds(tabl)
results[nValue] += 1
return results
def get_chances(tabl):
results = tabl
tot = float(sum(tabl))
for i in range(0,len(tabl)):
results[i] /= tot
return results
get_chances() and get_sample() are purely debug/integrity check functions.
Trying to build a dictionary, I got this so far:
Code:
test = {}
for k in range(0,20):
test[k] = k
def get_next_free(ind):
nxt = int()
while nxt in ind.keys():
nxt += 1
return nxt
If you couldn't tell, this finds a free key for the dictionary that I can use to append a new weight to the list.
Here's the problem:
Whenever I try to remove an item from the set, like so:
Return Item 'A' 'B' 'C'
Index 0 1 2
Value 20 5 13
Upon removing 'B', becomes:
Return Item 'A' 'C'
Index 0 2
Value 20 13
Where 'Index' refers to both the key in the dictionary and the index in the list.
Seeing as the proper Index should be 1 and not 2, I need to run a check against all items in the dictionary to lower all higher values by 1.
I kind of know how to do this, but I think that's not even the proper solution.
I was wondering if anyone could look at this and tell me if they might have a better way to do it.
I'm also wondering if the proper solution ought to be blending the list and dictionary.
OR I think ordered dictionaries from collections might be the way to go. I would still probably need two of them, one for the string return, one for the odds weight.
OR I could make the list a set of ordered pairs, [string,weight].
I have a lot of solutions but I don't know which would be best in implementation.
Also, does anyone know how to run a clock test on functions? Experiments would be much smoother and decisions easier if I had a way to test time taken for a function.
March 15th, 2013, 08:36 PM

Your question exceeds my capacity to comprehend.
We're to ignore get_sample and get_chances.
Then you build a dictionary
test = {k:k for k in range(20)}
and a function to search for an unused integer key. These don't appear again in the post.
Incomprehensible notations "Whenever I try to remove an item from the set, like so:
Return Item 'A' 'B' 'C'
Index 0 1 2
Value 20 5 13"
and what set? Granted, dictionary keys behave as a set.
Timing and profiling: see click me.
[code]
Code tags[/code] are essential for python code and Makefiles!
March 16th, 2013, 02:45 PM

Thank you very much for the timing link.
You're right about the question being confusing, I've since fixed the entire thing. Here's the code, for anyone interested:
Code:
class odds_table(list):
def weights(self):
return list(item[1] for item in self)
def returns(self):
return list(item[0] for item in self)
def roll_odds(self,debug=False):
from random import randrange
cnt,cap,roll = int(),int(),randrange(0,sum(self.weights()))
while cnt<len(self):
cap += self.weights()[cnt]
if roll < cap:
if debug == False:
return self.returns()[cnt]
break
if debug == True:
return cnt
break
else:
cnt += 1
def get_sample(self,sampsize=1000):
results = list(0 for c in self)
for i in range(0,sampsize):
nValue = self.roll_odds(debug=True)
results[nValue] += 1
return zip(self.returns(),results)
def get_chances(self):
results = self.weights()
tot = float(sum(results))
for i in range(0,len(results)):
results[i] /= tot
return zip(self.returns(),results)
test = odds_table([['A',200],['B',200],['C',200],['D',200]])
EDIT: Minor enhancement to returns on get_chances and get_sample.