I need to write a function called flip_coins(n) that returns the amount of heads. Then I need to to write a program that flips 8 coins a thousand times and returns the amount of times heads comes up three times in a row with a loop. After that I have some calculations on probability of the flips. So far this is what I have, but it wont run. What am I missing?
import random
def flip_coin():
return random.choice("HT")
def flip_coins(n):
for i in range(n):
if flip_coins() == "H":
heads_count +=1
return heads_count
for i in range (1000):
if flip_coins(8) == "3":
multiple_heads_count += 1
return multiple_heads_count
print(multiple_heads_probability)
print(second_probability)
multiple_heads_probability = multiple_heads_count/1000
second_probability = 56/256
This is rather interesting, similar to a dice rolling program I wrote a few months ago to get me back into python!
The first thing I noticed is that the code is trying to print two variables before they are created, you also need to be careful when dividing an integer, it will always return an integer, this meant that without converting to a float first (using float() or adding .0 to the end of an integer) the result will always be zero. So I changed those lines to:
multiple_heads_probability = float(multiple_heads_count)/1000
second_probability = 56.0/256
print(multiple_heads_probability)
print(second_probability)
Secondly, if you want the program to find the probability of throwing a heads three times in a row, then I would suggest adding an else statement after your if flip_coin() == "H": block. Then another if statement to determine whether there have been 3 in a row. Also, in order to add to a variable, you must first initialize them, you can do this using: heads_count = 0 and adding to it later. So I changed your second function to:
def flip_coins(n):
heads_count = 0
heads_rows = 0
for i in range(n):
if flip_coin() == "H":
heads_count +=1
else:
heads_count == 0
if heads_count == 3:
heads_rows += 1
heads_count = 0
else:
pass
return heads_rows
Lastly, the for loop. Why are you using return outside of a function? This is only for use when writing a fruitful (not void) function and not in loops (unless inside a fruitful function). In the line if flip_coins(8) == "3":, you are comparing an integer to a string so it will always return false. Because of the changes to flip_coins() I have also changed the for loop in other ways, it is now:
multiple_heads_count = 0
for i in range (1000):
if flip_coins(8) >= 1: #if there were any occurrences of 3 heads (H) in a row
multiple_heads_count += 1
The corrected and complete code is below, along with 10 possible outputs (out of thousands).
Code:
import random
def flip_coin():
return random.choice("HT")
def flip_coins(n):
# initialize two variables for incrementation
heads_count = 0
heads_rows = 0
for i in range(n): # do n times
if flip_coin() == "H": # if flipped a heads
heads_count +=1 # increment heads_count by one
else: # otherwise
heads_count == 0 # reset heads_count
if heads_count == 3: # if there have been three heads so far
heads_rows += 1 # increment heads_rows by one
heads_count = 0 # reset heads_count
else: # otherwise
pass # do nothing
return heads_rows
multiple_heads_count = 0 # initialize a variable for incrementation
for i in range (1000): # do 1000 times
if flip_coins(8) >= 1: # if there was at least one three heads in a row
multiple_heads_count += 1 # increment multiple_heads_count by one
multiple_heads_probability = float(multiple_heads_count)/1000 # calculate the probability of having at least one heads in a row
second_probability = 56.0/256 # This is the supposed theoretical probability, however I have not checked this yet
print(multiple_heads_probability)
print(second_probability)
Outputs:
0.865
0.21875
0.851
0.21875
0.853
0.21875
0.861
0.21875
0.866
0.21875
0.89
0.21875
0.839
0.21875
0.856
0.21875
0.855
0.21875
0.841
0.21875
I am intrigued as to what 56.0/256 represents, could someone enlighten me in a comment?
It looks like you are calling "flip_coins" from inside itself. You want to call "flip_coin" from inside "flip_coins" like this:
def flip_coins(n):
for i in range(n):
if flip_coin() == "H": ## changed to flip_coin
heads_count +=1
return heads_count
EDIT: There are several more issues here.
Variables must be assigned (i.e. appear on the left-hand side of an = sign) before they are referenced (appear in an expression to be evaluated). This occurs in the function "flip_coins" where you need to assign heads_count=0 before you start you loop. Also multiple_heads_count is never initialized before you try to increment it in the main (the code not inside a function definition). Finally, you are trying to print two variables, multiple_heads_probability and second_probability before you ever assign them.
You are incorrectly trying to compare an integer with a string in your loop
for i in range (1000):
if flip_coin(8) == "3": ## changed to flip_coin()
multiple_heads_count += 1
The value of flip_coin(8) is an integer, but you are checking for equality with the string "3". Strings and integers are never equal. In this case, just remove the quotes from around the 3.
You have a return statement outside of a function
return multiple_heads_count
This statement can be deleted. After running the loop, the value of multiple_heads_count will still be available, because you are still in the same scope, so you can just print it out or use it however you need.
(EDIT: NOTE - this paragraph applies to Python 2.x, but not Python 3.x) Once you fix those syntax errors, you're going to find that your results always print "0". That's because in python, division of two integers produces an integer result (the quotient, with the remainder thrown away). In this case, you're always dividing an integer by a larger integer, so the quotient is always zero. What you want is to divide the integers and get a floating point result, so you can force python to do this by specifying at least one element of the quotient as a floating point:
multiple_heads_probability = multiple_heads_count/1000.0 ## added ".0"
You can add ".0" to any integer value, and it will force floating point division. This is a very important feature of python to be aware of.
Finally, based on your problem statement, your logic is wrong. Your problem states that you should count instances of "three heads in a row" out of 8 coin flips, but your code counts ALL heads out of the 8, and returns the total number of heads. Now, there is some ambiguity here. You are checking for EXACTLY three heads, but is that what the problem states? Even if you fix the logic to look for consecutive heads, you will ignore "HHHH", "HHHHH", etc. because you are testing for exactly three. Also, are you supposed to count "HHHTTHHH" as two instances of three heads in a row?
Python is a great language, and it is a great choice for this kind of problem. Good luck!
Related
Rahul was learning about numbers in list. He came across one word ground of a number.
A ground of a number is defined as the number which is just smaller or equal to the number given to you.Hence he started solving some assignments related to it. He got struck in some questions. Your task is to help him.
O(n) time complexity
O(n) Auxilary space
Input Description:
First line contains two numbers ânâ denoting number of integers and âkâ whose ground is to be check. Next line contains n space separated numbers.
Output Description:
Print the index of val.Print -1 if equal or near exqual number
Sample Input :
7 3
1 2 3 4 5 6 7
Sample Output :
2
`
n,k = 7,3
a= [1,2,3,4,5,6,7]
b=[]
for i in range(n):
if k==a[i]:
print(i)
break
elif a[i]<k:
b.append(i)
print(max(b))
`
I've found a solution, you can pour in if you've any different views
n,k = 7,12
a= [1,2,3,4,5,6,7]
b=[]
for i in range(n):
if k==a[i]:
print(i)
break
elif a[i]<k:
b.append(i)
else:
print(max(b))
From what I understand, these are the conditions to your question,
If can find number, print the number and break
If cannot find number, get the last index IF it's less than value k
Firstly, it's unsafe to manually input the length of iteration for your list, do it like this:
k = 3
a= [1,7,2,2,5,1,7]
finalindex = 0
for i, val in enumerate(a):
if val==k:
finalindex = i #+1 to index because loop will end prematurely
break
elif val>=k:
continue
finalindex = i #skip this if value not more or equal to k
print(finalindex) #this will either be the index of value found OR if not found,
#it will be the latest index which value lesser than k
Basically, you don't need to print twice. because it's mutually exclusive. Either you find the value, print the index or if you don't find it you print the latest index that is lesser than K. You don't need max() because the index only increases, and the latest index would already be your max value.
Another thing that I notice, if you use your else statement like in your answer, if you have two elements in your list that are larger than value K, you will be printing max() twice. It's redundant
else:
print(max(b))
I need to identify the count of numbers with non-repeating digits in the range of two numbers.
Suppose n1=11 and n2=15.
There is the number 11, which has repeated digits, but 12, 13, 14 and 15 have no repeated digits. So, the output is 4.
Wrote this code:
n1=int(input())
n2=int(input())
count=0
for i in range(n1,n2+1):
lst=[]
x=i
while (n1>0):
a=x%10
lst.append(a)
x=x//10
for j in range(0,len(lst)-1):
for k in range(j+1,len(lst)):
if (lst[j]==lst[k]):
break
else:
count=count+1
print (count)
While running the code and after inputting the two numbers, it does not run the code but still accepts input. What did I miss?
The reason your code doesn't run is because it gets stuck in your while loop, it can never exit that condition, since n1 > 0 will never have a chance to be evaluated as False, unless the input itself is <= 0.
Anyway, your approach is over complicated, not quite readable and not exactly pythonic. Here's a simpler, and more readable approach:
from collections import Counter
n1 = int(input())
n2 = int(input())
count = 0
for num in range(n1, n2+1):
num = str(num)
digit_count = Counter(num)
has_repeating_digits = any((True for count in digit_count.values() if count > 1))
if not has_repeating_digits:
count += 1
print(count)
When writing code, in general you should try to avoid nesting too much stuff (in your original example you have 4 nested loops, that's readability and debugging nightmare), and try using self-describing variable names (so a, x, j, k, b... are kind of a no-go).
If in a IPython session you run import this you can also read the "Zen of Python", which kind of sums up the concept of writing proper pythonic code.
sum = 2
x=3
y=5000
for i in range (x,y):
for j in range (2,i):
if i%j==0:
break
elif i%j!=0 and j==i-1:
sum += i
if i==y-1 and y<2000000:
x=y
y+=5000
else:
continue
print(sum)
**I am not getting what is wrong in this code. By running this I came to know that the Last If and Else statement are not running **
Given your code, there are a couple of things wrong. First, sum is a python function name and should never be used as a variable name. It will get you into trouble in more ways than I care to think about. Second, the last else statement is not needed, because whether the if clause above it is or is not executed executed, the for loop will be executed again. Third, I don't understand the purpose of y and the magical value 5000, unless you are trying to provide an end value for your loop. The problem with this approach is you seem to try and extend it's range in increments of 5000. The problem is that once the initial for loop is executed, it creates a local iterable from x to 5000, and subsequent changes to y do not affect the for loops range.
I would approach the problem differently, by creating a list of primes and then use the python sum method to add all the values. Here is the code:
def sum_primes(max_prime):
""" Return Sum of primes Less than max_prime"""
primes = [2]
indx_num = 3
while primes[-1] <= max_prime:
update = True
for prime in primes:
if indx_num == prime or indx_num % prime == 0:
update = False
break
if update:
primes.append(indx_num)
indx_num += 2
#return summ of all values except the last
return sum(primes[:-1])
Executing sum_primes(2000000)
yields 1709600813
Edited for Updated code
#racraman. Love you man. You not only helped me improve my code but also to understand the Equation. Thanks for your time.
import math
# performing ramanujan's infinite series to
#generate a numerical approximation of 1/pi:
""" 1/pi = (2*sqrt(2))/9801) * (4*k)!*(1103+26390k)/(((k!)**4)*396**(4k)))"""
def factorial_1(k):
if k==0:
return 1
else:
result = k* factorial_1(k-1)
return result
def estimate_pi():
k=0
total=0
n=(2*math.sqrt(2)/9801)
limit=int(input("Enter the ending limit = ")) #k=0 until limit=infinity!!!!
while True:
m=factorial_1(4*k)*(1103+26390*k)
o=((factorial_1(k))**4)*(396**(4*k))
result=n*(m/o)
total+=result #assigning result to a new variable to keep track of changes
if k>limit:
break
k+=1 #updating value of k, to improve result & total for each loop.
return 1/total # Return's pi=3.14 only if k=0
print(estimate_pi())
The statement :
k = result
is the problem - the variable k cannot be both a loop counter and the running total.
Instead of that statement, you will need to simply decrement k, and also add result to a new running total variable that you initialise to 0 outside the loop.
You would also only want to print the result and return only after the loop has finished.
EDIT TO ADD :
Please don't use Answers in that way; that's not what they're for, and would be confusing for other readers to try to follow. The question is for containing all (ongoing) steps of defining the problem (just mark the appended updates with "EDIT TO ADD" as I have done with this comment); the answers are for solutions to that problem, to be accepted if they proved useful.
Ramanujan's formula most certainly works for increasing values of k - but you have to iterate starting at 0.
For example, let's say the user enters 5 for k.
What your code is currently doing is incrementing k - so calculating k = 5, 6, 7, ..... terminating when the step's result is 0. You're missing out k=0, 1, 2, 3, 4 - the major terms !
What you want to do instead is sum the results for k = 0, 1, 2, 3, 4, 5 so how about :
Have the user enter a variable limit instead of k
Start k at 0, and increment at each iteration
Terminate the loop when the step's result < epsilon, or k > limit
Incidentally, the n=(2*math.sqrt(2)/9801) is a constant, so can go outside the loop therefore get calculated only once.
#racraman. I'm Posting the updated code as an answer do that I could keep track of the Error's I've made for future references. Thanks for the Help.
# performing ramanujan's infinite series to
#generate a numerical approximation of 1/pi:
""" 1/pi = (2*sqrt(2))/9801) * (4*k)!*(1103+26390k)/(((k!)**4)*396**(4k)))"""
def factorial_1(k):
if k==0:
return 1
else:
result = k* factorial_1(k-1)
return result
def estimate_pi():
k=int(input("enter the value of k = "))
total=0
while True:
n=(2*math.sqrt(2)/9801)
m=factorial_1(4*k)*(1103+26390*k)
o=((factorial_1(k))**4)*(396**(4*k))
result=n*(m/o)
total+=result #assigning result to a new variable to keep track of changes
epsilon=1e-15
if abs(result)<epsilon:
break
k+=1 #updating value of k, to improve result & total for each loop.
return 1/total # Return's pi=3.14 only if k=0
print(estimate_pi())
I am making a code guessing program that asks for an input of an example key code, then the program tries combinations of characters and finds how long it took.
What I need to do is have a function that takes in a list of numbers, and returns a list of numbers, the hard thing being that the length could be anything. I currently have this:
def increment(nums):
nums[len(nums) - 1] += 1
for i in range(len(nums)):
if nums[-i + 1] == 62:
nums[-i + 1] = 0
nums[-i] += 1
if nums[0] == 62:
return [0 for n in nums]
return nums
I am trying to make the last index increase, when that reaches 62, increment the second to last by 1, then set the last to 0, continuing on and on. Then, when the first number reaches 62, it returns a list of zeros.
The expected output is as follows:
[0,0,0,1]
[0,0,0,2]
[0,0,0,3]
[0,0,0,4]
...
[0,0,0,61]
[0,0,1,0]
...
The current output is as follows:
[0,0,0,1]
[0,0,0,2]
[0,0,0,3]
[0,0,0,4]
...
[0,62,0,0]
At this point I am confused. Is there anything I am doing wrong?
Your indices in the carry loop are off, you're adding 1 and nothing, when you want to subtract 1 and 2:
def increment(nums):
nums[-1] += 1 # len(nums) - 1 is a slow verbose way to index at -1 in Python
for i in range(len(nums)):
if nums[-i - 1] == 62: # Change + 1 to - 1
nums[-i - 1] = 0 # Change + 1 to - 1
nums[-i - 2] += 1 # Change no adjustment to -2
if nums[0] == 62:
nums[:] = [0] * len(nums) # Always mutate argument to match return
return nums
This will still fail when you hit the wraparound case (due to an index out of bounds issue on the increment), and it involves more small math operations than needed, so we can improve it a bit and fix the bug by adjusting the range to run one fewer times, and remove two of the index fixups:
# Run one fewer times, iterate as negative numbers directly, and start
# from -1, not 0 so no adjustment needed for two of three lookups
for i in range(-1, -len(nums), -1):
if nums[i] == 62:
nums[i] = 0
nums[i - 1] += 1
If speed was important, you could get a bit more clever with enumerate so you're usually not even doing indexing, but this is close to what you already had, and premature optimization is the root of all evil. :-)
Note that if the goal is just to make an iterator that produces lists of this form sequentially, as I mention in the comments, the itertools module provides simpler ways to do this. For memory reasons, we can't use itertools.cycle (it would end up eventually storing the entire run of values, about 15 million of them for the four element case), but we can simulate it using chain:
from itertools import chain, product, repeat
carrygen = chain.from_iterable(product(range(62), repeat=4) for _ in repeat(None))
next(carrygen) # To skip all zero entry the first time around
carrygen = map(list, carrygen) # Returns lists instead of tuples
for nums in carrygen:
print(nums)
which would output indefinitely starting with until you break the loop or kill the process:
[0,0,0,1]
[0,0,0,2]
[0,0,0,3]
[0,0,0,4]
...
[0,0,0,61]
[0,0,1,0]
...
I don't think your list indices are working like you expect in your for loop, but rather than try to unravel that, I'd suggest that this would be a good use for a recursive function:
def increment(nums):
# Condition for ending the recursion when nums is empty
if not nums:
return []
# Check if we're overflowing the last item...
if nums[-1] < 61:
# ...if not, just increment it and return
nums[-1] += 1
return nums
else:
# ...if so, strip it off, increment the rest of the list, and
# tack on a 0 to the end
return increment(nums[:-1]) + [0]