<SYSTEM_TASK:>
Given the following text description, write Python code to implement the functionality described below step by step
<END_TASK>
<USER_TASK:>
Description:
 What are the odds that you'll lose money on the lottery?
The code below finds the approximate odds that, after a certain number of tickets, you'll have lost money (overall) on the lottery. The code should be adaptable to any lottery, but the specific examples below focus on two popular lottery games in New York state
Step1:  The Lottery class takes four parameters
Step2:  Mega Millions
Offical odds
Durango Bill details
Step3:  100,000 player simulations — Mega Millions
Step4:  1 million 50-ticket simulations — Mega Millions
Step5:  How much should you expect to lose playing Mega Millions?
The code below simulates the net profit/loss of the 1,000,000 simulated players who each bought one $1 Mega Millions ticket per week, for 50 weeks
Step6:  Powerball
Offical odds
Durango Bill details
Step7:  100,000 player simulations — Powerball
Step8:  How much should you expect to lose playing Powerball?
The code below simulates the net profit/loss of 1,000,000 players who each buy one $2 Powerball ticket per week, for 50 weeks
<ASSISTANT_TASK:>
Python Code:
import random
import pandas as pd
import matplotlib as mpl
import seaborn as sb
%matplotlib inline
Explanation: What are the odds that you'll lose money on the lottery?
The code below finds the approximate odds that, after a certain number of tickets, you'll have lost money (overall) on the lottery. The code should be adaptable to any lottery, but the specific examples below focus on two popular lottery games in New York state: Mega Millions and Powerball.
The per-play odds come from the New York Lottery's official website and Durango Bill's detailed explanations.
The jackpots depends on the day you're playing. But, for the sake of this analysis, the particular amount doesn't matter. But just to be safe, the analysis assumes an arbitrarily high amount of $1 billion. 
Additionally, some prizes may be split among multiple winners. ("In some cases, the fixed prizes may be paid on a pari-mutuel basis and will be lower than these published amounts," the fine print says.) So, if anything, the simulated results below may understate the actual odds of becoming long-term net loser.
End of explanation
class LotterySimulation(object):
    def __init__(self, lottery, n_tickets, n_players):
        self.lottery = lottery
        self.n_tickets = n_tickets
        self.n_players = n_players
        self.winnings = [ sum(lottery.play_x_times(n_tickets))
            for _ in range(n_players) ]
    
    @property
    def net(self):
        outlay = self.n_tickets * self.lottery.ticket_cost
        return [ win - outlay
            for win in self.winnings ]
    
    @property
    def net_loss_proportion(self):
        return float(sum(n < 0 for n in self.net)) / self.n_players
class Lottery(object):
    def __init__(self, name, ticket_cost, total_combinations, winning_combinations):
        self.name = name
        self.ticket_cost = ticket_cost
        self.total_combinations = total_combinations
        self.winning_combinations = winning_combinations
        self.cutoffs = self.construct_cutoffs()
    
    def construct_cutoffs(self):
        winning_cutoffs = []
        cumulative = 0
        for n, winnings in self.winning_combinations:
            cumulative += n
            winning_cutoffs.append((cumulative, winnings))
        return winning_cutoffs
    
    def get_odds_of_winning_anything(self):
        return float(self.cutoffs[-1][0]) / self.total_combinations
    
    def play_once(self):
        rand = random.randint(1, self.total_combinations)
        for i, winnings in self.cutoffs:
            if rand <= i:
                return winnings
        return 0
    
    def play_x_times(self, x):
        return [ self.play_once() for n in range(x) ]
    
    def simulate(self, n_tickets, n_players):
        return LotterySimulation(self, n_tickets, n_players)
Explanation: The Lottery class takes four parameters:
The lottery name.
The cost of a ticket.
The total number of possible combinations.
A list of tuples — one for each prize level. Each of these tuples takes the form, (possible_combinations, dollars_won).
End of explanation
mega_millions = Lottery("Mega Millions", 1, 258890850, [
    (1, 1000000000), # Hypothetical $1 billion jackpot
    (14, 1000000), # $1 million
    (350, 5000),
    (4900, 500),
    (24150, 50),
    (338100, 5),
    (547400, 5),
    (4584475, 2),
    (12103014, 1)
])
print("On a single Mega Millions ticket, "
      "your odds of winning anything is "
      "approximately {0:.5f}%, or 1 in {1:.2f}."\
    .format(
        mega_millions.get_odds_of_winning_anything() * 100,
        1.0 / mega_millions.get_odds_of_winning_anything()
    ))
