#!/usr/bin/env python '''lottery.py Playing lottery according to: www.lotto.be TO PLAY: $ python lottery.py DEPENDENCY combinations.py: http://www.clips.ua.ac.be/~vincent/software.html#combinations Copyright (c) 2011 CLiPS. All rights reserved. ''' __author__="Vincent Van Asch" __date__="22 November 2011" __version__="1.1" import os, sys, random, pickle, time try: import combinations except ImportError: print >>sys.stderr, 'ERROR: The script depends on combinations.py (http://www.clips.ua.ac.be/~vincent/software.html#combinations)' sys.exit(1) # CONSTANTS ###################################################################################################### # Price for playing once COST = 1 # PRICE MONEY for a correct subset # Based on the draw of 5 November 2011 PRICEMONEY={'2+':3, '3':5, '3+':10.3, '4':21.6, '4+':223.1, '5':865.8, '5+':27183.8, '6':947540} CURRENCY = 'EURO' ################################################################################################################## def loginfo(s): print >>sys.stderr, '%s: %s' %(time.strftime('%d/%m/%Y %H:%M:%S'), s) def getsubsets(numbers, minimum=3): '''Gets all subsets of the list of numbers. minimum: the minimal length for a subset ''' d={} if minimum < 1: raise ValueError('minimum should at least be 1') for i in range(minimum, len(numbers)+1): d[str(i)] = [set(x) for x in combinations.subsets(numbers, i)] return d class Lotto(object): def __init__(self, pool, length): '''pool: list of number to draw from length: length of the draw''' self.cache = {} self._factor = None self.length=length self.pool=pool self.cachefile = 'lottery.%d.%s.cache' %(length, '-'.join([str(p) for p in pool])) def cacheddraw(self): '''Get a draw from the pool''' if not self.cache: self.build() i = random.randint(0, self.factor) try: return self.cache[i] except KeyError: print self.factor, self.cache raise def uncacheddraw(self): '''uncached drawing''' out=set([]) while len(out) < self.length: out.add(random.choice(self.pool)) return out #draw = cacheddraw draw = uncacheddraw def build(self): if os.path.isfile(self.cachefile): loginfo('Reading cache...') with open(self.cachefile) as f: self.cache = pickle.load(f) loginfo('Reading done.') else: # all possibilities ntotal = combinations.ncombinations(len(self.pool), self.length) denom = int(ntotal/10.0) if not denom: denom=1 loginfo('Building cache with %d combinations...' %(ntotal)) count=0 for c in combinations.subsets(self.pool, self.length): self.cache[count] = set(c) count+=1 if not count%denom: loginfo('%d combinations computed...' %count) loginfo('Building done...') # write with open(self.cachefile, 'w') as f: pickle.dump(self.cache, f, pickle.HIGHEST_PROTOCOL) loginfo('Writing cache file done.') @property def factor(self): if self._factor is None: self._factor = len(self.cache)-1 return self._factor def play(numbers, times, reserve=None, pool=range(1,43)): '''Play a number of times on the lottery and returns the number of gains per subsetlength reserve: the reserve number pool: the pool of number to draw from ''' if not set(numbers).issubset(set(pool)): raise ValueError('The set of number must come from the pool: %s' %pool) if not len(numbers) == len(set(numbers)): raise ValueError('The set of numbers must consist of unique numbers') if reserve is not None: if reserve in numbers: raise ValueError('The reserve number should not be in numbers') if reserve not in pool: raise ValueError('Reserve number should be in pool: %s' %pool) length = len(numbers) # The lotto daemon lotto = Lotto(pool, length) # The winning combinations winners = getsubsets(numbers, minimum=2) # if reserve add if reserve is not None: for k, sets in winners.items(): if k!=str(length): key = k +'+' winners[key] = [] for s in sets: l = list(s) l.append(reserve) winners[key].append(set(l)) winners.pop('2') winners = winners.items() winners.sort(key=lambda x:x[0], reverse=True) #print 'WINNERS', winners gains={} denom = int(times/10.0) for i in range(times): # Get a random set of bingo = lotto.draw() #print 'BINGO', bingo win=False for kind, subsets in winners: if win:break for subset in subsets: if win: break if subset.issubset(bingo): gains[kind] = gains.get(kind, 0) + 1 #print subset win=True if not i%denom: loginfo('played %d times...' %(i)) #print 'GAINS', gains return gains def playwithmoney(numbers, stake, reserve=None): '''play''' # number of times to play times = int(stake/float(COST)) # playing print 'Playing %d times at %.2f %s per gamble' %(times, COST, CURRENCY) wins = play(numbers, times, reserve=reserve, pool=range(1,46)) wins = wins.items() wins.sort() # Report total=0 print 'PROFIT PER RANK:' for kind, c in wins: money = PRICEMONEY[kind]*c total+=money print ' '*11 + 'Rank %-2s: %9.2f %s (%d)' %(kind, money, CURRENCY, c) print print 'STAKE : % 9.2f %s' %(stake, CURRENCY) print 'TOTAL GROSS PROFIT: % 9.2f %s' %(total, CURRENCY) print '-'*55 print 'TOTAL NET PROFIT : % 9.2f %s' %(total-stake, CURRENCY) def getinput(): print '<<< Play lottery like on www.lotto.be >>>' numbers = raw_input('Give 6 numbers from the set of 1-45 that you want to play with (separated by whitespace):\n') numbers = [int(x) for x in numbers.split()] if len(numbers) != 6: raise ValueError('You should enter 6 number separated by whitespace. Example: 1 2 3 4 5 6') reserve = int(raw_input('Choose the extra number: ')) stake = int(raw_input('For how much money (%s) do you want to play?: ' %CURRENCY)) return numbers, reserve, stake if __name__ == '__main__': try: numbers, reserve, stake = getinput() playwithmoney(numbers, stake, reserve = reserve) except Exception, e: print 'ERROR:', e.message sys.exit(1)