pythonmatplotlibcomparepython-itertoolsdice

How to compare results of dice rolls using variables and a rolling method


How do I code:

Player 1 always rolls dice A, player B always rolls dice B, compares result 5782 times? Also for A vs C, B vs C respectively.

It seems I can't manage to print the number of times dice A is larger, dice B is larger, and then, dice A and B have equal value.

The problem is that apparently, die_A_larger, die_B_larger and die_A_and_B_equal are undefined. I wonder why and how to fix the problem.

My code up to now:

import numpy as np

class die:
    def __init__(self, side_values=[1,2,3,4,5,6]):
        self.side_values = side_values

    def roll(self):
        i=np.random.randint(1,7)
        return self.sides[i]

#variables
A = die([3,3,3,3,3,6])
B = die([2,2,2,5,5,5])
C = die([1,4,4,4,4,4])
nmax = 5782

def count_number_of_wins(A, B):

    die_A_larger = 0
    die_B_larger = 0
    die_A_and_B_equal = 0

for n in range(nmax):
    if A > B:
        die_A_larger += 1
    elif A < B:
        die_B_larger +=1
    else:
        die_A_and_B_equal +=1
    
    return (die_A_larger, die_B_larger, die_A_and_B_equal)
print (count_number_of_wins(A, B))


def determine_best_die(dice):
    assert all(len(die) == 6 for die in dice)

    wins = [0] * len(dice)

    for i in range(len(dice)):
        for j in range(i+1, len(dice)):
            a, b = count_number_of_wins(dice[i], dice[j])
            if a > b:
                wins[i] = wins[i] + 1
            else:
                wins[j] = wins[j] + 1
    for i in wins:
        if (i == (len(dice)-1)):
            return wins.index(i)
    return -1

Solution

  • You need to vectorize, and iterate over the combinations you described in your question via itertools:

    import itertools
    from typing import Sequence
    
    import numpy as np
    
    
    class Die:
        def __init__(self, side_values: Sequence[int] = range(1, 7)) -> None:
            self.sides, counts = np.unique(side_values, return_counts=True)
            self.probabilities = counts / counts.sum()
    
        def roll(self, rand: np.random.Generator, n: int) -> np.ndarray:
            return rand.choice(a=self.sides, p=self.probabilities, size=n)
    
    
    def main() -> None:
        rand = np.random.default_rng(seed=0)
        a = Die((3, 3, 3, 3, 3, 6))
        b = Die((2, 2, 2, 5, 5, 5))
        c = Die((1, 4, 4, 4, 4, 4))
        nmax = 5_782
        names = 'abc'
    
        for (name_1, die_1), (name_2, die_2) in itertools.combinations(
            zip(names, (a, b, c)), r=2,
        ):
            rolls_1 = die_1.roll(rand, n=nmax)
            rolls_2 = die_2.roll(rand, n=nmax)
            print(f'{name_1} < {name_2}: {np.count_nonzero(rolls_1 < rolls_2)}')
            print(f'{name_1} = {name_2}: {np.count_nonzero(rolls_1 == rolls_2)}')
            print(f'{name_1} > {name_2}: {np.count_nonzero(rolls_1 > rolls_2)}')
    
    
    if __name__ == '__main__':
        main()
    
    a < b: 2409
    a = b: 0
    a > b: 3373
    a < c: 4029
    a = c: 0
    a > c: 1753
    b < c: 2402
    b = c: 0
    b > c: 3380