Explanation: Mega Millions
Offical odds
Durango Bill details
End of explanation
n_simulations = 1000 * 100
for n_tickets in (10, 50, 100):
    sim = mega_millions.simulate(n_tickets, n_simulations)
    print(
        "Among 100k simulated players who each bought {0} tickets, "
        "{1:.3f}% lost money overall.".format(
            n_tickets, 
            sim.net_loss_proportion * 100
        )
     )
Explanation: 100,000 player simulations — Mega Millions
End of explanation
mm_1_million = mega_millions.simulate(50, 1000 * 1000)
print(
    "Among 1 million simulated players who each bought {0} tickets, "
    "{1:.3f}% lost money overall.".format(
        n_tickets,
        mm_1_million.net_loss_proportion * 100.0
   )
)
Explanation: 1 million 50-ticket simulations — Mega Millions
End of explanation
def plot_net(sim):
    count = sim.n_tickets
    stemmed = pd.Series(sim.net).apply(lambda x: min(count, x))
    ax = stemmed.hist(bins=range(-count * sim.lottery.ticket_cost, count+1, 1),
        figsize=(12, 6),
        normed=True)
    ax.set_title("Net Profit/Loss After {0} Tickets — {1}"\
        .format(count, sim.lottery.name), fontsize=18, fontweight="bold")
    ax.set_ylabel("Percentage of Simulations", fontsize=14)
    ax.set_yticks(list(pd.np.arange(0, ax.get_ylim()[-1] + 0.01, 0.01)))
    ax.set_yticklabels([ "{0:.0f}%".format(y * 100) 
        for y in ax.get_yticks() ], fontsize=12)
    ax.set_xlim((-count * sim.lottery.ticket_cost, count))
    tick_spacing = 10 if (count * sim.lottery.ticket_cost <= 100) else 20
    ax.set_xticks(range(-count * sim.lottery.ticket_cost, count+1, tick_spacing))
    ax.set_xticklabels([ ("${0}" if x >= 0 else "-${0}").format(abs(x)) + ("+" if x == count else "")
        for x in ax.get_xticks() ], fontsize=12)
    mpl.pyplot.setp(ax.patches[:count * sim.lottery.ticket_cost - 1], facecolor="darkred")
    mpl.pyplot.axvline(0, color="black", linestyle="dashed")
    return ax
plot_net(mm_1_million);
Explanation: How much should you expect to lose playing Mega Millions?
The code below simulates the net profit/loss of the 1,000,000 simulated players who each bought one $1 Mega Millions ticket per week, for 50 weeks:
End of explanation
powerball = Lottery("Powerball", 2, 292201338, [
    (1, 1000000000),
    (25, 1000000),
    (320, 50000),
    (8000, 100),
    (20160, 100),
    (504000, 7),
    (416640, 7),
    (3176880, 4),
    (7624512, 4)
])
print("On a single Powerball ticket, "
      "your odds of winning anything is "
      "approximately {0:.5f}%, or 1 in {1:.2f}."\
    .format(
        powerball.get_odds_of_winning_anything() * 100,
        1.0 / powerball.get_odds_of_winning_anything()
    ))
Explanation: Powerball
Offical odds
Durango Bill details
End of explanation
n_simulations = 1000 * 100
for n_tickets in (10, 50, 100):
    sim = powerball.simulate(n_tickets, n_simulations)
    print(
        "Among 100k simulated players who each bought {0} tickets, "
        "{1:.3f}% lost money overall.".format(
            n_tickets, 
            sim.net_loss_proportion * 100
        )
     )
pb_1_million = powerball.simulate(50, 1000 * 1000)
print(
    "Among 1 million simulated players who each bought {0} tickets, "
    "{1:.3f}% lost money overall.".format(
        n_tickets,
        pb_1_million.net_loss_proportion * 100.0
   )
)
Explanation: 100,000 player simulations — Powerball
End of explanation
plot_net(pb_1_million);
Explanation: How much should you expect to lose playing Powerball?
The code below simulates the net profit/loss of 1,000,000 players who each buy one $2 Powerball ticket per week, for 50 weeks:
End of explanation
<END_TASK>