Python random numbers loop - python

Hey I have a class exercise that I'm stuck with and would appreciate any help. The program is supposed to random select a number between 1-5 and loop until all numbers are picked. Then it's supposed to repeat about 100 times to give an average of how many picks it takes to get all five numbers. I know how to use random.int, just not sure how to write a loop where it breaks when all 5 numbers are picked. Any sort of help would be great. Thank you

I would suggest you to use a Set. Each time a value between 1-5 is reached, put it in the your set, then when the size of the set is 5, break the loop.

This will do it:
from random import randint
a = []
for _ in range(100):
b = 0
c = set()
while len(c) < 5:
c.add(randint(1, 5))
b += 1
a.append(b)
d = round(sum(a)/len(a))
print("{}\nAverage loops: {}".format(c, d))
Documented version:
# Import the `randint` function from `random`.
from random import randint
# This will hold the results that will later be used to calculate the average.
a = []
# This loops 100 times (to get data for a calculation of the average).
for _ in range(100):
# This will be the number of times the while-loop loops.
b = 0
# This is a set to hold the choices of `random.randint`.
# When it reaches 5 items, all numbers from 1-5 have been found.
c = set()
# Loop while the length of the set is less than 5.
while len(c) < 5:
# Add a new random number to the set,
# If the number is already there, nothing happens.
c.add(randint(1, 5))
# Record a completed iteration of the while-loop.
b += 1
# Add the number of while-loop loops to `a`.
a.append(b)
# The average is calculated by dividing the sum of `a` by the length of `a`.
# It is then rounded to the nearest integer.
d = round(sum(a)/len(a))
# Print the results.
print("{}\nAverage loops: {}".format(c, d))
Sample output:
{1, 2, 3, 4, 5}
Average loops: 12
{1, 2, 3, 4, 5}
Average loops: 10
{1, 2, 3, 4, 5}
Average loops: 9

I would just do a while-loop that generates a random number between 1-5 until it gets the first number, t, logging the number of tries it took., logging the number of tries it took.hen do that with the next number, and when you're done find the average of how many tries it took.
Example:
total = 0
for i in range(100):
for n in range(1,6):
generatedNum = 0
while generatedNum != n:
#generate random number
total += 1
print (total/100)

Here is yet another way we may use:
import random
total = {1:0,2:0,3:0,4:0,5:0}
for k in xrange(100): #outter loop
trial = {}
n = 0 #counter
while n<5:
sample = random.randint(1,5) #sample
try:
trial[sample] += 1
except:
n += 1
trial[sample] = 1
for i in xrange(1,6): #accumulate the results
total[i] += trial[i]
which results in:
>>> total
{1: 221, 2: 255, 3: 246, 4: 213, 5: 243}

Related

Finding a more concise way to add values to empty list Python

I am new to Python and while my task is deemed correct, I know there is a more efficient way to write the code and am looking for advice.
My goal is to count the number of scores (between 1-6) of a dice roll and assign each number to a list. In this case I know the value of the dice roll 'N' - 1 will be the index at which it is added to the list but I am unsure as to how to go about writing it.
import random
dice = [0]*6
for roll in range(1001):
N = random.randint(1,6)
if N == 1:
dice[0] = dice[0] + 1
if N == 2:
dice[1] = dice[1] + 1
if N == 3:
dice[2] = dice[2] + 1
if N == 4:
dice[3] = dice[3] + 1
if N == 5:
dice[4] = dice[4] + 1
if N == 6:
dice[5] = dice[5] + 1
print(f' the number of times the dice rolled 1-6 is as follows {dice}')
You can use N-1 for the index of the list.
dice[N-1] += 1
When dealing with lists of random values, I recommend numpy:
import numpy as np
_, counts = np.unique(np.random.randint(1,7, 1000), return_counts=True)
Here you go:
dice = [0]*6
for roll in range(1001):
dice[random.randint(0, 5)] += 1
print(f' the number of times the dice rolled 1-6 is as follows {dice}')
The list is being indexed with N-1.
import random
a = random.sample(range(1, 1001), 6)
print(a)
This could brief a lot more what you are looking for
https://pynative.com/python-random-sample/

