import math
import numpy as np
import pandas as pd
import random
import seaborn as sns
x = np.array([[3/8],
              [1/16],
              [9/16]])
y = np.array([[1, 0, 3/8],
              [0, 1, 1/16],
              [0, 0, 9/16]])
a = y@x
for i in range(10000) :
    a = y@a
a
array([[8.57142857e-001],
       [1.42857143e-001],
       [4.94065646e-324]])
x = np.array([[24/256],
              [40/256],
              [144/256],
              [48/256]])
y = np.array([[1, 0, 1/8, 3/32],
              [0, 1, 1/8, 5/32],
              [0, 0, 5/8, 9/16],
              [0, 0, 1/8, 3/16]])
a = y@x
for i in range(10000) :
    a = y@a
    
a
array([[4.5e-001],
       [5.5e-001],
       [4.9e-324],
       [0.0e+000]])
def monteCarlo(rolls):
    wins = 0
    losses = 0
    
    #Roll 4 dice.
    for roll in range(rolls):
        
        #Inititate.
        dice = [random.randrange(1, 5, 1),
                random.randrange(1, 5, 1),
                random.randrange(1, 5, 1),
                random.randrange(1, 5, 1)]
        
        #Place in bins until all are unique or all are duplicate.
        outcome = updateDice(dice)
    
        if outcome == "win":
            wins += 1
        else:
            losses += 1
    return(wins, losses)
#Returns "win" or "loss" depending on if all dice are in unique or all dice are duplicates
def updateDice(dice):
    
    #Frequency of dice numbers.
    freq = {}
    for r in dice :
        if r in freq.keys():
            freq[r] += 1
        else :
            freq[r] = 1
    
    #Place dice in unique and duplicate bins.
    
    unique = []
    duplicate = []
    
    for f in freq:
        if freq[f] == 1:
            unique.append(f)
        elif freq[f] > 1:
            for i in range(freq[f]):
                duplicate.append(f)
    
    
    #All are unique.            
    if len(unique) == 4:
        return("win")
    
    #All are duplicate.            
    elif len(duplicate) == 4:
        return("loss")
    
    
    #Reroll duplicates.
    else :
        newdice = unique.copy()
        for d in duplicate:
            newdice.append(random.randrange(1, 5, 1))
        return(updateDice(newdice))
monteCarlo(10000000)
(4496805, 5503195)