<jupyter_start><jupyter_text>Coin Toss Game This notebook simulates a coin tossing game where the player gets to pick a sequence of head/tail occurences as the endgame. A coin is tossed until the chosen sequence of head/tail occurs and the game ends. The objective is to find the sequence of head/tail occurences that will end the game with the least number of tosses. This is simulated by running a given number of coin toss games with the chosen endgame sequence. The average number of tosses required to win is computed and its distribution is plotted.<jupyter_code># Import useful packages
import sys
import numpy as np
from collections import deque
import ipywidgets as widgets
from IPython.display import display
from bokeh.io import show, output_notebook
from bokeh.plotting import figure 
output_notebook()
# Defines a class for the coin toss game
class CoinToss:
    
    # Initializing variables
    # Arguments: number of games to simulate, sequence of head/tail to end the game
    def __init__(self, number_of_games, endgame):
        self.numgames = number_of_games
        self.endgamelen = len(endgame)
        self.endgame = endgame
        self.reset()
        self.check_endgame()
        
    # Reset all the counters
    def reset(self):
        self.counter = np.zeros(self.numgames)
        
    # Check if endgame is correctly inputted    
    def check_endgame(self):
        if self.endgame.strip('HT'):
            sys.exit('ERROR: Endgame can only be a string containing Hs and/or Ts')
                
    # Run the coin toss game    
    def run(self):        
        # Initialize a queue for the current sequence
        curr_seq = deque('', self.endgamelen)
        endgame_reached = False
        # Start looping through number of games 
        for i in range(self.numgames):
            while not endgame_reached:
                # Update counter for current game
                self.counter[i] += 1
                # Check if coin toss resulted in a Head or a Tail
                if np.random.random_sample() < 0.5:
                    curr_seq.append('H')
                else:
                    curr_seq.append('T')
                # Check if the current sequence is equal to the endgame
                check = sum(cs == eg for (cs, eg) in zip(curr_seq, self.endgame))
                if check == self.endgamelen:
                    endgame_reached = True
                    curr_seq.clear()
            endgame_reached = False
        print('Average number of tosses to reach endgame = ', np.mean(self.counter))
        
    # Plot the distribution of number of tosses required to end the game
    def plot_counts(self):
        hist, edges = np.histogram(self.counter, density=False, bins=50)
        p = figure(plot_width=800, plot_height=300,
                   title='{} games with endgame {}'.format(self.numgames, self.endgame), 
                   tools='', background_fill_color='#fafafa')
        p.quad(top=hist, bottom=0, left=edges[:-1], right=edges[1:], fill_color="navy", 
               line_color="white", alpha=0.5)
        p.y_range.start = 0
        p.xaxis.axis_label = 'Number of tosses to reach endgame'
        p.yaxis.axis_label = 'counts'
        show(p)
# Start the coin tossing game simulation
def start_tossing(number_of_games=2000, endgame='HHH'):
    c = CoinToss(number_of_games, endgame)
    c.run()
    c.plot_counts()

# # Interactive control for entering number of games
# style = {'description_width': 'initial'}    
# number_of_games = widgets.IntSlider(description='Number of games', style=style, 
#                                     min=1, max=5000, step=1, value=200, continuous_update=False)
# # Interactive control for entering the endgame
# endgame=widgets.Text(value='HH', placeholder='Type endgame', 
#                      description='Endgame:', disabled=False)
# # Creating the interactive controls
# widget_ui = widgets.HBox([number_of_games, endgame])
# widget_out = widgets.interactive_output(start_tossing, 
#                                         {'number_of_games': number_of_games, 'endgame': endgame})
# Display the controls and output
display(widget_ui, widget_out)
start_tossing(2000, endgame='HHH')<jupyter_output>Average number of tosses to reach endgame =  13.9545
{'fraction_non_alphanumeric': 0.08185219831618334, 'fraction_numerical': 0.009354536950420954, 'mean_word_length': 2.5552784704904408, 'pattern_counts': {'":': 0, '<': 5, '<?xml version=': 0, '>': 4, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 3, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'chain_length': '1', 'dir': 'jupyter-structured-clean-dedup', 'id': '54421', 'license': 'MIT', 'n_tokens_mistral': 1256, 'n_tokens_neox': 1185, 'n_words': 403, 'path': 'CoinToss-sim.ipynb', 'repo_name': 'nishantsule/Coin-Toss-Game', 'size': '4276'}