Posts: 13
Threads: 4
Joined: Nov 2020
Nov-18-2020, 03:42 AM
(This post was last modified: Nov-18-2020, 06:39 AM by buran.)
The question asks to Write a program called test4.py that plays the following card game:
The game starts with certain initial amount of dollars.
At each round of the game, instead of flipping a coin, the player shuffles a deck and draws 6 cards. If the drawn hand contains at least one ace, the player gains a dollar, otherwise they lose a dollar.
The game runs until the player either runs out of money or doubles their initial amount.
To test the game, given the initial amount, run it 1000 times to determine how many rounds does the game last on average.
Provide a user with an interface to enter the initial bankroll. For each entered number, the program should respond with the average duration of the game for that initial bankroll.
If code is correct it should run the program:
Output: Enter initial amount: 10
Average number of rounds: 46.582
Enter initial amount: 20
Average number of rounds: 97.506
Enter initial amount: 30
Average number of rounds: 148.09
Enter initial amount: 40
Average number of rounds: 194.648
Enter initial amount: 50
Average number of rounds: 245.692
Enter initial amount: 60
Average number of rounds: 290.576
Enter initial amount: 70
Average number of rounds: 335.528
Enter initial amount: 80
Average number of rounds: 391.966
Enter initial amount: 90
Average number of rounds: 433.812
Enter initial amount: 100
Average number of rounds: 487.258
This is my code (but the numbers are incorrect(average):
import random
faceValues = ['ace', '2', '3', '4', '5', '6',
'7', '8', '9', '10', 'jack',
'queen', 'king']
suits = ['clubs', 'diamonds', 'hearts',
'spades']
import random
def shuffledDeck():
deck = []
for faceValue in faceValues:
for suit in suits:
deck.append(faceValue + ' of ' + suit)
random.shuffle(deck)
return deck
def faceValueOf(card):
return card.split()[0]
def suitOf(card):
return card.split()[2]
import random
def oneGame(initial):
countFlips = 0
bankroll = initial
while 0 < bankroll < 2*initial:
d=shuffledDeck()
numberOfAces=0
for number in range(6):
countFlips+=1
for currentHand in d:
if faceValueOf(currentHand)=='ace':
bankroll +=1
else:
bankroll -= 1
return countFlips
def experiment(initials, repetitions):
for initial in initials:
print('Enter Initial bankroll:', initial)
totalFlips = 0
for number in range(repetitions):
totalFlips += oneGame(initial)
print('Average number of rounds:', totalFlips/repetitions)
print()
experiment([10,20,30,40,50,60,70,80,90,100],1000)
Posts: 13
Threads: 4
Joined: Nov 2020
This is my code:
import random
faceValues = ['ace', '2', '3', '4', '5', '6',
'7', '8', '9', '10', 'jack',
'queen', 'king']
suits = ['clubs', 'diamonds', 'hearts',
'spades']
import random
def shuffledDeck():
deck = []
for faceValue in faceValues:
for suit in suits:
deck.append(faceValue + ' of ' + suit)
random.shuffle(deck)
return deck
def faceValueOf(card):
return card.split()[0]
def suitOf(card):
return card.split()[2]
import random
def oneGame(initial):
countFlips = 0
bankroll = initial
while 0 < bankroll < 2*initial:
d=shuffledDeck()
numberOfAces=0
for number in range(6):
countFlips+=1
for currentHand in d:
if faceValueOf(currentHand)=='ace':
bankroll +=1
else:
bankroll -= 1
return countFlips
def experiment(initials, repetitions):
for initial in initials:
print('Enter Initial bankroll:', initial)
totalFlips = 0
for number in range(repetitions):
totalFlips += oneGame(initial)
print('Average number of rounds:', totalFlips/repetitions)
print()
experiment([10,20,30,40,50,60,70,80,90,100],1000)
The error is that it is not giving me the correct average number :(
If written correctly It should run:
Enter initial amount: 10
Average number of rounds: 46.582
Enter initial amount: 20
Average number of rounds: 97.506
Enter initial amount: 30
Average number of rounds: 148.09
Enter initial amount: 40
Average number of rounds: 194.648
Enter initial amount: 50
Average number of rounds: 245.692
Enter initial amount: 60
Average number of rounds: 290.576
Enter initial amount: 70
Average number of rounds: 335.528
Enter initial amount: 80
Average number of rounds: 391.966
Enter initial amount: 90
Average number of rounds: 433.812
Enter initial amount: 100
Average number of rounds: 487.258
The assignment was to Write a program called test4.py that plays the following card game:
The game starts with certain initial amount of dollars.
At each round of the game, instead of flipping a coin, the player shuffles a deck and draws 6 cards. If the drawn hand contains at least one ace, the player gains a dollar, otherwise they lose a dollar.
The game runs until the player either runs out of money or doubles their initial amount.
To test the game, given the initial amount, run it 1000 times to determine how many rounds does the game last on average.
Provide a user with an interface to enter the initial bankroll. For each entered number, the program should respond with the average duration of the game for that initial bankroll.
Posts: 6,809
Threads: 20
Joined: Feb 2020
Nov-18-2020, 05:44 AM
(This post was last modified: Nov-18-2020, 06:28 AM by deanhystad.)
You have an error in oneGame. The rules are supposed to be that you win 1 if your hand contains an ace, otherwise you lose 1. Your logic is, well it is hard to say exactly what your logic is doing, but you never win, you lose very quickly, and you count to 6 instead of counting how long it takes to win or lose. This part is the problem. I think you were planning on counting aces, but that idea got lost somewhere.
numberOfAces=0
for number in range(6):
countFlips+=1
for currentHand in d:
if d == 1:
bankroll +=1
else:
bankroll -= 1 Are you required to make a regular deck of cards? To learn the statistics of the game it would easier and faster if you design the deck to fit the experiment. The code below makes it easy to count aces by assigning aces a value of 1 and all other cards a value of 0. If the sum of a hand > 0 you know you have an ace.
deck = [1,0,0,0,0,0,0,0,0,0,0,0,0]*4
def hand():
if sum(random.sample(deck, k=6)) > 0:
return 1;
return -1
def game(start):
count = 0
bank = start
while 0 < bank < start * 2:
bank += hand()
count += 1
return count; If you want to stay with using a deck with Aces and Queens you can still speed things up asking if 'Ace' is
Posts: 6,809
Threads: 20
Joined: Feb 2020
Posts: 13
Threads: 4
Joined: Nov 2020
(Nov-18-2020, 05:45 AM)deanhystad Wrote: Don't double post.
Sorry I didn't mean to. It was my first time on the website and I got confused. I was even confused about how to post a thread.
Okay this is my code(idk how to set it up on the thread the way you did (I'm sorry :( ). Below my code is instructions to fix my code provided from my professor. Can you help me fix the code per his instruction? copy/paste, fix the send to me bc I'm still new and I get lost going through line to fix. Thankk you in advance!!!!
import random
faceValues = ['ace', '2', '3', '4', '5', '6',
'7', '8', '9', '10', 'jack',
'queen', 'king']
suits = ['clubs', 'diamonds', 'hearts',
'spades']
import random
def shuffledDeck():
deck = []
for faceValue in faceValues:
for suit in suits:
deck.append(faceValue + ' of ' + suit)
random.shuffle(deck)
return deck
def faceValueOf(card):
return card.split()[0]
def suitOf(card):
return card.split()[2]
import random
def oneGame(initial):
countFlips = 0
bankroll = initial
while 0 < bankroll < 2*initial:
start=0
d=shuffledDeck()
for number in range(6):
countFlips+=1
for currentHand in d:
if faceValueOf(currentHand)=='ace':
start += 1
if start >= 1:
bankroll += 1
else:
bankroll -= 1
return countFlips
def experiment(initials, repetitions):
for initial in initials:
print('Enter Initial bankroll:', initial)
totalFlips = 0
for number in range(repetitions):
totalFlips += oneGame(initial)
print('Average number of rounds:', totalFlips/repetitions)
print()
experiment([10, 20, 30,40,50,60,70,80,90,100], 1000)
Professor instruction :
The last line of your program automatically uses the initial amounts shown in the test instructions. However, that's not what the test instructions say to do, which is to provide a user with an interface to enter the initial bankroll. To fix this, you will need to replace that line with a loop that repeatedly prompts the user for the initial bankroll and then passes it to the experiment function. (You can then remove line 50 since it won't be needed.)
- The purpose of countFlips is to keep track of each time your program draws a hand. However, since line 38 is inside the for loop on the line above it, it increases countFlips 6 times instead of just once. You can fix this by moving that line outside (before or after) that loop.
- Line 39 goes through all 52 cards in the deck, which is not correct. To fix, you can replace that line with currentHand = d[number], which makes your program draw a card (make sure it is indented so that it is inside the for loop on line 37).
Posts: 6,809
Threads: 20
Joined: Feb 2020
Please wrap code in Python tags so it retains proper indentation.
This code plays the card game and calculates the average number of hands for any starting bank.
import random
deck = 'A234567890JQK'*4
def play(start, hand=6, replay=1):
count = 0
for _ in range(replay):
bank = start
while 0 < bank < start*2:
if 'A' in random.sample(deck, hand):
bank += 1
else:
bank -= 1
count += 1
return count
while True:
start = int(input('Enter inital amount: '))
print('Average number of rounds:', play(start, replay=1000)/1000) This is my deck of cards
deck = 'A234567890JQK'*4 I also made a version where this was my deck of cards
deck = '[1,0,0,0,0,0,0,0,0,0,0,0,0]'*4 Either work fine. The important thing is to have something that accurately represents the attributes that are important for the purpose of this experiment. The deck should have 4 aces and 48 other cards. The aces can be a 1 and other cards 0, or the aces can be A and the other cards not A. There is no reason to make the deck any fancier than it has to be for the purposes of the experiment.
This is a hand.
if 'A' in random.sample(deck, hand):
bank += 1
else:
bank -= 1 There is no reason to count how many aces appear in the hand. The rules of the game are you get paid $1 if there are any aces and you lose $1 if there are no aces. When I used 0's and 1's I used the sum() function to determine if there are any aces. With the letters I look for the letter 'A'. This code is sufficient for playing a single hand, and there is no reason to make the code more complicated than it has to be.
This is a game.
bank = start
while 0 < bank < start*2:
if 'A' in random.sample(deck, hand):
bank += 1
else:
bank -= 1
count += 1 The rules of the game say you continue to play hands until you either lose all your money or you double your money. It doesn't matter if you win or loose. The important part here is keeping track of how many hands it takes to win or lose.
For my purposes I don't want to play a single game. I want to play 1000 games. I could write a function to play a hand, and a function to play a game, and a function to calculate the average of 1000 games, but the more functions I use the slower the code. To allow for playing more than one game I wrapped the game inside a loop.
def play(start, hand=6, replay=1):
count = 0
for _ in range(replay):
bank = start
while 0 < bank < start*2:
if 'A' in random.sample(deck, hand):
bank += 1
else:
bank -= 1
count += 1
return count And finally, this code lets me enter the starting bank and prints the average number of hands.
while True:
start = int(input('Enter inital amount: '))
print('Average number of rounds:', play(start, replay=1000)/1000) The program will calculate averages for as long as I input integer strings. To quit I can type Ctrl+c or just enter without a number.
Posts: 13
Threads: 4
Joined: Nov 2020
The avg number is a bit off still so. This is an example of the running code.
Example of running the program:
Enter initial amount: 10
Average number of rounds: 46.582
Enter initial amount: 20
Average number of rounds: 97.506
Enter initial amount: 30
Average number of rounds: 148.09
Enter initial amount: 40
Average number of rounds: 194.648
Enter initial amount: 50
Average number of rounds: 245.692
Enter initial amount: 60
Average number of rounds: 290.576
Enter initial amount: 70
Average number of rounds: 335.528
Enter initial amount: 80
Average number of rounds: 391.966
Enter initial amount: 90
Average number of rounds: 433.812
Enter initial amount: 100
Average number of rounds: 487.258
Write a program called test4.py that plays the following card game:
The game starts with certain initial amount of dollars.
At each round of the game, instead of flipping a coin, the player shuffles a deck and draws 6 cards. If the drawn hand contains at least one ace, the player gains a dollar, otherwise they lose a dollar.
The game runs until the player either runs out of money or doubles their initial amount.
To test the game, given the initial amount, run it 1000 times to determine how many rounds does the game last on average.
Provide a user with an interface to enter the initial bankroll. For each entered number, the program should respond with the average duration of the game for that initial bankroll.
Posts: 6,809
Threads: 20
Joined: Feb 2020
Your big error is in oneGame()
def oneGame(initial):
countFlips = 0
bankroll = initial
while 0 < bankroll < 2*initial:
# This is where you error was. You did multiple
# adds and subtracts for each hand. There should
# only be 1 ad or subtract
for card in shuffledDeck[0:6]: # Look at top six cards
if 'ace' in card:
bankroll += 1
break # Stop after find first ace
else:
bankroll -= 1 # Only do this if for loop completes
countFlips += 1
return countFlips Your code added a dollar for each ace and subtracted a dollar for each non-ace. If you drew 4 aces you would add $2, but if you drew no aces you lost $6. In the code above we break out of the for loop after finding the first ace. The "else" statement is only executed when there are no aces in the hand.
The for/else is a bit confusing. I don't think any other programming language has this logic construct. You might find the code easier to understand if the "hand" logic is broken out into it's own function.
def hand():
for card in shuffledDeck[0:6]: # Look at top 6 cards
if 'ace' in card:
return 1 # Return 1 if we find an ace
return -1 # Return -1 if no ace found
def oneGame(initial):
countFlips = 0
bankroll = initial
while 0 < bankroll < 2*initial:
bankroll += hand()
countFlips += 1
return countFlips
Posts: 6,809
Threads: 20
Joined: Feb 2020
Nov-20-2020, 05:32 AM
(This post was last modified: Nov-20-2020, 05:32 AM by deanhystad.)
I think the averages in your last post look fine. 1000 hands is a pretty small sample size for this game as the number of hands required to win or lose varies greatly. I modified my program slightly to collect the counts and do a little statistical analysis and plotting.
import random
import statistics
import collections
import matplotlib.pyplot as plt
deck = 'A234567890JQK'*4
hand = 6
def play(start):
count = 0
bank = start
while 0 < bank < start*2:
if 'A' in random.sample(deck, hand):
bank += 1
else:
bank -= 1
count += 1
return count
while True:
start = int(input('Enter inital amount: '))
counts = [play(start) for _ in range(1000)]
unique_counts = collections.Counter(counts)
print('Mean =', statistics.mean(counts))
print('Median =', statistics.median(counts))
print('Number of different counts =', len(unique_counts))
print('Count range =', min(counts), 'to', max(counts))
mode = statistics.mode(counts)
print('Mode =', mode, 'Count =', unique_counts[mode])
print('Standard Deviation =', statistics.stdev(counts))
plt.bar(unique_counts.keys(), unique_counts.values())
plt.show() Output: Enter inital amount: 100
Mean = 484.818
Median = 474.0
Number of different counts = 222
Count range = 238 to 952
Mode = 454 Count = 15
Standard Deviation = 103.47417929987066
Enter inital amount: 100
Enter inital amount: 100
Mean = 492.046
Median = 480.0
Number of different counts = 227
Count range = 250 to 934
Mode = 466 Count = 15
Standard Deviation = 102.92227591186895
Running two tests the average count changed from 484 to 492. Such variation is not surprising when you see the number of hands required to win or lose a game ranges from the low 200's to over 1000 upon occasion. When I increased the sample size from 1000 to 10,000 I also noticed some interesting clumping in the plots. The kind of non-uniform distribution that raises hell with statistical analysis.
What I found really interesting is how bad this game is. You never win. I modified the code to count wins and losses and I never win. I guess this makes sense considering you only have a 38% chance of winning any given hand and you need to win a lot of hands to double your money. The odds are not in your favor.
|