so my goal is to try to simulate an actaul deck and draw five cards and check if there is a three of a kind. I have no problem making the deck and drawing five cards, the problem arises when i check for three of a kind
my code:
from random import shuffle, sample
from itertools import product
#generating deck
suits = ["s","d","h","c"]
values = ["1","2","3","4","5","6","7","8","9","10","11","12","13"]
deck = list(product(values,suits))
sim = 100000
three_of_a_kind = 0
for i in range(sim):
shuffle(deck)
#generating hand
hand = sample(deck,5)
#checking for three of a kind
if any(hand[0][0] == x[0] for x in hand):
three1 += 1
elif any(hand[1][0] == x[0] for x in hand):
three2 += 1
elif any(hand[2][0] == x[0] for x in hand):
three3 += 1
if three1 == 3 or three2 == 3 or three3 == 3:
three_of_a_kind += 1
prob_three = three_of_a_kind/sim
print(prob_three)
edit: my deck only had 12 cards and I changed it to 13 but my question has not changed
Using collections.Counter to count cards
# Counter(...) returns a dictionary of counts of card values
# Checking for count of 3 (card[0] is the card value in hand)
if any(v==3 for k,v in Counter(card[0] for cardin hand).items()):
three_of_a_kind += 1
Complete Code
from random import shuffle, sample
from itertools import product
from collections import Counter
#generating deck
suits = ["s","d","h","c"]
values = ["1","2","3","4","5","6","7","8","9","10","11","12","13"]
deck = list(product(values,suits))
sim = 100000
three_of_a_kind = 0
for i in range(sim):
shuffle(deck)
#generating hand
hand = sample(deck,5)
# Check for 3 of a kind by checking for 3 cards of same value
if any(v==3 for k,v in Counter(card[0] for card in hand).items()):
three_of_a_kind += 1
prob_three = three_of_a_kind/sim
print(f'{prob_three:.4%}')
Here is a little trick:
#checking for three of a kind
values = sorted(card[0] for card in hand)
if values.count(values[2]) == 3:
three_of_a_kind += 1 # three, but not four
If there are 3 equal values in a sorted list of length 5, it must look like one of these possibilities:
C C C x y
x C C C y
x y C C C
In each case the middle card value C = values[2] is the value we need to count.
For more general solutions see: collections.Counter
#checking for three of a kind
if 3 in collections.Counter(card[0] for card in hand).values():
three_of_a_kind += 1
Related
I have a list of football players. Each player has three attributes: position (G, D, M, A), name and salary.
Position Name Salary
P Buffon 6
D Maldini 23
D Baresi 15
D Bergomi 7
C Kakà 33
C Gomez 18
A Ronaldo 52
A Vieri 44
...
I want to create all possible combinations of a football team which contains exactly 11 players. These are the constrains:
Players constrain: total elements = 11
Position constrain: P = 1, D = 4, C = 4, A = 2
Salary constrain: sum salary < 200
I have started researching and it looks to me that itertools could help me generate all possible teams given the constrains. But what is not clear to me is how to code the constrains.
subset = df[['position', 'name', 'salary']]
tuples = [tuple(x) for x in subset.values]
all_permutations = itertools.permutations(tuples)
for perm in all_permutations:
# constrains
The itertools library has a very nice function for iterating through combinations. You can get all combinations of 11 players, and then filter through those.
from collections import Counter
import itertools
def valid_team(team):
positions = []
salary = 0
for player in team:
(player_pos,_,player_salary)=player
positions.append(player_pos)
salary += player_salary
pos_count = Counter(positions)
return (
pos_count['P'] is 1 and
pos_count['D'] is 4 and
pos_count['C'] is 4 and
pos_count['A'] is 2 and
salary<200
)
for team in itertools.combinations(players,11):
if (valid_team(team)):
print("found valid team")
print(team)
else:
print("found invalid team")
It should be noted that there is lot of unnecessary processing in the above method, as you can select each position individually. Alternative implementation below.
players_sorted = {}
for player in players:
if player[0] not in players_sorted:
players_sorted[player[0]] = []
players_sorted[player[0]].append(player)
p_guys = itertools.combinations(players_sorted['P'],1)
d_guys = itertools.combinations(players_sorted['D'],4)
c_guys = itertools.combinations(players_sorted['C'],4)
a_guys = itertools.combinations(players_sorted['A'],2)
teams = itertools.product(p_guys,d_guys,c_guys,a_guys)
for team in teams:
team_players = []
for pos in team:
team_players.extend(pos)
if (valid_team(team_players)):
print("found valid team")
print(team)
else:
print("found invalid team")
print(team)
You can use simple recursion with a generator:
from collections import Counter
pos_c = {'P':1, 'D':4, 'C':4, 'A':2}
def teams(d, c = []):
if len(c) == 11:
yield c
else:
s, pos = sum(int(j) for *_, j in c), Counter([j for j, *_ in c])
for i in d:
if not c or (i not in c and s+int(i[-1]) < 200 and pos_c[i[0]] >= pos.get(i[0], 0)+1):
yield from teams(d, c+[i])
My assignment is to create a program that simulates 2 coins being tossed at the same time. If both heads, then Group A gets a point; if both tails then Group B gets a point. If the coins are different then the Prof gets a point. The program must take 2 inputs: number of games and number of tosses per game. Here are 2 separate sample runs to illustrate:
How many games? 1
How many coin tosses per game? 100
Game 0:
Group A: 25 (25.0%); Group B: 19 (19.0%); Prof: 56 (56.0%)
Wins: Group A=0 (0.0%); Group B=0 (0.0%); Prof=1 (100.0%)
How many games? 5
How many coin tosses per game? 10
Game 0:
Group A: 3 (30.0%); Group B: 1 (10.0%); Prof: 6 (60.0%)
Game 1:
Group A: 6 (60.0%); Group B: 1 (10.0%); Prof: 3 (30.0%)
Game 2:
Group A: 4 (40.0%); Group B: 1 (10.0%); Prof: 5 (50.0%)
Game 3:
Group A: 4 (40.0%); Group B: 1 (10.0%); Prof: 5 (50.0%)
Game 4:
Group A: 5 (50.0%); Group B: 3 (30.0%); Prof: 2 (20.0%)
Wins: Group A=2 (40.0%); Group B=0 (0.0%); Prof=3 (60.0%)
My code (albeit clunky) works for taking the inputs, simulating coin tosses, and calculating and displaying the number of points per group and the percent. My problem however, is in calculating and storing the number of wins across all of the games played. Here is my code as of now:
import random
def coinFlip():
games = input("How many games? ")
tosses = input("How many coin tosses per game? ")
for i in range(games):
gA = 0
gAW = 0
gB = 0
gBW = 0
prof = 0
profW = 0
for j in range(tosses):
flip1 = random.randint(0, 1)
flip2 = random.randint(0, 1)
if (flip1 == 0 and flip2 == 0):
gA += 1
elif (flip1 == 1 and flip2 == 1):
gB += 1
else:
prof += 1
gAper = ((gA * 1.0) / tosses) * 100
gBper = ((gB * 1.0) / tosses) * 100
profper = ((prof * 1.0) / tosses) * 100
if (gA > gB and gA > prof):
gAW += 1
elif (gB > gA and gB > prof):
gBW += 1
elif ( prof > gA and prof > gB):
profW += 1
gAWper = ((gAW * 1.0) / games) * 100
gBWper = ((gBW * 1.0) / games) * 100
profWper = ((profW * 1.0) / games) * 100
print "Game {}:".format(i)
print " Group A: {} ({}%); Group B: {} ({}%); Prof: {} ({}%)".format(gA, gAper, gB, gBper, prof, profper)
print "Wins: Group A = {} ({}%); Group B = {} ({}%); Prof: {} ({}%)".format(gAW, gAWper, gBW, gBWper, profW, profWper)
I'm thinking I should store the wins in a list, but that's where I'm lost.
The critical problem is that you have reset the long-term counts at the start of every game. Thus, nobody gets to record more than one win. This works great for my Monday-night Frisbee games, but is not effective for your assignment.
Return to your psuedo-code and see where the loops and initializations match up. Here's a code version:
def coinFlip():
# Set-up you do only once per program execution
games = input("How many games? ")
tosses = input("How many coin tosses per game? ")
games_won_A = 0
games_won_B = 0
games_won_prof = 0
for i in range(games):
# Set-up things you do once per game
tosses_won_A = 0
tosses_won_B = 0
tosses_won_prof = 0
for j in range(tosses):
# Things you do every toss
flip1 = random.randint(0, 1)
flip2 = random.randint(0, 1)
...
# Summary things you do every game
# ... such as compute percentages
# Summary things you do at the end of the program execution
# ... such as print the overall totals
Does that get you moving?
BTW< note that this becomes a lot shorter if you put the counters into a list. For instance, counting the winner of each flip becomes a single line:
win_count[flip1 + flip2] += 1
win_count can be a list of three elements, recording the wins for A, prof, and B, in that order.
This probably isn't what the OP was looking for, but in general generating random numbers with numpy can accomplish this quickly and simply.
import numpy as np
# get these from input or wherever
games = 5
tosses = 10
n_coins = 2
experiment = np.random.randint(2,size=(games, tosses, n_coins))
flip_results = experiment.sum(axis=2) # 0 means group A wins, 1 Prof, 2 group B
game_results = np.stack((flip_results == 0, flip_results == 1, flip_results == 2))
game_results = game_results.sum(axis=2)
total_results = game_results.sum(axis=1)
print(game_results, total_results)
So I have a challenge, in which I have to create a programme that simulates a coin flip, by generating a random number corresponding to either heads or tails. When three simultaneous 'H' (heads) or 'T' (tails) are outputted my programme should stop. I have tried to get this to work, here is my code so far:
import random
active=True
list1 = []
b = 0
while active:
l=random.randint(0,1)
b += 1
i='a'
if l == 0:
i = 'H'
else:
i = 'T'
list1.append(i)
if list1[:-3] is ['H','H','H']:
active = False
elif list1[:-3] is ['T','T','T']:
active = False
else:
active = True
print(list1),
It seems that the only thing not working is the part that checks for 3 corresponding heads or tails, does anybody know how I may code this part correctly?
The problem, as was mentioned in the comments above, is that list1[:-3] should be list1[-3:] (getting the last three elements of the list, instead of everything up to the last three elements) and comparisons should be done with == instead of is. The adjusted program would be:
import random
active=True
list1 = []
b = 0
while active:
l=random.randint(0,1)
b += 1
i='a'
if l == 0:
i = 'H'
else:
i = 'T'
list1.append(i)
if list1[-3:] == ['H','H','H']:
active = False
elif list1[-3:] == ['T','T','T']:
active = False
else:
active = True
print(list1)
However, I think it might also be useful to see a condensed approach at writing the same program:
import random
flips = []
while flips[-3:] not in (['H'] * 3, ['T'] * 3):
flips.append(random.choice('HT'))
print(flips)
You can do this by tracking a running list of flips. If the new flip is the same as the previous, append it to the list. Else, if the new flip is not the same as the previous, clear the list and append the new flip. Once the length reaches 3, break from the while loop:
import random
flipping = True
flips = []
flip_status = {0: "H", 1: "T"}
current_flip = None
while flipping:
current_flip = flip_status[random.randint(0,1)]
print current_flip
if len(flips) == 0:
flips.append(current_flip)
else:
if current_flip == flips[-1]:
flips.append(current_flip)
if len(flips) == 3:
break
else:
flips = []
flips.append(current_flip)
print "Flips: " + str(flips)
Here's a sample run:
T
T
H
T
T
H
T
H
H
T
T
T
Flips: ['T', 'T', 'T']
I am stuck in a code in python which takes in number of dices and number of rolls and returns the sum of numbers obtained. It should also print the histogram of the sum. I am stuck in the first part of the code. Can someone help me fix this? Not sure where i am going wrong. Any help for the second part (returning histogram) would be helpful for me to learn it in python.
from random import choice
def roll(rolls,dice):
d = []
for _ in range(rolls):
d[sum(choice(range(1,7)) for _ in range(dice))] += 1
return(d)
Your problem here is that you can't arbitrarily index into an empty list:
l = []
l[13] += 1 # fails with IndexError
Instead, you could use a defaultdict, which is a special type of dictionary that doesn't mind if a key hasn't been used yet:
from collections import defaultdict
d = defaultdict(int) # default to integer (0)
d[13] += 1 # works fine, adds 1 to the default
or Counter, which is designed for cases like this ("provided to support convenient and rapid tallies") and provides extra handy functions (like most_common(n), to get the n most common entries):
from collections import Counter
c = Counter()
c[13] += 1
To manually use a standard dict to do this, just add a check:
d = {}
if 13 in d: # already there
d[13] += 1 # increment
else: # not already there
d[13] = 1 # create
Try this,
from random import choice
import pylab
def roll( rolls, dice ):
s = list()
for d in range( dice ):
for r in range( rolls ):
s.append( choice( range(1,7) ) )
return s
s = roll( rolls, dice )
sum_of_rolls = sum( s )
# then to plot..
pylab.hist( s )
This should do it
import random
def rolls(N, r): # N=number of dice. r=number of rolls
myDie = [1,2,3,4,5,6]
answer = {}
for _rolling in range(r):
rolls = []
for _die in range(N):
rolls.append(random.choice(myDie))
total = 0
for roll in rolls:
total += roll
if total not in answer:
answer[total] = 0
answer[total] += 1
return answer
I'm trying to write a function that calls a function (roll die() which rolls a die 1000 times and counts on a list [1,2,3,4,5,6] so an outcome might be [100,200,100,300,200,100]) and tells it to run it x amount of times. It seems my code is printing it over and over again x times
#simulate rolling a six-sided die multiple tiems, and tabulate the results using a list
import random #import from the library random so you can generate a random int
def rollDie():
#have 6 variables and set the counter that equals 0
one = 0
two = 0
three = 0
four = 0
five = 0
six = 0
#use a for loop to code how many times you want it to run
for i in range(0,1000):
#generate a random integer between 1 and 6
flip = int(random.randint(1,6))
# the flip variable is the the number you rolled each time
#Every number has its own counter
#if the flip is equal to the corresponding number, add one
if flip == 1:
one = one + 1
elif flip == 2:
two = two + 1
elif flip == 3:
three = three + 1
elif flip == 4:
four = four + 1
elif flip == 5:
five = five + 1
elif flip == 6:
six = six + 1
#return the new variables as a list
return [one,two,three,four,five,six]
the new function that I am having problems with is:
def simulateRolls(value):
multipleGames = rollDie() * value
return multipleGames
I would like to see a result like this if you typed in 4 for value
[100,300,200,100,100,200]
[200,300,200,100,100,100]
[100,100,100,300,200,200]
[100,100,200,300,200,100]
Can someone guide me in the right direction?
You can get what you want like this:
def simulateRolls(value):
multipleGames = [rollDie() for _ in range(value)]
return multipleGames
By the way, your original function seems to work perfectly fine, but if you're interested, you can remove some redundancy like this:
def rollDie():
#have 6 variables and set the counter that equals 0
results = [0] * 6
#use a for loop to code how many times you want it to run
for i in range(0,1000):
#generate a random integer between 1 and 6
flip = int(random.randint(1,6))
# the flip variable is the the number you rolled each time
results[flip - 1] += 1
return results
The line
multipleGames = rollDie() * value
will evaluate rollDie() once and multiply the result by value.
To instead repeat the call value times do this.
return [rollDie() for i in xrange(value)]
You can also simplify your rollDie function by working with a list throughout
import random #import from the library random so you can generate a random int
def rollDie():
result = [0] * 6
for i in range(0,1000):
result[random.randint(0,5)] += 1
return result