python append not adding to list - python

I am trying to learn python and am currently working with a basic dice roll script.
2 die roll until they both hit 6. when it will print the number of rolls it took to hit the defined [6:6].
this repeats 2 more times as seen with
for x in range(3):
roll_dice()
My problem is that when I try to sum the run list it will only print the last dice roll count. I'm thinking my run.append(count) is not updating but resetting once it goes through the loop again?
I understand the rest of my code is probably really inefficient but still early stages of learning.
import random
def roll_dice():
dice_one = 0
dice_two = 0
count = 0
run = []
while True:
dice_one = random.randrange(1,7)
dice_two = random.randrange(1,7)
count += 1
print(dice_one, " ", dice_two)
if dice_one + dice_two == 12:
print("----", count, "attempts----")
break
run.append(count)
print(sum(run))
for x in range(3):
roll_dice()

Like the others have pointed out, the run.append(count) is being called outside the While loop. Due to this, only the last updated value of count is being added to run.
By moving the run.append(count) inside the While loop, it will be updated each time the loop is executed.

Simply put run.append(count) in the while loop:
import random
def roll_dice():
dice_one = 0
dice_two = 0
count = 0
run = []
while True:
dice_one = random.randrange(1,7)
dice_two = random.randrange(1,7)
count += 1
print(dice_one, " ", dice_two)
if dice_one + dice_two == 12:
print("----", count, "attempts----")
break
run.append(count)
print(sum(run))
for x in range(3):
roll_dice()

print(sum(run)) only prints the last dice roll count because run.append(count) is outside the while loop. It is only called once on every function call. Put it inside the while loop and it will append each time you roll the dies.

Related

Shadow name error and Local variable not used

