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)
Related
I'm trying to write some Python code which will calculate the probability of the sum of n rolled m sided fair dice of being a certain value or greater. The inputs are the sum of all dice rolls, the number of rolls made and the number of sides on the dice. The output is the percentage chance of the sum of dice rolls being that value or greater.
I'm basing my calculations on the equations I found in this paper and scaling it for any sided die being rolled any number of times: https://digitalscholarship.unlv.edu/cgi/viewcontent.cgi?article=1025&context=grrj
I've made some code which "works" but is incredibly slow for when the dice has lots of faces so is only useful for dice with 20 faces or less.
import numpy as np
def probability_calculator(roll_total, num_of_rolls, dice_faces):
if num_of_rolls == 0:
probability = 100
elif num_of_rolls == 1:
probability = (dice_faces + 1 - roll_total) * 100/dice_faces
else:
inverse = (dice_faces ** num_of_rolls) ** -1
side_list = np.linspace(1, dice_faces, dice_faces)
expanded_list = np.zeros(dice_faces * num_of_rolls)
stacked_side_list = side_list
for i in range(num_of_rolls - 1):
stacked_side_list = np.vstack((stacked_side_list, side_list))
index_array = np.zeros(num_of_rolls, dtype=int)
while True:
value = 0
for i in range(num_of_rolls):
value = value + stacked_side_list[i][index_array[i]]
expanded_list[int(value) - 1] += 1
if sum(index_array) == (dice_faces - 1) * num_of_rolls:
break
for i in range(num_of_rolls):
if index_array[i] == dice_faces - 1:
index_array[i] = 0
else:
index_array[i] += 1
break
probability = inverse * sum(expanded_list[roll_total - 1:]) * 100
return probability
As you can see, this is incredibly inefficient code which if you were to roll only four 100 sided die you would have to iterate through the while loop 100^4 = 100,000,000 times.....
I am pretty certain there is some mathematical equation which can simplify this code and make it run many orders of magnitude faster but maths isn't my favourite subject and I don't know of any equation or Python function that could help.
Had a quick look at the paper and got scared by the formulas. Implemented a presumably different way simply counting how often the different totals can be reached:
from functools import lru_cache
#lru_cache(None)
def sum_freq(total, rolls, faces):
if not rolls:
return not total
return sum(sum_freq(total - die, rolls - 1, faces)
for die in range(1, faces + 1))
def probability_calculator(roll_total, num_of_rolls, dice_faces):
return sum_freq(roll_total, num_of_rolls, dice_faces) / dice_faces**num_of_rolls
Demo for your "four 100 sided die":
prob_314 = probability_calculator(314, 4, 100)
prob_any = sum(probability_calculator(total, 4, 100)
for total in range(1, 401))
print(f'{prob_314:%}')
print(f'{prob_any:%}')
Output:
0.113564%
100.000000%
Output for ten 100 sided dice:
0.050065%
100.000000%
Output for 42 such 100 sided dice:
0.000000%
100.000000%
Try it online!
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/
My teacher wants me to find the median of 10 inputs from the user by using iterations.
This is how I used iterations to find the sum, number of odd numbers, the max, and the number of prime numbers. But I'm stuck on finding the median.
def Main(): #main function
sum=0
odd=0
temp=0
prime=0
median=0
for i in range(10):
x=float(input("Please enter a number")) #ask user for input 10 times
sum=sum+x #adds all inputs together
if x%2!=0: #all even numbers are divisible by 2
odd=odd+1
if x>=temp: #update temp with current largest input
temp=x
for p in range (2,int(math.sqrt(x))+1):#find prime numbers
if x>=2 and x%p==0: prime=prime+1
import math
def Main(): #main function
sum=0
odd=0
temp=0
prime=0
median=0
my_list =[]
for i in range(10):
x=float(input("Please enter a number: ")) #ask user for input 10 times
sum=sum+x #adds all inputs together
if x%2!=0: #all even numbers are divisible by 2
odd=odd+1
if x>=temp: #update temp with current largest input
temp=x
for p in range (2,int(math.sqrt(x))+1):#find prime numbers
if x>=2 and x%p==0: prime=prime+1
my_list.append(x)
my_list.sort()
size =len(my_list)
if size == 1:
median = my_list[0]
elif size % 2 == 0:
size = int(size/2)
median=(my_list[size-1]+my_list[size])/2
else:
median = my_list[int(size / 2)]
print("sum is ", sum, ",odd is ", odd, ",temp is ", temp, ",prime is ", prime, "median is ", median)
Main()
First of all, as a user pointed out in a comment to your question, your method to determine prime numbers is not correct. You only should increase that counter after all factors have been checked, not after each one.
There are a few questions on StackOverflow that show how to calculate primes in python; here is a slightly improved version of your code with that error fixed (and some style improvement suggestions):
def main():
sum = 0
counter_odd = 0
max_num = None
min_num = None
counter_prime = 0
median = 0
for i in range(10):
x = float(input("Please enter a number"))
sum += x
if x % 2 != 0:
counter_odd += 1
if max_num is None or max_num < x:
max_num = x
if min_num is None or min_num > x:
min_num = x
if x == 0 or x == 1:
counter_prime += 1
elif x > 1:
if not any(x % d == 0 for d in range(2, int(math.sqrt(x)) + 1)):
counter_prime += 1
As to your main question: there are several questions on SO about finding medians in unsorted lists (that would be very similar to searching for medians without having the whole list at the beginning). Maybe search for that without the Python tag, so you get to see some algorithms without tying to a specific language.
For example, in this question you can find the suggestion to use the median of medians approach (Wikipedia).
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.
I am VERY new to Python and I have to create a game that simulates flipping a coin and ask the user to enter the number of times that a coin should be tossed. Based on that response the program has to choose a random number that is either 0 or 1 (and decide which represents “heads” and which represents “tails”) for that specified number of times. Count the number of “heads” and the number of “tails” produced, and present the following information to the user: a list consisting of the simulated coin tosses, and a summary of the number of heads and the number of tails produced. For example, if a user enters 5, the coin toss simulation may result in [‘heads’, ‘tails’, ‘tails’, ‘heads’, ‘heads’]. The program should print something like the following: “ [‘heads’, ‘tails’, ‘tails’, ‘heads’, ‘heads’]
This is what I have so far, and it isn't working at all...
import random
def coinToss():
number = input("Number of times to flip coin: ")
recordList = []
heads = 0
tails = 0
flip = random.randint(0, 1)
if (flip == 0):
print("Heads")
recordList.append("Heads")
else:
print("Tails")
recordList.append("Tails")
print(str(recordList))
print(str(recordList.count("Heads")) + str(recordList.count("Tails")))
You need a loop to do this. I suggest a for loop:
import random
def coinToss():
number = input("Number of times to flip coin: ")
recordList = []
heads = 0
tails = 0
for amount in range(number):
flip = random.randint(0, 1)
if (flip == 0):
print("Heads")
recordList.append("Heads")
else:
print("Tails")
recordList.append("Tails")
print(str(recordList))
print(str(recordList.count("Heads")) + str(recordList.count("Tails")))
I suggest you read this on for loops.
Also, you could pass number as a parameter to the function:
import random
def coinToss(number):
recordList, heads, tails = [], 0, 0 # multiple assignment
for i in range(number): # do this 'number' amount of times
flip = random.randint(0, 1)
if (flip == 0):
print("Heads")
recordList.append("Heads")
else:
print("Tails")
recordList.append("Tails")
print(str(recordList))
print(str(recordList.count("Heads")) + str(recordList.count("Tails")))
Then, you need to call the function in the end: coinToss().
You are nearly there:
1) You need to call the function:
coinToss()
2) You need to set up a loop to call random.randint() repeatedly.
I'd go with something along the lines of:
from random import randint
num = input('Number of times to flip coin: ')
flips = [randint(0,1) for r in range(num)]
results = []
for object in flips:
if object == 0:
results.append('Heads')
elif object == 1:
results.append('Tails')
print results
This is possibly more pythonic, although not everyone likes list comprehensions.
import random
def tossCoin(numFlips):
flips= ['Heads' if x==1 else 'Tails' for x in [random.randint(0,1) for x in range(numflips)]]
heads=sum([x=='Heads' for x in flips])
tails=numFlips-heads
import random
import time
flips = 0
heads = "Heads"
tails = "Tails"
heads_and_tails = [(heads),
(tails)]
while input("Do you want to coin flip? [y|n]") == 'y':
print(random.choice(heads_and_tails))
time.sleep(.5)
flips += 1
else:
print("You flipped the coin",flips,"times")
print("Good bye")
You could try this, i have it so it asks you if you want to flip the coin then when you say no or n it tells you how many times you flipped the coin. (this is in python 3.5)
Create a list with two elements head and tail, and use choice() from random to get the coin flip result. To get the count of how many times head or tail came, append the count to a list and then use Counter(list_name) from collections. Use uin() to call
##coin flip
import random
import collections
def tos():
a=['head','tail']
return(random.choice(a))
def uin():
y=[]
x=input("how many times you want to flip the coin: ")
for i in range(int(x)):
y.append(tos())
print(collections.Counter(y))
Instead of all that, you can do like this:
import random
options = ['Heads' , 'Tails']
number = int(input('no.of times to flip a coin : ')
for amount in range(number):
heads_or_tails = random.choice(options)
print(f" it's {heads_or_tails}")
print()
print('end')
I did it like this. Probably not the best and most efficient way, but hey now you have different options to choose from. I did the loop 10000 times because that was stated in the exercise.
#Coinflip program
import random
numberOfStreaks = 0
emptyArray = []
for experimentNumber in range(100):
#Code here that creates a list of 100 heads or tails values
headsCount = 0
tailsCount = 0
#print(experimentNumber)
for i in range(100):
if random.randint(0, 1) == 0:
emptyArray.append('H')
headsCount +=1
else:
emptyArray.append('T')
tailsCount += 1
#Code here that checks if the list contains a streak of either heads or tails of 6 in a row
heads = 0
tails = 0
headsStreakOfSix = 0
tailsStreakofSix = 0
for i in emptyArray:
if i == 'H':
heads +=1
tails = 0
if heads == 6:
headsStreakOfSix += 1
numberOfStreaks +=1
if i == 'T':
tails +=1
heads = 0
if tails == 6:
tailsStreakofSix += 1
numberOfStreaks +=1
#print('\n' + str(headsStreakOfSix))
#print('\n' + str(tailsStreakofSix))
#print('\n' + str(numberOfStreaks))
print('\nChance of streak: %s%%' % (numberOfStreaks / 10000))
#program to toss the coin as per user wish and count number of heads and tails
import random
toss=int(input("Enter number of times you want to toss the coin"))
tail=0
head=0
for i in range(toss):
val=random.randint(0,1)
if(val==0):
print("Tails")
tail=tail+1
else:
print("Heads")
head=head+1
print("The total number of tails is {} and head is {} while tossing the coin {} times".format(tail,head,toss))
Fixing the immediate issues
The highest voted answer doesn't actually run, because it passes a string into range() (as opposed to an int).
Here's a solution which fixes two issues: the range() issue just mentioned, and the fact that the calls to str() in the print() statements on the last two lines can be made redundant. This snippet was written to modify the original code as little as possible.
def coinToss():
number = int(input("Number of times to flip coin: "))
recordList = []
heads = 0
tails = 0
for _ in range(number):
flip = random.randint(0, 1)
if (flip == 0):
recordList.append("Heads")
else:
recordList.append("Tails")
print(recordList)
print(recordList.count("Tails"), recordList.count("Heads"))
A more concise approach
However, if you're looking for a more concise solution, you can use a list comprehension. There's only one other answer that has a list comprehension, but you can embed the mapping from {0, 1} to {"Heads", "Tails"} using one, rather than two, list comprehensions:
def coinToss():
number = int(input("Number of times to flip coin: "))
recordList = ["Heads" if random.randint(0, 1) else "Tails" for _ in range(number)]
print(recordList)
print(recordList.count("Tails"), recordList.count("Heads"))
import random
def coinToss(number):
heads = 0
tails = 0
for flip in range(number):
coinFlip = random.choice([1, 2])
if coinFlip == 1:
print("Heads")
recordList.append("Heads")
else:
print("Tails")
recordList.append("Tails")
number = input("Number of times to flip coin: ")
recordList = []
if type(number) == str and len(number)>0:
coinToss(int(number))
print("Heads:", str(recordList.count("Heads")) , "Tails:",str(recordList.count("Tails")))
All Possibilities in Coin Toss for N number of Coins
def Possible(n, a):
if n >= 1:
Possible(n // 2, a)
z = n % 2
z = "H" if z == 0 else "T"
a.append(z)
return a
def Comb(val):
for b in range(2 ** N):
A = Possible(b, [])
R = N - len(A)
c = []
for x in range(R):
c.append("H")
Temp = (c + A)
if len(Temp) > N:
val.append(Temp[abs(R):])
else:
val.append(Temp)
return val
N = int(input())
for c in Comb([]):
print(c)
heads = 1
tails = 0
input("choose 'heads' or 'tails'. ").upper()
random_side = random.randint(0, 1)
if random_side == 1:
print("heads you win")
else:
print("sorry you lose ")