Is there a way to add and subtract numbers from a list sequentially?

I'm trying to add and subtract each number in a list like this 1 - 1/3 + 1/5 - 1/7 + 1/9. If you keep on doing this and then multiply the answer by 4 you get an aproximation of pi.
I have a list of odd numbers called ODD but im having trouble adding and subtracing as shown above
I literally just started coding in python today so this could be a simple mistake but I can't find anything online about it
Thanks,
Adam
import time
start_time = time.time()
EVEN = []
ODD = []
y = int(1.e2)
x = range(y)
#-----------------------------------------------------------------------------------------
for i in x:
if i%2 == 0:
print(i)
EVEN.append(i)
else:
print(i)
ODD.append(i)
oc = len(ODD)
ec = len(EVEN)
print("")
print(str(oc) + " " + "Odds Found!")
print(str(ec) + " " + "Evens Found!")
print("--- %s seconds to compute ---" % "{:.2f}".format(((time.time() - start_time))))
time.sleep(3) #START OF PROBLEM
for i in ODD:
fract = 1/ODD[i]-1/ODD[i+1]
sfract = fract + 1/ODD[i+2]
print(fract)
print(sfract)
Your problem is because this loop
for i in ODD:
iterates over elements in a list (for each loop). This is why ODD[i] would result in an index error or would calculate something else than what you're interested in. You should just use the variable i.
flag = True
for i in ODD:
if flag:
fract += 1 / i
else:
fract -= 1/ i
flag = not flag
Besides, since you write in Python I'd recommend using list comprehension:
EVEN = [i for i in x if i % 2 == 0]
ODD = [i for i in x if i % 2 == 1]
There is absolutely no need to use any lists in this program.
arbitrary_number = 1000
sign = 1
total = 0
for n in range(1, arbitrary_number, 2):
total += sign * 1.0 / n
sign = -sign
print(4*total)
I wrote this out with the intention of having each step be clear. There are easier ways to write this with less code. Remember that Python is made to be simple. There is usually one clear way to come up with a solution, but always try experimenting.
number = 0 #initialize a number. This number will be your approximation so set it to zero.
count = 0 #set a count to check for even or odd [from the formula] (-1)^n
for num in range(1,100,2): #skip even values.
"""
The way range works in this case is that you start with 1, end at 100 or an arbitrary
number of your choice and you add two every time you increment.
For each number in this range, do stuff.
"""
if count%2 == 0: #if the count is even add the value
number += 1/num #example add 1, 1/5, 1/9... from number
count += 1 #in order to increment count
else: #when count is odd subtract
number -= 1/num #example subtract 1/3, 1/7, 1/11... from number
count += 1 #increment count by one
number = number*4 #multiply by 4 to get your approximation.
Hope this helps and welcome to Python!
Let's examine the for loop:
for i in ODD:
fract = 1/ODD[i]-1/ODD[i+1]
sfract = fract + 1/ODD[i+2]
print(fract)
print(sfract)
since you declare fract & sfract inside the loop, they do not compute the sum, but only two and three terms of the sum, respectively. If you initialize the variables outside of the loop, their scope will allow them to accumulate the values.
For what you are doing, I would use numpy.float for those variables to prevent overflow.
If you need to add and subtract sequentially in a list, you can use the Python slice operation to create 2 lists with odd and even indexes.
# Example list
lst = [1, 2, 3, 4, 5, 6, 7, 8, 9]
# [1, 3, 5, 7, 9]
add_list = lst[0::2]
# [2, 4, 6, 8]
subtract_list = lst[1::2]
# Now you can add all the even positions and subtract all the odd
answer = sum(add_list) - sum(subtract_list) # Same as 1-2+3-4+5-6+7-8+9

Unique sums greater than a number

