## Pythonic Pick 4 Lottery

The Pythonic Pick 4 Lottery works like this: a customer picks four numbers in the range 1 through 9, inclusive, without duplicates. At a designated time, today's winning numbers are chosen randomly. Any customer who matches three of the four winning numbers wins a small amount and any customer who matches all four numbers win a larger amount. There is no reward for matching two or fewer of the winning numbers.

For example, suppose Michael picked the numbers [5, 7, 2, 9] (this is called the customer's entry) and today's winning numbers are [2, 8, 5, 3]. Then Michael only matched two numbers. The order of the numbers does not matter. Sarah, who picked [8, 5, 1, 2], has three matches. Gustav, who picked [3, 5, 8, 2], has matched all four numbers.

Furthermore, a customer may choose to play the superball option for an extra fee. The superball gives the customer a chance to increase their number of matches. The superball value is a single number in the same range (1 to 9) and is randomly determined at the same time the winning numbers are picked. If the superball value is in today's winning numbers, it will be substituted for one of the numbers in the customer's entry that didn't match, increasing their matches by one.

For example, suppose Tom picked [1, 4, 6, 7] and chose the superball option. If the winning numbers are [5, 3, 1, 6] and the superball is 3, then Tom's initial two matches

Increase to three because the superball is used as a substitute for one of his incorrect values. If the superball value is not in the winning numbers, or the customer already picked the superball value, it has no effect.

Program Behavior

Your program will randomly pick today's winning numbers and the superball value. It will then read a set of customer entries from a data file and determine how many of the entries winners are. Here's a sample output of the program:

Pythonic Pick 4 Lottery Results

Today's winning numbers: [1, 8, 6, 2]

Today's superball: 3

Number of entries: 947

Number of entries that used superball: 293

Number of entries that matched 3 numbers: 139

Number of entries that matched 4 numbers: 9

Your program should produce output consistent with the example above. Include blank lines in the output as shown.

In that example, the superball value (3) was not in the winning numbers, so no one benefitted by using the superball option.

The data file contains one customer's pick (one entry) per line. Which you can use to test your program. Here are the first few lines of that data file:

5 6 9 8

7 9 1 6 sb

8 4 3 5 sb

9 2 8 7

7 3 1 6

3 1 2 7 sb

7 9 3 5

7 3 9 1 sb

1 8 9 4

6 1 5 9

6 2 9 7

2 3 4 5

1 2 5 4

Each line in the data file contains the four numbers chosen by a particular customer separated by spaces. If the line has the characters sb at the end that means that customer has opted to play the superball.

You can assume the data in the data file is valid and formatted correctly: four numbers per line, no duplicates per entry, etc.

Here's another sample run of the program using the same data file:

Pythonic Pick 4 Lottery Results

Today's winning numbers: [5, 9, 8, 1]

Today's superball: 9

Number of entries: 947

Number of entries that used superball: 293

Number of entries that matched 3 numbers: 190

Number of entries that matched 4 numbers: 22

This time, the superball value is in the set of winning numbers, so many (but not all) customers who played the superball option had their number of matches increased by 1.

The numbers reported in the last two lines of the output include those that were Increased by the superball option. The count of three matches does not include those that matched four.

**Solution:**

```
import random
def pick_winning_numbers(lb: int, ub:int, n: int) -> list:
"""
This function returns a list of 4 non-repeated random numbers
:param lb: integer: lower bound of the range (inclusive)
:param ub: integer: upper bound of the range (inclusive)
:param n: integer: represents the number of random values to be returned
:return: list of 4 integers
"""
numbers = random.sample(range(lb, ub+1), n)
return numbers
def pick_superball(lb: int, ub: int) -> int:
"""
This function returns a random integer between the range defined by the variables 'ub' and 'lb'
:param lb: integer: lower bound of the range (inclusive)
:param ub: integer: upper bound of the range (inclusive)
:return:
"""
return random.randint(lb, ub)
def convert_list_to_integers(str_list: list) -> list:
"""
This function accepts a list of string representing valid integers, and returns a list
of these integers
:param str_list: list of strings
:return: list of integers
"""
list_int = [int(x) for x in str_list]
return list_int
def count_matches(winning_numbers: list, numbers: list) -> int:
"""
This function accepts two lists of integers, and count how many numbers from the second list
are in the first list
:param winning_numbers: list of integers
:param numbers: list of integers
:return: number of matched integers (int)
"""
matches = 0
for n in numbers:
if n in winning_numbers:
matches += 1
return matches
def main():
"""
Main function where all the functionality of the program is contained
:return: None
"""
# First, pick today's winning numbers
winning_numbers = pick_winning_numbers(1, 9, 4)
# Pick the superball number
sb = pick_superball(1, 9)
# Create helper variables to count the number of entries, number of entries that used superball,
# number of entries that matched 3 or 4 numbers, etc
n_entries = 0
n_superball_used = 0
n_matched_3 = 0
n_matched_4 = 0
# Now, read the file of entries
with open("entries.txt", 'r') as f:
# Read all lines
lines = f.readlines()
# Pick customer numbers
for i, line in enumerate(lines):
# trim and strip line
line = line.strip()
# Split line by space to convert it into a list
customer_numbers_str = line.split(" ")
# Check if this customer used superball
user_used_sb = False
if "sb" in customer_numbers_str:
# Remove the 'sb' from customer's numbers
user_used_sb = True
del customer_numbers_str[customer_numbers_str.index("sb")]
# Increment the counter for number of superball used
n_superball_used += 1
# Now, convert customer's numbers from string to int
customer_numbers = convert_list_to_integers(customer_numbers_str)
# Now, count matches
n = count_matches(winning_numbers, customer_numbers)
"""
Now, if the user used the 'sb' option:
* If the 'sb' number is in today's winning numbers, then add one additional match
to this user
* If 'sb' is not in today's winning numbers, then check if the user has this number
"""
if sb in winning_numbers:
n += 1
else:
if sb in customer_numbers and not sb in winning_numbers:
n += 1
# Increment the entries counter
n_entries += 1
# Check if the number of matches is 3 or 4
if n == 3:
n_matched_3 += 1
elif n == 4:
n_matched_4 += 1
# Now, display the results
print("Pythonic Pick 4 Lottery Results")
print("Today's winning numbers: [", end="")
for i, x in enumerate(winning_numbers):
print(x, end="")
if i < len(winning_numbers) -1:
print(", ", end="")
print("]")
print(f"Today's superball: {sb}")
print(f"Number of entries: {n_entries}")
print(f"Number of entries that used superball: {n_superball_used}")
print(f"Number of entries that matched 3 numbers: {n_matched_3}")
print(f"Number of entries that matched 4 numbers: {n_matched_4}")
if __name__ == '__main__':
main()
```