How to create a proper histogram in python with only one value - python

I wrote a function aveMean(die, numRolls, numTrials) which requires the following:
Blockquote
die, a Die
numRolls, numTrials, are positive ints
Calculates the expected mean value of the longest run of a number over numTrials runs of numRolls rolls.
Calls makeHistogram to produce a histogram of the longest runs for all the trials. There should be 10 bins in the histogram
Choose appropriate labels for the x and y axes.
Returns the mean calculated
Blockquote
Everything works fine, except:
the list has just one item
the items in the list are equal
or the numRolls are limited to one roll
This is how it should look like
You see that in 1.-3. there is always a little extra bar (barely visible) on the left side. How can I get rid of it? I read something about this is due to Python 3, but I didn't find out a solution.
Thanks!
P.S. I edited the code how to call the histogram and also the function that uses the call to create the histogram:
def getMeanAndStd(X):
mean = sum(X)/float(len(X))
tot = 0.0
for x in X:
tot += (x - mean)**2
std = (tot/len(X))**0.5
return mean, std
class Die(object):
def __init__(self, valList):
""" valList is not empty """
self.possibleVals = valList[:]
def roll(self):
return random.choice(self.possibleVals)
def makeHistogram(values, numBins, xLabel, yLabel, title=None):
pylab.hist(values, numBins)
pylab.xlabel(xLabel)
pylab.ylabel(yLabel)
if(title != None): pylab.title(title)
pylab.show()
def aveMean(die, numRolls, numTrials):
tries = die
testList, res = [], []
for i in range(numTrials):
count, tempCount, testList = 1, 1, []
for i in range(numRolls):
testList.append(tries.roll())
for i in range(1, numRolls):
if testList[i-1] == testList[i]:
count +=1
else:
if count > tempCount:
tempCount = count
count = 1
else:
count = 1
res.append(tempCount)
mean, std = getMeanAndStd(res)
makeHistogram(res, 10, 'Quantity of Consecutive Numbers', 'Consecutive Number per Run')
return round(mean, 3)
The Error Message I get is: Unsuccessfully called makeHistogram

def getAverage(die, numRolls, numTrials):
"""
- die, a Die
- numRolls, numTrials, are positive ints
- Calculates the expected mean value of the longest run of a number
over numTrials runs of numRolls rolls
- Calls makeHistogram to produce a histogram of the longest runs for all
the trials. There should be 10 bins in the histogram
- Choose appropriate labels for the x and y axes.
- Returns the mean calculated
"""
tries = die
testList, res = [], []
for i in range(numTrials):
count, tempCount, testList = 1, 1, []
for i in range(numRolls):
testList.append(tries.roll())
for i in range(1, numRolls):
if testList[i-1] == testList[i]:
count +=1
else:
count = 1
if count > tempCount:
tempCount = count
if count > tempCount:
tempCount = count
res.append(tempCount)
mean, std = getMeanAndStd(res)
makeHistogram(res, 10, 'Quantity of Consecutive Numbers', 'Consecutive Number per Run')
return round(mean, 3)

Related

How to get percentage of combinations computed?