So I'm trying to write a code that takes a list of numbers between 1 and 10 and finds sums that are greater or equal than 10 and then remove those numbers from the list. Here's the twist: first you need to check if there is any 10 in the list, the any couple of numbers that sum to 10, then any 3 numbers and so on until 5. Also, the lower the numbers summed the better. So you need to get rid of most numbers when summing couples. So far I managed to do the couples:
n = input("How many numbers in the list? \n")
throw = []
for i in range(int(n)):
throw.append(random.randint(1, 10))
throw.sort()
increments = 0
print(throw)
increments += throw.count(10)
throw = list(filter(lambda i: i != 10, throw))
high = len(throw)-1
low = 0
acceptable_couples = []
get_rid = []
while low < high:
sums = throw[high] + throw[low]
if sums >= 10:
increments += 1
get_rid.append(throw[high])
get_rid.append(throw[low])
acceptable_couples.append((throw[high], throw[low]))
high -= 1
low += 1
else:
low += 1
for i in get_rid:
throw.remove(i)
I also did the pairs of 3 and was thinking to apply the same method for 4, and 5:
while len(throw) >= 3:
z = 0
x = list(itertools.combinations(throw, 3))
for couple in x:
if sum(couple) >= 10:
z += 1
i = list(couple)
increments += 1
for j in couple:
throw.remove(j)
break
else:
continue
if z == 0:
break
I was hoping to find a less messy way to do it. This works, but for large number of numbers it seems a lot of useless computation.
Any ideas?
In that case perhaps this would be a solution. In pseudo code:
Read list of numbers and sort from high to low
remove all numbers 10 from the list and add these as a solution
Loop until list is empty
take the largest number in the list (which is the first number as list is sorted) and remove it from the list
Check if by adding the smallest number we can get a sum greater or equal to 10 if not go to a bigger number until we complete the loop. Break loop if a solution is found, add to solutions and remove the element from the list that solved it.
if solved break and repeat the outer while loop with next biggest number in the list. If not solved then add the next biggest number to the sum and remove it from the list and check if we can find a solution adding smaller numbers running the for loop again
Code
import random
n = int(input("How many numbers in the list? \n"))
throw = [random.randint(1, 6) for _ in range(n)]
print(throw)
throw.sort(reverse=True)
print(throw)
list_of_solved_sets = []
# remove all numbers 10 from the list and add a solution
while throw and throw[0] == 10:
list_of_solved_sets.append([throw[0]])
del throw[0]
while throw:
# take the largest number in the set (which is the first number
# as list is sorted) and remove it from the list
solved_set = [throw[0]]
_sum = throw[0]
del throw[0]
while throw:
solved = False
# Check if by adding the smallest number we can get
# a sum greater or equal to 10 if not go to a bigger number
# until we complete the loop. Break loop if a solution is found, add
# to solutions and remove element from the list that solved it
for j in range(len(throw) - 1, -1, -1):
if _sum + throw[j] >= 10:
solved_set.append(throw[j])
del throw[j]
list_of_solved_sets.append(solved_set)
solved = True
break
# if solved break and repeat the outer while loop with next biggest number
# in the list. If not solved then add the next biggest number to the sum and
# check if we can find a solution adding smaller numbers running the for
#loop again
if solved:
break
else:
_sum += throw[0]
solved_set.append(throw[0])
del throw[0]
print('List of solved sets:')
for i, solved_set in enumerate(list_of_solved_sets):
print(f' {i+1}: {solved_set}')
Result example:
How many numbers in the list?
10
[3, 2, 5, 1, 6, 3, 4, 3, 2, 1]
[6, 5, 4, 3, 3, 3, 2, 2, 1, 1]
List of solved sets:
1: [6, 4]
2: [5, 3, 2]
3: [3, 3, 2, 1, 1]
Not sure if I understand your question correctly. My interpretation is that you have a set of numbers between 1 and 10 and you need to find the longest sub sets of numbers from this set that sum up to 10 or greater and then remove these numbers from the original set until you can not find any more sets with more than one number.
If this is the correct interpretation than the following should work:
import random
n = int(input("How many numbers in the list? \n"))
throw = [random.randint(1, 10) for _ in range(n)]
print(throw)
throw.sort()
list_of_solved_sets = []
sets_found = True
while sets_found:
_sum = 0
solved_set = []
solved_indexes = []
for index, element in enumerate(throw):
_sum += element
solved_set.append(element)
solved_indexes.append(index)
if _sum >= 10:
break
if len(solved_set) <= 1:
sets_found = False
else:
list_of_solved_sets.append(solved_set)
for index in reversed(solved_indexes):
del throw[index]
print('List of solved sets:')
for i, solved_set in enumerate(list_of_solved_sets):
print(f' {i+1}: {solved_set}')
Note you need to remove the indexes from the list throw in reversed order!