self teaching myself how to code and starting with this book and a Udemy course.
have been working on this practice project for 2 days now and I keep running into "Local variable 'streaks' not used when I have the streak counter placed inside the htcheck function even though I'm Cleary defining the variable, I tried placing the streak variable outside of the function at the top of the code to declare as it a global value but that still doesn't work and then I get the "Shadow name" error.
what the code should be doing is flipping a coin 10000 times then checking for streaks of 6 then present the user with how many streaks of 6 occurred and a percent value of how often a streak of 6 was, I'm sure a lot of you have seen this question been asked before as it's from Al Sweigart's Automate The Boring Stuff with python 2nd edition <- I just cant find the answer to my specific error hence this post.
I just need help with figuring out why my variable ' streaks = 0 ' isn't working as shown below. and why it doesn't work as a global variable declared where I have heads tails and x. I would prefer a solution that keeps streaks inside the htcheck function but i'm open to any and all solutions.
Thank you in advance.
# Automate Python - Coin Flips Streaks
heads = []
tails = []
x = 0
#Flips a coin, then stores result into respective list
def coinflip():
y = random.randint(0, 1)
if y == 0:
heads.append('H')
tails.clear()
elif y == 1:
tails.append('T')
heads.clear()
#checks if list len is 6 then clears and adds +1 to streak
def htcheck():
streaks = 0
if len(heads) == 6:
streaks = streaks + 1
heads.clear()
elif len(tails) == 6:
tails.clear()
streaks = streaks + 1
while x < 10000:
x = x + 1
coinflip()
htcheck()
print('# Streaks of 6: ", streaks)
While you can use global variables for something like this, I generally prefer using return statements and tracking the variables separately for easier debugging and readability
Something like this is an option
# Automate Python - Coin Flips Streaks
heads = []
tails = []
num_streaks = 0
#here we eliminate the need for a counter variable x by using a for loop instead of a while loop below, instead creating a counter for our streaks
#Flips a coin, then stores result into respective list
def coinflip():
y = random.randint(0, 1)
if y == 0:
heads.append('H')
tails.clear()
elif y == 1:
tails.append('T')
heads.clear()
#checks if list len is 6 then clears and adds +1 to streak
def htcheck():
streaks = 0
if len(heads) == 6:
streaks = streaks + 1
heads.clear()
elif len(tails) == 6:
tails.clear()
streaks = streaks + 1
#here we return the local variable instead of trying to use the global scope
return streaks
#using a for instead of a while loop is a bit of a stylistic choice but can prevent problems arising from forgetting a `break` condition or messing up counter incrementation
for x in range(1000):
coinflip()
#here we add to the streak counter we declared in the outer scope by using the local variable returned from the function
num_streaks += htcheck()
print('# Streaks of 6: ', num_streaks)

Python coin flip with functions

I need to create a python program that will use various functions to simulate flipping a coin 100 times and finding the largest streak of "H"'s out of 10,000 tries. I am stuck on how to finish the def main() function, specifically the counter. I also don't know if my program is calculating the streaks correctly.
def flipCoin() - returns 'H' or 'T' with the same probability as a coin.
def simulate(numFlips) - simulates flipping a coin numFlips(100) times. This function returns a list of length numFlips containing H's and T's.
def countStreak(flips_list) - iterates through the flips list passed to it and counts streaks of 'H's and returns the largest streak it finds. Keep track of the current number of heads and the current largest streak of heads in two separate variables.
As you iterate through the list, keep track of the current number of heads you've seen in a row. If you see a tail, check if the current streak of heads is larger than your current longest streak. If so, save the current streak. Then reset your heads counter.
In the main function, write a testing loop that simulates the process 10000 times.
Keep track of the current largest streak of heads and display this result after the test loop completes.
# import statements
import random
# function defintions
def flip():
coin = random.randint(0, 1)
if coin == 0:
return "H"
else:
return "T"
def simulate(num_flips):
# simulates numFlips coin flips
# returns a list of the flips
numFlips = []
for i in range(100):
numFlips.append(flip())
return numFlips
def countStreak(flips_list):
# iterates through the 'flips' list
# returns number of 'H's
count = 0
maxCount = 0
flips_list = simulate()
for i in flips_list:
if i == "H":
count += 1
if count > maxCount:
maxCount = count
else:
count = 0
return maxCount
def main():
for j in range(10000):
trial = simulate(100)
coinFlip = countStreak(1)
# need something here to track count of streaks for "H"
print("The longest streak of heads was " + str(coinFlip) +".")
if __name__ == "__main__":
main()
So there was a flaw in your code, you were running simulate() function 10000 times. But actually, you had to run it once, but return a list of 10000 items. Also, you need not check the streak every time so the check_streak() need to be out of the loop and we need to pass the result obtained from simulate(10000) into it.
Correct Code:
# import statements
import random
# function defintions
def flip():
coin = random.randint(0, 1) # better option would be to use random.choice()
if coin == 0:
return "H"
else:
return "T"
def simulate(num):
# simulates numFlips coin flips
# returns a list of the flips
numFlips = []
for i in range(num): # this needs to run num times
numFlips.append(flip())
return numFlips
def countStreak(flips_list):
# iterates through the 'flips' list
# returns number of 'H's
count = 0
maxCount = 0
for i in flips_list:
if i == "H":
count += 1
if count > maxCount:
maxCount = count
else:
count = 0
return maxCount
def main():
trial = []
for j in range(10000):
temp2 = simulate(100) # SImulate 10000 coin flips
coinFlip = countStreak(temp2) # Check streak of variable trial
trial.append(coinFlip)
# need something here to track count of streaks for "H"
# print(trial)
print("The longest streak of heads was " + str(max(trial)) +".")
if __name__ == "__main__":
main()
This Part is Optional, For optimisation
Though the logic isn't wrong, you need not make the list 1st and then check streak, you can simply check it together, it will take less time and space.
Also, your logic is correct, but this one would be better:
import random
# function defintions
def flip():
return random.choice(['H', 'T']) # using random.choice()
def simulate(num_flips):
streak = 0
temp = 0
for i in range(num_flips):
if flip() == 'H':
temp+=1 # adding one to temporary streak if it is a heads
else: # this block executes if streak is broken
if temp > streak:
streak = temp
temp = 0
return streak
def main():
trial = []
for i in range(10000):
trial.append(simulate(100))
print("The longest streak of heads was " + str(max(trial)) +".")
if __name__ == "__main__":
main()

Counting Heads and Tails in a coin flip program

For my assignment, I have to use Functions within Python to simulate a coin flip. I managed to get the coin flip to showcase heads and tales for the amount the user has inputted. However, for the next portion, I have to get the program to read how many times Heads and Tails appeared. The error I am getting is
'NameError: name 'heads' is not defined'.
import random
def main():
tosses = int(input("Please enter the amount of coin tosses:"))
coin(tosses)
count = 0
heads = 0
tails = 0
def coin(tosses):
for toss in range(tosses):
if random.randint(1, 2) == 1:
print('Heads')
heads += 1
count += 1
else:
print('Tails')
heads += 1
count += 1
print (heads)
print (tails)
main()
Problem
heads was defined out of the scope of the function coin.
Solution
Try defining the variables inside the function, then returning them. Note: the same had to be done with main.
import random
def main():
tosses = int(input("Please enter the amount of coin tosses:"))
coin(tosses)
heads, tails, count = coin(tosses)
return heads, tails
def coin(tosses):
count = 0
heads = 0
tails = 0
for toss in range(tosses):
if random.randint(1, 2) == 1:
print('Heads')
heads += 1
count += 1
else:
print('Tails')
tails += 1 # note you had this say heads before
count += 1
return heads, tails, count
heads, tails = main()
print(heads)
print(tails)
More on why this problem occurred
When you use def and create a new function, all of the variables in that function are accessible just to that function.
What was happening to you, is that you were trying to update the heads variable with heads += 1, but the function literally didn't know what the variable you were referring to is! (That variable was defined in main, and is only accessible from within the main function.)

Dice roller having issues with second while loop

I'm a longterm lurker first time questioner. I'm trying to teach myself Python and while I've researched my question I couldn't find an answer. My below code runs if I remove the first While loop but currently it doesn't seem to enter the second while loop. I think I might be channelling my inner VBA which I use at work and this is only second time I've tried Python.
I've tried changing the first while so it isn't just while true and tried variants on the second while.
The intent here is to investigate a dice pool mechanic for a game I'm thinking of and model rolling multiple D6s, 5-6 explode, 3+ successes and 1-2 failures. Ultimately I want it to run roll the dice return the dice list number of successes etc and then reset asking the user for number of dice to roll again.
import random
Scount = 0
Xcount = 0
Fcount = 0
rollcount = 0
cheat = 0
NoOfDice = 1
Dicelist = []
while True:
print ("Input number of dice to roll")
NoOfDice=input()
while cheat<int(NoOfDice):
rand = random.randint(1, 6)
Dicelist.append(rand)
if rand <= 4:
cheat += 1
if rand >= 3:
Scount += 1
if rand >= 2:
Fcount += 1
if rand <= 5:
Xcount += 1
print (Dicelist)
print ("We rolled " + str(NoOfDice) + " you got " + str(Scount) + " number of succeses with " + str(Xcount) + " number of dice exploded with " + str(Fcount) + " dice failed")
Thank you all and appreciate your time!
The condition for your first while loop is essentially going to always be True, meaning that it's an infinite loop.
Your second loop may not seem like it's running, but it definitely is (as long as you enter a number greater than 0).
The reason your program has no output is because your print() statements are after the infinite loop, so they'll never run. This is why your program runs as desired when you remove the infinite loop.
To fix this, just move your print() statements inside the first loop but at the end.
Note: If you want to get time to read what is being printed when you run the program, you should change the print()s to input()s as this will mean that the first loop only loops around after you've pressed Enter.
Additional Note: random.randint(1, 6) returns a value from 0 to 5 not from 1 to 6. Looking at your values in your if statements, you probably want to change code to:
rand = random.randint(1,6) + 1
Your code could further be condensed using with just 2 if statements instead of 4. Below is my proposed solution. I wrapped it in a function but you don't have to. I'll leave it for you think and decide how to escape the first "while" loop after the second while loop finished execution.
def rolldice ():
... while True:
... scount = 0
... xcount = 0
... fcount = 0
... cheat = 0
... NoOfDice = ''
... DiceList = []
... NoOfDice = input ('Number of dice to roll: ')
... while cheat < int (NoOfDice):
... rand = random.randint(1, 6)
... DiceList.append (rand)
... if rand <= 5:
... cheat += 1
... xcount += 1
... if rand >= 2:
... fcount += 1
... scount += 1
... print ('Dice List: ', DiceList)
... print ('Number of dice rolled:', NoOfDice)
... print ('Success Count: %d' % scount)
... print ('Exploded Count: %d' % xcount)
... print ('Failed Count: %d' % fcount)
...
>>> rolldice()
Number of dice to roll: >? 3
Dice List: [2, 3, 1]
Number of dice rolled: 3
Success Count: 2
Exploded Count: 3
Failed Count: 2
Number of dice to roll: >? 1
Dice List: [5]
Number of dice rolled: 1
Success Count: 1
Exploded Count: 1
Failed Count: 1
Number of dice to roll:

Dice statistics in Python

: Repeatedly asks the user for the number of times to roll the dice, quitting only when the user-entered number is less than 1. Hint: Use a while loop that will execute as long as num_rolls is greater than or equal to 1.
I did this but don't know how to do it using while loop.
import random
num_sixes = 0
num_sevens = 0
num_rolls = int(input('Enter number of rolls:\n'))
if num_rolls >= 1:
for i in range(num_rolls):
die1 = random.randint(1,6)
die2 = random.randint(1,6)
roll_total = die1 + die2
#Count number of sixes and sevens
if roll_total == 6:
num_sixes = num_sixes + 1
if roll_total == 7:
num_sevens = num_sevens + 1
print('Roll %d is %d (%d + %d)' % (i, roll_total, die1, die2))
print('\nDice roll statistics:')
print('6s:', num_sixes)
print('7s:', num_sevens)
else:
print('Invalid number of rolls. Try again.')
*
Using a while loop is a very common way to solve some problems in programming languages like C. In Python you can do that as well, but Python has it's own ways to do some things. In your case you have been using a for loop with the range() function. That is more "pythonic" than counting down with while, which is more "C-ish".
Interestingly, the range function is clever and you non't need to do an extra check. Any integer argument < 1 will result in an empty list and the for loop will not be executed. And the for has an else:
for i in range(num_rolls):
# your dicing code
else:
print('Invalid number of rolls. Exiting.')
sys.exit(1) # might be good to signal an error with a return code > 0
# your result printing code
TL;DR: Your code is fine if not better. Only change it if the teacher (?) requires while.

Categories