I have this password generator, which comute combination with length of 2 to 6 characters from a list containing small letters, capital letters and numbers (without 0) - together 61 characters.
All I need is to show percentage (with a step of 5) of the combinations already created. I tried to compute all the combinations of selected length, from that number a boundary value (the 5 % step values) and count each combination written in text file and when when the count of combinations meets the boundary value, print the xxx % completed, but this code doesn't seem to work.
Do you know how to easily show the percentage please?
Sorry for my english, I'm not a native speaker.
Thank you all!
def pw_gen(characters, length):
"""generate all characters combinations with selected length and export them to a text file"""
# counting number of combinations according to a formula in documentation
k = length
n = len(characters) + k - 1
comb_numb = math.factorial(n)/(math.factorial(n-length)*math.factorial(length))
x = 0
# first value
percent = 5
# step of percent done to display
step = 5
# 'step' % of combinations
boundary_value = comb_numb/(100/step)
try:
# output text file
with open("password_combinations.txt", "a+") as f:
for p in itertools.product(characters, repeat=length):
combination = ''.join(p)
# write each combination and create a new line
f.write(combination + '\n')
x += 1
if boundary_value <= x <= comb_numb:
print("{} % complete".format(percent))
percent += step
boundary_value += comb_numb/(100/step)
elif x > comb_numb:
break
First of all - I think you are using incorrect formula for combinations because itertools.product creates variations with repetition, so the correct formula is n^k (n to power of k).
Also, you overcomplicated percentage calculation a little bit. I just modified your code to work as expected.
import math
import itertools
def pw_gen(characters, length):
"""generate all characters combinations with selected length and export them to a text file"""
k = length
n = len(characters)
comb_numb = n ** k
x = 0
next_percent = 5
percent_step = 5
with open("password_combinations.txt", "a+") as f:
for p in itertools.product(characters, repeat=length):
combination = ''.join(p)
# write each combination and create a new line
f.write(combination + '\n')
x += 1
percent = 100.0 * x / comb_numb
if percent >= next_percent:
print(f"{next_percent} % complete")
while next_percent < percent:
next_percent += percent_step
The tricky part is a while loop that makes sure that everything will work fine for very small sets (where one combination is more than step percentage of results).
Removed try:, since you are not handling any errors with expect.
Also removed elif:, this condition is never met anyway.
Besides, your formula for comb_numb is not the right one, since you're generating combinations with repetition. With those changes, your code is good.
import math, iterations, string
def pw_gen(characters, length):
"""generate all characters combinations with selected length and export them to a text file"""
# counting number of combinations according to a formula in documentation
comb_numb = len(characters) ** k
x = 0
# first value
percent = 5
# step of percent done to display
step = 5
# 'step' % of combinations
boundary_value = comb_numb/(100/step)
# output text file
with open("password_combinations.txt", "a+") as f:
for p in itertools.product(characters, repeat=length):
combination = ''.join(p)
# write each combination and create a new line
f.write(combination + '\n')
x += 1
if boundary_value <= x:
print("{} % complete".format(percent))
percent += step
boundary_value += comb_numb/(100/step)
pw_gen(string.ascii_letters, 4)

subtract n values from input python

I haven't found anything even relevant to my question, so i may be asking it wrong.
I am working on an exercise where I am given sequential values starting at 1 and going to n, but not in order. I must find a missing value from the list.
My method is to add the full 1 => n value in a for loop but I can't figure out how to add n - 1 non-sequential values each as its own line of input in order to subtract it from the full value to get the missing one.
I have been searching modifications to for loops or just how to add n inputs of non-sequential numbers. If I am simply asking the wrong question, I am happy to do my own research if someone could point me in the right direction.
total = 0
for i in range (1 , (int(input())) + 1):
total += i
print(total)
for s in **?????(int(input()))**:
total -= s
print(total)
sample input:
5
3
2
5
1
expected output: 4
To fill in the approach you're using in your example code:
total = 0
n = int(input("How long is the sequence? "))
for i in range(1, n+1):
total += i
for i in range(1, n):
total -= int(input("Enter value {}: ".format(i)))
print("Missing value is: " + str(total))
That first for loop is unnecessary though. First of all, your loop is equivalent to the sum function:
total = sum(range(1,n+1))
But you can do away with any iteration altogether by using the formula:
total = int(n*(n+1)/2) # division causes float output so you have to convert back to an int
I don't know if you are supposed to create the initial data (with the missing item), so I added some lines to generate this sequence:
import random
n = 12 # or n = int(input('Enter n: ')) to get user input
# create a shuffled numeric sequence with one missing value
data = list(range(1,n+1))
data.remove(random.randrange(1,n+1))
random.shuffle(data)
print(data)
# create the corresponding reference sequence (without missing value)
data2 = list(range(1,n+1))
# find missing data with your algorithm
print("Missing value =", sum(data2)-sum(data))
Here is the output:
[12, 4, 11, 5, 2, 7, 1, 6, 8, 9, 10]
Missing value = 3