how to output my functions numeric values as a list in python

here is my function:
def seq_sum(n):
""" input: n, generate a sequence of n random coin flips
output: return the number of heads
Hint: For simplicity, use 1,0 to represent head,tails
"""
flip = 0
heads = 0
while flip <= n:
coin = random.randint(0,2)
flip += 1
if coin == 1:
heads += 1
print(heads)
the output looks like this:
55
1
0
2
1
and so on. but what I want is the number of heads, plus a LIST of the output:
55
[1, 0, 2, 1, .....]
when I tried print(list(heads))I get the following error message:
TypeError: 'int' object is not iterable
In your function, you are merely keeping track of the total number of heads and not their history. You need to create an iterable collection to hold the interim values, such as a list or Numpy Array.
import numpy as np
def seq_sum(n):
flips = np.random.randint(low=0, high=2, size=n)
return sum(flips), flips.tolist()
# Example usage.
total_heads, flips = seq_sum(n=10)
Note that the start and end points are inclusive and exclusive, respectively, for numpy's randint function.
Hope this code will do what you want
def seq_sum(n):
flips = [random.randint(0, 1) for _ in range(n)]
return sum(flips), flips
Usage
s, l = seq_sum(10)
From the comment in your code I can tell that the function should return only the number of heads so
def seq_sum(n):
return sum(random.randint(0, 1) for _ in range(n))
import random
# edit in place
def seq_sum(n):
""" input: n, generate a sequence of n random coin flips
output: return the number of heads
Hint: For simplicity, use 1,0 to represent head,tails
"""
flip = 0
heads = 0
seq = list()
while flip <= n:
coin = random.randint(0,2)
seq.append(coin)
flip += 1
if coin == 1:
heads += 1
print(heads,seq)
#solution 2
def seq_sum(n):
flip = 0
seq = list() #create a list to store every random value
while flip < n: # if want to generate n values, the while loop only need compare 0,1,2,...n-1 times, so you need <, not <=.
coin = random.randint(0,1) # coin has only two sides
seq.append(coin)
flip += 1
return seq
# print(heads) # it is not good idea to print data in function.
random_list = seq_sum(55)
head_num = sum(random_list)
I don't know if I understood correctly, but here's my quite simple solution.
import random
def seq_sum(n):
""" input: n, generate a sequence of n random coin flips
output: return the number of heads
Hint: For simplicity, use 1,0 to represent head,tails
"""
flip = 0
heads = 0
outcomes=[]
while flip < n:
coin = random.randint(0,2)
outcomes.append(coin)
flip += 1
if coin == 1:
heads += 1
print(heads)
print(outcomes)
--------
output in console:
>>>seq_sum(3)
>>>2
>>>[1, 2, 1]
when I tried print(list(heads))I get the following error message:
TypeError: 'int' object is not iterable
Let's start with here. heads is always an integer from beginning till the end. Thus, when you put list( ) around heads, Python is complaining that you are feeding list an integer, which is not iterable.
Takeaway 1: some objects can only take certain kinds of arguments.
Second stop: I want to have a list to store the heads and tails. What should I do? One way is to create a list to store it.
my_list = [] # or list()
To add to the list, you can use append method. append method adds one element to the end of the list.
my_list.append(1)
# now my_list is [1]
my_list.append(0)
# now my_list looks like [1, 0]
Third goal: I want to randomly generate 0s and 1s to represent tails and heads. Are you really doing what you want to do? Be careful about the functions you call, especially those you are not familiar with. Read about what do the functions do.
random.randint(a, b)
Return a random integer N such that a <= N <= b. -- documentation for randint
randint(0, 2) will generate 0, 1, 2 randomly, which can represent head, tail, and... ohhh we don't have 3 things to represent.
Goal 4: Do you want to return/save the values for later use? or just print it out? Think about it and make the decision. Do you know you can turn 2 things/more at a time?
def bar():
return 1, 2
c = bar() # c is a tuple that holds two values, 0 and 1 now!
# c[0] == 1 # access the first element with index 0
# c[1] == 2
Hope with these, you can code your own answer.

