text: import random
  import numpy as np
  
  #%%
  BANDIT_PROBABILITIES = [0.2, 0.55, 0.75]
  NUM_TRIALS = 100_000
  HYPERPARAMETER = 2
  
  class Bandit:
      def __init__(self, p):
          self.p = p
          self.mean = 0
          self.N = 0
  
      def pull(self):
          return random.random() < self.p
  
      def update(self, x):
          self.N = self.N + 1
          self.mean = (1 - 1.0/self.N)*self.mean + 1.0/self.N*x
  
      def ucb(self, N_total):
          return np.sqrt(HYPERPARAMETER*np.log(N_total)/self.N)
  
  
  
  def experiment():
      bandits = [Bandit(p) for p in BANDIT_PROBABILITIES]
      optimal_j = np.argmax(BANDIT_PROBABILITIES)
  
      num_times_explored = 0
      num_times_exploited = 0
      num_optimal = 0
      rewards = np.zeros(NUM_TRIALS)
  
      # Play each bandit once (Initialization)
      for j in range(len(bandits)):
          if j==optimal_j:
              num_optimal += 1
  
          x = bandits[j].pull()
          bandits[j].update(x)
          rewards[j] = x
  
  
      for i in range(len(bandits),NUM_TRIALS):
          j = np.argmax([b.mean+b.ucb(i) for b in bandits])
  
          if j==optimal_j:
              num_optimal += 1
  
          x = bandits[j].pull()
          bandits[j].update(x)
          rewards[i] = x
  
      j = np.argmax([b.mean for b in bandits])
      print("Best bandit: ", bandits[j].mean)
  
      print("Number times explored: ",num_times_explored)
      print("Number times exploited : ", num_times_exploited )
      print("Total reward earned: ", rewards.sum())
      print("Win rate: ", rewards.sum()/NUM_TRIALS)
      print("Selected optimal bandit: ", num_optimal)
  
      for i,b in enumerate(bandits):
          print(f"Mean of bandit {i}: ", b.mean)
  
  
  if __name__ == "__main__":
      experiment()
  