Simulating a competition python

**The parts I need some assistance with are:

  1. A way to implement the probability for a foul into the code (added Omar’s input here and it works)
  2. Print the results nicely instead of how it is now (prints out name and jump for each simulation so when I do 100 simulations there are too many outputs
  3. Top 10 list – further clarification in comments.
  4. With Omar’s input the histogram has been made, now I just have to import it to a pdf file.
import matplotlib.pyplot as plt
import random
filename=input('Which file do you want to collect the competitors from?: ') 
class Player():
    
    win_length = []
    def __init__(self,name,m,s,fp):
        
        self.name=name
        self.m=m
        self.s=s
        self.fp=fp
        self.best= 0
        self.wins = 0
 
 
    def __str__(self):
 
         playerwins = self.name + ' ' + str(self.wins) + ' ' + 'Wins'
 
         return playerwins
 
 
        
    
    def jump(self):
 
        result=[]
        foul = [1] * int(10 * self.fp) + [0] * int(10 * (1 - self.fp))
 
        for i in range(0,6):
            if random.choice(foul) == 0:
                jump  = 3 * (random.normalvariate(self.m,self.s))
                result.append(jump)
            
 
        self.best = max(result) 
        
        return self.best
 
 

class Arena():
    
    def main(self):
        print ("Welcome to the competition, please enter how many simulations you would like to run!")
        self.readplayersfromfile()
        self.contest()
        self.sortStats()
        self.stats()
    
    
    def readplayersfromfile(self):
 
        infil = open(filename,'r')
 
        line = infil.readline()
 
        self.players = []
 
        while line != '':
 
            line = line.rstrip('n')
 
            parts = line.split()
 
            name = parts[0]
 
            m = float(parts[2])
 
            s = float(parts[3])
            
            fp = float(parts[4]) #added fp down here since it has to check the probability from the file(?)
            
            tmp = Player(name, m, s, fp)
 
            self.players.append(tmp)
 
            line = infil.readline()
 
        return self.players
 
    
    
    def contest(self):
 
        while True:
 
            try:
 
                x = int(input("How many competitions?"))
                break
 
            except ValueError:
                print ("Only numbers please!")
        
        
 
        for rounds in range(0,x):
 
            for player in self.players:
                player.jump()
 
 
            bestjump = max(self.players, key = lambda jump: jump.best)
            Player.win_length.append(bestjump.best)
            bestjump.wins += 1
 
            print ("Winner: ", bestjump.name, "nResult: ", bestjump.best)
 
        plt.hist(Player.win_length, bins=5, color='y', ec='black')
        plt.title('Distribution of Winning lengths')
        plt.xlabel('Jump lengths')
        plt.show()
 
 
    
    
    def sortStats(self):
 
        return self.players.sort(key=lambda Player:Player.wins, reverse=True)
 
 
 
   
 
    def stats(self):
 
        for wins in range(len(self.players)):
 
            print (self.players[wins])
            
                
    
        
        
            
        
 
 
a=Arena()
a.main()
    Example Run
    Which file do you want to collect the competitors from? test.txt
    Welcome to the competition, please enter how many simulations you would like to run!
    
    How many competitions? 100
    
    RESULTS
    Carl Phelps 16.45
    Charlie Jumper 17.89
    Michael Finks 17.59
    
    TOP 10
    Carl Phelps 19.5
    Charlie Jumper 18.67
    Michael Finks 18.31
    and so on
    
    STATISTICS
    Carl Phelps 43 Wins
    Charlie Jumper 37 Wins
    Michael Finks 20 Wins
    Histogram can be seen in hist.pdf!

If any clarification is required please comment.

Answer

class Player:

    def __init__(self, name, m, s, fp):  # fp => probability of foul
        self.name = name
        self.m = m
        self.s = s
        self.fp = fp
        self.best = 0
        self.wins = 0

    def jump(self):
        resultat = [0]  # No need to have "resultat" as an instance attribute
        foul = [1] * int(10 * self.fp) + [0] * int(10 * (1 - self.fp))  # probability space depending on "fp"

        for i in range(6):
            if random.choice(foul) == 0:
                jump = 3 * (random.normalvariate(self.m, self.s))
                resultat.append(jump)

        self.best = max(resultat)

        return self.best
  1. I guess you could just move the print statement outside of the loop such that you only print the last run/simulation, if that’s what you want (or do you want to print the average of all the jumps?).

3 + 4. Create a class object attribute above __init__ as win_length = {}:

class Player:
    win_length = {}  # Dictionary of winners
    def __init__(self, name, m, s, fp):  # fp => probability of foul
        self.name = name
        self.m = m
        self.s = s
        self.fp = fp
        self.best = 0
        self.wins = 0

Now under your readplayersfromfile() method, add this command such that you insert every player name as a key in the dictionary:

        while line != '':
 
            line = line.rstrip('n')
 
            parts = line.split()
 
            name = parts[0]
            Player.win_length[name] = []

Finally, under your contest() method:

        for rounds in range(0, x):

            for player in self.players:
                player.jump()

            bestjump = max(self.players, key=lambda jump: jump.best)
            Player.win_length[bestjump.name].append(bestjump.best)  # Add the best jump to list of winning player
            bestjump.wins += 1

        jump_list = []  # Contains jumps of all runs/simulations (for histogram)
        for lis in Player.win_length.values():
            jump_list += lis

        top_list = sorted(jump_list, reverse=True)[:10]
        for i in top_list:
            for k in Player.win_length:
                if i in Player.win_length[k]:
                    print(f"{k}: {i:.4}")
 
        plt.hist(jump_list, color='y', ec='black')
        plt.title('Distribution of Winning lengths')
        plt.xlabel('Jump lengths')
        plt.show()

Leave a Reply

Your email address will not be published. Required fields are marked *