Sum of Even Fibonacci Numbers < X

I'm working on this one and I seem to have a working solution but I have difficulty understanding its behaviour.
Here is what I have.
#!/usr/bin/python
def even_fib_sums(limit):
number = 1
last = 0
before_last = 0
total = 0
for counter in range (0,limit):
before_last = last
last = number
number = before_last + last
if not number % 2:
total += number
yield total
print sum(even_fib_sums(4000000))
I'm new to programming but it makes sense to me that this is not very effective considering I need to cycle through all 4000000 numbers in the range.
If I use the same approach in generating the Fibonacci sequence up to 5 as follows, you will see the results below.
def generate_fib(limit):
number = 1
last = 0
before_last = 0
total = 0
for counter in range (0,limit):
before_last = last
last = number
number = before_last + last
print number
generate_fib(5)
Result: 1,2,3,5,8
Of these numbers in the result, only 2 and 8 % 2 == 0.
The sum should be 10 but I am returning 12 if I am to use the first snippet above. Why so?
By considering the terms in the Fibonacci sequence whose values do not exceed four million, find the sum of the even-valued terms.
You only need to loop until you hit a fib that is > 400000 not the 4 millionth fibonacci number which your code is trying to do, you can simplify to a using generator function with sum, only yielding even numbers and breaking the loop when you hit a fibonacci number > 4000000:
def fib(n):
a, b = 0, 1
while a <= n:
a, b = b, a + b
if not b & 1:
yield b
print(sum(fib(4000000)))
It takes a fraction of a second to compute:
In [5]: timeit sum(fib(4000000))
100000 loops, best of 3: 6 µs per loop
trying to timeit even_fib_sums(4000000) is still running after a few minutes.
by using for counter in range(0, limit) you are having 'limit' iteration in your function. for example, if your 'limit' variable is 10, you won't have the sum of even fibonachi numbers that are less than 10, but you will have the sum of the first 10 fibonachi numbers that are even.
To make your code works properly, you need to remplace for counter in range(0, limit) by while last < limit, and each time you find that last is even, you add it to total.
You can probably clean up that generating function a bit. Here is how I would write it.
def fib(x):
a = 1
b = 1
yield a
yield b
a,b = b,a+b
while b<=x:
yield b
a,b = b,a+b
This will give you a generating function which will give you all Fibonacci numbers less than or equal to x (we should be a little more careful here, as we will return the first two numbers no matter what).
Then we can just do
sum(x for x in fib(4000000) if x%2==0)
You should change your code to just yield the number, not the sum or just change yield to return, and remove the sum() keyworkd like this:
def even_fib_sums(limit):
number = 1
last = 0
before_last = 0
total = 0
for counter in range (0,limit):
before_last = last
last = number
number = before_last + last
if not number % 2:
total += number
return total
print even_fib_sums(5)
In the first code snippet, you sum the total of round numbers, instead of just yielding the number. If you expect to get 10 in your first snippet for an input of 5, you should amend the code in either of the following ways (not trying to be efficient here, just to fix the problem):
...
number = before_last + last
if not number % 2:
yield number
print sum(even_fib_sums(4000000))
or
...
number = before_last + last
if not number % 2:
total += number
return total
print even_fib_sums(4000000)

Categories

Resources