I need a function to list all multiples of 3 in the previous output in decending order

I'm trying to participate in a coding challenge, and I have part of the code complete, but now I need a function to list all multiples of 3 in the previous output in descending order.
Is there a function you could do that would run all the previous numbers printed in the triangle and divide it by 3,and then print the numbers that came out as a whole number from that calculation? Or some other similar task to come up with all the multiples of 3 up to line 50 in Pascal's Triangle?
def generate_pascals_triangle(rows):
triangle = [[1], [1, 1]]
if rows == 1:
return triangle[0]
else:
for row_number in range(2, rows):
triangle.append([1]*row_number)
for number in range(1, row_number):
triangle[row_number][number] = (triangle[row_number-1][number-1]+triangle[row_number-1][number])
triangle[row_number].append(1)
return triangle
def difference_between_rows(row, next_row):
row_len = 0
next_row_len = 0
for number in row:
string_number = str(number)
row_len += (len(string_number)+1)
for number in next_row:
string_number = str(number)
next_row_len += (len(string_number)+1)
return (next_row_len-1) - (row_len-1)
def print_pascals_triangle(triangle):
largest_element = triangle[-1][len(triangle[-1]) // 2]
element_width = len(str(largest_element))
def format_row(row):
return ' '.join([str(element).center(element_width) for element in row])
triangle_width = len(format_row(triangle[-1]))
for row in triangle:
print(format_row(row).center(triangle_width))
if __name__ == '__main__':
rows = 51
print_pascals_triangle(generate_pascals_triangle(rows))
Have you tried storing each output in a list?

Count occurances with if statement python

Think of the Unit Circle x 2. What I have done is create two lists, one for x and one for y, producing 500 pairs of random (x,y). Then I created r=x2+y2 in my while loop, where r is the radius and x2=x**2 and y2=y**2. What I want to be able to do is count the number of times r=<2. I assume my if statement needs to be in the while loop, but I don't know how to actually count the number of times the condition r=<2is met. Do I need to create a list for the r values?
import random
from math import *
def randomgen(N):
rlg1=[]
rlg2=[]
a=random.randint(0,N)
b=float(a)/N
return b
i=0
rlg=[]
rlg2=[]
countlist=[]
while i<500:
x=randomgen(100)*2
y=randomgen(100)*2
x2=x**2
y2=y**2
r=x2+y2
rlg.append(x)
rlg2.append(y)
print rlg[i],rlg2[i]
i+=1
if r<=2:
import random
from math import *
def randomgen(N):
rlg1=[]
rlg2=[]
a=random.randint(0,N)
b=float(a)/N
return b
i=0
rlg=[]
rlg2=[]
countlist=[]
amount = 0
while i<500:
x=randomgen(100)*2
y=randomgen(100)*2
x2=x**2
y2=y**2
r=x2+y2
rlg.append(x)
rlg2.append(y)
print rlg[i],rlg2[i]
i+=1
if r<=2:
amount += 1
You need two counters here. One for the total number of points (i) and one for the number of points that lie within your circle r <= 2 (I'm calling this one isInside). You only want to increment the isInside counter if the point lies within your circle (r <= 2).
i = 0
rlg = []
rlg2 = []
countlist = []
isInside = 0
while i < 500:
x=randomgen(100)*2
y=randomgen(100)*2
x2=x**2
y2=y**2
r=x2+y2
rlg.append(x)
rlg2.append(y)
print rlg[i],rlg2[i]
i+=1
if r <= 2:
# increment your isInside counter
isInside += 1

running a program over x amount of times

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

Categories

Resources