#1
  1. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    80
    Rep Power
    2

    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.
  2. #2
  3. Contributing User
    Devshed Demi-God (4500 - 4999 posts)

    Join Date
    Aug 2011
    Posts
    4,966
    Rep Power
    481
    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!
  4. #3
  5. No Profile Picture
    Contributing User
    Devshed Newbie (0 - 499 posts)

    Join Date
    Dec 2012
    Posts
    80
    Rep Power
    2
    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.

IMN logo majestic logo threadwatch logo seochat tools logo