I wrote a rather inapt lotto simulator in Python, showing how long it would take to win the jackpot. I ran a similar application implemented in C, and it is so much faster. I know you can't compare the two, but I wonder anyway if there is room for performance improvement in my code. By the way, I converted my code using Cython into C, with no speed gain.
import random, locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
r_list = []
super_number = 0
my_super_number = 5
my_list = [[3, 4, 45, 7, 23, 33], [1, 2, 3, 4, 5, 6], [13, 43, 33, 15, 17, 18], [11, 14, 2, 17, 33, 13],
[1, 2, 14, 15, 25, 26], [23, 26, 37, 40, 43, 44]] # each list within corresponds to 1 games per drawing
match_list = []
iteration = 0
number_matches = 0
def fill_random_list():
for i in range(6):
# print (random.randint(1,49))
r_list.append(random.randint(1, 49))
def return_matches(lista, listb):
# print set(lista).intersection(listb)
return set(lista).intersection(listb)
def return_number_matches(l_matches):
if l_matches:
return len(l_matches)
def print_communicate(v_iteration, v_number_matches, v_guess, v_r_list, v_match_list, v_super_number,
v_my_super_number):
print (
'Drawing No.: ' + locale.format("%d", v_iteration, grouping=True))
print ('My guess: ' + str(sorted(v_guess)) + ', Super Number: ' + str(v_my_super_number))
print ('Result :' + str(sorted(v_r_list)) + ', Super Number: ' + str(v_super_number))
print ('My hits: ' + str(sorted(v_match_list)) + ', Amount of hits: ' + str(v_number_matches))
print ('Time to win: ' + str(calculate_time_to_win(v_iteration)) + ' Years')
print ('---------')
def calculate_time_to_win(v_drawings):
return (v_drawings/2)/365 # calculate years assuming participation in 2 lotteries a week
def draw_lottery(v_hits, v_with_super_number): #v_hits: number of hits until termination, v_with_super_number: include super number 'yes' or 'no'
global iteration, number_matches, r_list, match_list, my_list, super_number, my_super_number
jackpot = False
while not jackpot:
fill_random_list() # draw lottery results
super_number = random.randint(1, 9) # draw super number
for guess in my_list:
match_list = return_matches(r_list, guess)
number_matches = return_number_matches(match_list)
if number_matches == v_hits:
if v_with_super_number == 'yes':
if my_super_number == super_number:
print_communicate(iteration, number_matches, guess, r_list, match_list, super_number,
my_super_number)
jackpot = True
if v_with_super_number == 'no':
if my_super_number != super_number:
print_communicate(iteration, number_matches, guess, r_list, match_list, super_number,
my_super_number)
jackpot = True
match_list = []
number_matches = 0
if jackpot:
break
else:
iteration += 1
print 'Drawing No.: {0}'.format(iteration) + ' Years: {0}\r'.format(calculate_time_to_win(iteration)),
r_list = []
match_list = []
number_matches = 0
def iterate(number):
for i in enumerate(range(number), 1):
print('Round: ' + str(i[0]))
draw_lottery(6, 'no')
def main():
iterate(1)
print 'END!'
if __name__ == "__main__":
main()
1 Answer 1
Documentation
The PEP 8 style guide recommends adding docstrings for functions.
You should also add a docstring to the top of the code to summarize its purpose. For example:
"""
Lotto simulator, showing how long it would take to win the jackpot.
"""
Comments
Remove commented-out code to reduce clutter:
# print (random.randint(1,49))
# print set(lista).intersection(listb)
Simpler
The code would be simpler without this function:
def return_number_matches(l_matches):
It is only called once, and it really just executes len
on its input.
Since the i
variable is not used in the following loop:
for i in range(6):
the _
placeholder can be used:
for _ in range(6):
Portability
I realize this question was posted many years ago when Python version 2.x was prevalent, but now that it is deprecated, consider porting to 3.x.
For example, change:
print 'END!'
to:
print('END!')
This line:
print('Round: ' + str(i[0]))
is simpler with an f-string:
print(f'Round: {i[0]}')
If you want to control the precision of the output in the draw_lottery
function:
print(f'Drawing No.: {iteration} Years: {calculate_time_to_win(iteration):.4f}')
Tools
You could run code development tools to automatically find some style issues with your code.
ruff
shows:
E401 [*] Multiple imports on one line
|
| import random, locale
| ^^^^^^^^^^^^^^^^^^^^^ E401
|
| locale.setlocale(locale.LC_ALL, 'en_US.UTF-8')
|
= help: Split imports
randint
can generate many numbers at once. No need to call it many times. \$\endgroup\$fill_random_list
is already implemented inrandom
module, it's calledrandom.sample()
. \$\endgroup\$