I am trying to write a script that simulates a dice game with unconventional dice. The objective of the game is to determine which dice is better based on repeated experiments where the larger number/roll wins. Here is working example I have so far:
from random import randint, seed
from datetime import datetime
import itertools as it
seed(datetime.now())
def find_the_best_dice(dices):
assert all(len(dice) == 6 for dice in dices)
for dice1, dice2 in it.combinations(dices, 2):
num_rounds = 100
num_dice1_wins = 0
num_dice2_wins = 0
for _ in range(num_rounds):
dice1_result = dice1[randint(0, 5)]
dice2_result = dice2[randint(0, 5)]
if dice1_result > dice2_result:
num_dice1_wins += 1
elif dice2_result > dice1_result:
num_dice2_wins += 1
return ("index of winning dice or -1 if tie")
find_the_best_dice(dices=[[1, 1, 6, 6, 8, 8], [2, 2,
4, 4, 9, 9], [3, 3, 5, 5, 7, 7]])
The issue I am facing is not knowing how to store the number of wins for more than 2 dice.
Usually, I would use a dictionary for something like this but since your representation of a dice is a list (unhashable) you can convert them into a frozenset or a tuple. I prefer a tuple since it preserves order and repetition (if any).
num_rounds = 100
dice_wins = {tuple(x):0 for x in dices}
for dice1, dice2 in it.combinations(dices, 2):
for _ in range(num_rounds):
dice1_result = dice1[randint(0, 5)]
dice2_result = dice2[randint(0, 5)]
if dice1_result > dice2_result:
dice_wins[tuple(dice1)] += 1
elif dice2_result > dice1_result:
dice_wins[tuple(dice2)] += 1
max_win = max(list(dice_wins.values()))
die_with_max_win = [dice for dice in dices if dice_wins[tuple(dice)] == max_win]
if len(die_with_max_win) == 1:
return die_with_max_win[0] # only dice with that many wins
else:
return -1 # more than one dice with max wins
Hope this helps!
If you’re talking about dice with the same amount of dots, a ‘best’ dice doesn’t exist. For example, if on average dice A wins from dice B and dice B from dice C, it’s still possible that on average dice C wins from dice A.
Related
I'm trying to figure out the average, the average of the average, of a series of d6 rolls' value, total of a series of d6 rolls, and average total of a series of d6 rolls. I keep getting numbers slightly off, and the variable I have ore both confusing me and I think some are redundant. If someone could help me clean up my code & stuff that would be helpful. I expanded upon Stefan B's code,
```python
from random import randint
numRolls = int(input("How many times will you roll the dice? "))
s = 0
for roll in range(numRolls):
d1 = randint(1, 6)
d2 = randint(1, 6)
s += d1 + d2
print("You rolled a", d1, "and a", d2)
print("Your total for all of the rolls is", s)
print("Your average for all of the rolls is", s / numRolls)
```
and added some of my own code, while not making it two dice rolls - my code:
```python
from random import randint
k = 0
x = 0
z = 0
v = 0
a = 0
j = 0
repeat = int(input("How many times would you like to repeat the following command? "))
numRolls = int(input("How many times will you roll the dice? "))
for roll in range(repeat):
s = 0
b = 0
for roll in range(numRolls):
d6 = randint(1, 6)
a += d6
s += d6
v = v + 1
y = s / numRolls
z += y
k += z
j = j + 1
print("Your total for all of the rolls is", s)
print("Your average for all of the rolls is ", s / numRolls)
rollsets = numRolls / 6
print("Your total average for the total of all rolls is ", z / v)
print("Your total average for all of the rolls is ", a / v)
#print(y)
#print(x)
#print(v)
#print(z)
#print(k)
```
I want to do kind of what it does in there, with the multiplying repeat and numRolls variables, and figure out the total and average of one of the small sets of rolls, and the average of both all rolls and the average of the totals.
I tried to use the letter variable to make better averages, but failed. I think I have redundant stuff, and I can't figure out how to measure the number of rolls and 'sets of rolls' for totals. Help please?
I recommend using more verbose variable names as I think that will help you keep track of what is going on. Conceptually, you want to keep a running total for all rolls of the dice.
from random import randint
number_of_dice = int(input("How many dice will you roll? "))
number_of_rounds = int(input("How many rounds will you roll the dice? "))
sum_all_rolls = 0
sum_all_round_averages = 0
print(f"Rolling {number_of_dice} dice, {number_of_rounds} times")
for round_index in range(number_of_rounds):
rolls = [randint(1, 6) for _ in range(number_of_dice)]
sum_this_round = sum(rolls)
average_this_round = sum_this_round / number_of_dice
print(f"Round {round_index + 1}. You rolled {rolls} and for a total of {sum_this_round} average {average_this_round}.")
sum_all_rolls += sum_this_round
sum_all_round_averages += average_this_round
print(f"Your total for all of the rolls is: {sum_all_rolls}")
print(f"Your average for all of the rolls is: {sum_all_rolls / (number_of_rounds * number_of_dice)}")
print(f"Your total for all round averages is: {sum_all_round_averages}")
print(f"Your average for all round averages is: {sum_all_round_averages/ number_of_rounds}")
This will give you a result like:
How many dice will you roll? 3
How many rounds will you roll the dice? 6
Rolling 3 dice, 6 times
Round 1. You rolled [3, 4, 4] and for a total of 11 average 3.6666666666666665.
Round 2. You rolled [6, 6, 1] and for a total of 13 average 4.333333333333333.
Round 3. You rolled [4, 3, 2] and for a total of 9 average 3.0.
Round 4. You rolled [3, 2, 1] and for a total of 6 average 2.0.
Round 5. You rolled [4, 5, 6] and for a total of 15 average 5.0.
Round 6. You rolled [5, 6, 3] and for a total of 14 average 4.666666666666667.
Your total for all of the rolls is: 68
Your average for all of the rolls is: 3.7777777777777777
Your total for all round averages is: 22.666666666666668
Your average for all round averages is: 3.777777777777778
I am new to Python and while my task is deemed correct, I know there is a more efficient way to write the code and am looking for advice.
My goal is to count the number of scores (between 1-6) of a dice roll and assign each number to a list. In this case I know the value of the dice roll 'N' - 1 will be the index at which it is added to the list but I am unsure as to how to go about writing it.
import random
dice = [0]*6
for roll in range(1001):
N = random.randint(1,6)
if N == 1:
dice[0] = dice[0] + 1
if N == 2:
dice[1] = dice[1] + 1
if N == 3:
dice[2] = dice[2] + 1
if N == 4:
dice[3] = dice[3] + 1
if N == 5:
dice[4] = dice[4] + 1
if N == 6:
dice[5] = dice[5] + 1
print(f' the number of times the dice rolled 1-6 is as follows {dice}')
You can use N-1 for the index of the list.
dice[N-1] += 1
When dealing with lists of random values, I recommend numpy:
import numpy as np
_, counts = np.unique(np.random.randint(1,7, 1000), return_counts=True)
Here you go:
dice = [0]*6
for roll in range(1001):
dice[random.randint(0, 5)] += 1
print(f' the number of times the dice rolled 1-6 is as follows {dice}')
The list is being indexed with N-1.
import random
a = random.sample(range(1, 1001), 6)
print(a)
This could brief a lot more what you are looking for
https://pynative.com/python-random-sample/
I am looking to have a dice game where a user is asked how many times the two dice are to be rolled. Based on pairs within the rolls the user is awarded money to their total.
The problem I have is that I am not able to compare the same positional values within the arrays using my current for loop.
The error I am getting is: The truth value of an array with more than one element is ambiguous. Use a.any() or a.all()
Here's the code:
import numpy as np
import random
def dice_game():
rolls = int(input("how many times would you like to roll the dice: "))
dice_value1 = np.random.randint( 1, 7, rolls)
print(dice_value1)
dice_value2 = np.random.randint( 1, 7, rolls)
print(dice_value2)
return dice_value1, dice_value2
result1, result2 = dice_game()
def dice_game_analysis(x,y):
total = 0
for i in range(len(x)):
if i == y:
if i == 1:
total = 0
if i <= 4:
total += x
if i >= 5:
total += 2*x
print(total)
dice_game_analysis(result1, result2)
Hi im trying to create a game where the computer generates 5 random numbers between 1 and 6. but my issue is i have created a list which will gain '1' in its respective section depending on what number comes up. e.g. if the computer generates 31534 the list needs to show [1,0,2,1,1,0] (because there was two 3's it fills 2 in the 3 slot) it only displays the 5 random numbers and nothing else
from random import randint
def rollDice():
dice = [str(randint(1, 6)) for _ in range(5)]
print(dice)
return dice
#-----------------------------------------------------------------
def countVals(dice):
totals = [0, 0, 0, 0, 0]
for x in dice:
if x == 1:
totals = totals[1] + 1
elif x == 2:
totals = totals[2] + 1
elif x == 3:
totals = totals[3] + 1
elif x == 4:
totals = totals[4] + 1
elif x == 5:
totals = totals[5] + 1
print(totals)
return totals
#------------------------------------------------------------------
rollDice()
countVals()
I believe your error lies when you increment the count of each number,
totals = totals[1] + 1
should be,
totals[1] = totals[1] + 1
Also depending on your application you may be able to simplify your code
def countVals(dice):
totals = [0, 0, 0, 0, 0]
for x in dice:
totals[x - 1] += 1
print (totals)
return totals
I think the problem is that the result returned by your rollDice function is a list of strings. The if - else statement in countVals then falls through cause for example '5' == 5 -> False. You could modify rollDice to return a list of int's instead (don't convert your ints to strings):
def rollDice():
dice = [randint(1, 6) for _ in range(5)]
print(dice)
return dice
If you absolutely want rollDice to return a list of strings you could convert the strings to ints using the int method in your countVals method. Example: int('5') -> 5, or just compare strings and not ints. x == '5'
Also make sure that you are saving your totals back to the right index in you totals list (in rollDice). You could do this a little more succinctly as follows: totals[1] += 1, for example:
def countVals(dice):
totals = [0, 0, 0, 0, 0, 0] #alternatively could be 'totals = [0]*6' :)
for value in dice:
totals[value - 1] += 1
print(totals)
return totals
(assuming rollDice has been modified to return a list of integers)
You should be able to call the methods as follows totals = countVals(rollDice()) to get your list of totals.
You could try the following:
dice = rollDice()
countVals(dice)
Also you want to fix the indentation of the print and return statements in countVals(). Currently, they only trigger if x==5. And as Salvador Dali mentions, either remove str from rollDice() or change the comparisons in countVals() to x == '1', etc.
Edit:
Here is how you may want to write your script:
def rollDice():
dice = [randint(1, 6) for _ in range(5)]
print(dice)
return dice
def countVals(dice):
totals = [0, 0, 0, 0, 0]
for x in dice:
# x can be, 1-5. Index of totals can be 0-4.
totals[x-1] += 1
print(totals)
return totals
dice = rollDice()
countVals(dice)
Hey I have a class exercise that I'm stuck with and would appreciate any help. The program is supposed to random select a number between 1-5 and loop until all numbers are picked. Then it's supposed to repeat about 100 times to give an average of how many picks it takes to get all five numbers. I know how to use random.int, just not sure how to write a loop where it breaks when all 5 numbers are picked. Any sort of help would be great. Thank you
I would suggest you to use a Set. Each time a value between 1-5 is reached, put it in the your set, then when the size of the set is 5, break the loop.
This will do it:
from random import randint
a = []
for _ in range(100):
b = 0
c = set()
while len(c) < 5:
c.add(randint(1, 5))
b += 1
a.append(b)
d = round(sum(a)/len(a))
print("{}\nAverage loops: {}".format(c, d))
Documented version:
# Import the `randint` function from `random`.
from random import randint
# This will hold the results that will later be used to calculate the average.
a = []
# This loops 100 times (to get data for a calculation of the average).
for _ in range(100):
# This will be the number of times the while-loop loops.
b = 0
# This is a set to hold the choices of `random.randint`.
# When it reaches 5 items, all numbers from 1-5 have been found.
c = set()
# Loop while the length of the set is less than 5.
while len(c) < 5:
# Add a new random number to the set,
# If the number is already there, nothing happens.
c.add(randint(1, 5))
# Record a completed iteration of the while-loop.
b += 1
# Add the number of while-loop loops to `a`.
a.append(b)
# The average is calculated by dividing the sum of `a` by the length of `a`.
# It is then rounded to the nearest integer.
d = round(sum(a)/len(a))
# Print the results.
print("{}\nAverage loops: {}".format(c, d))
Sample output:
{1, 2, 3, 4, 5}
Average loops: 12
{1, 2, 3, 4, 5}
Average loops: 10
{1, 2, 3, 4, 5}
Average loops: 9
I would just do a while-loop that generates a random number between 1-5 until it gets the first number, t, logging the number of tries it took., logging the number of tries it took.hen do that with the next number, and when you're done find the average of how many tries it took.
Example:
total = 0
for i in range(100):
for n in range(1,6):
generatedNum = 0
while generatedNum != n:
#generate random number
total += 1
print (total/100)
Here is yet another way we may use:
import random
total = {1:0,2:0,3:0,4:0,5:0}
for k in xrange(100): #outter loop
trial = {}
n = 0 #counter
while n<5:
sample = random.randint(1,5) #sample
try:
trial[sample] += 1
except:
n += 1
trial[sample] = 1
for i in xrange(1,6): #accumulate the results
total[i] += trial[i]
which results in:
>>> total
{1: 221, 2: 255, 3: 246, 4: 213, 5: 243}