Basic program generating random numbers Python - python

I want to create a program that will take a positive integer n, then create a list consisting of n random numbers between 0 and 9. Once I find that, I want to return the average of those numbers. Am I on the right track?
import random
def randomNumbers(n):
n > 0
myList = random.randrange(0,9)
I know I haven't gotten to the second part yet.. but is this how I start out?
This is my final code:
import random
def randomNumbers(n):
myList = []
for i in range(n):
myList.append(random.randrange(0, 9))
return sum(myList)/len(myList)
Could someone direct me to a page where it talks about a for and while loops and when to use them?

The equals sign (=) is only used to set the value of the "entire variable" (like myList). You want a list, which will then have values added to it, so start with this:
myList = []
to make it an empty list.
Now you had the right idea about repeating something while n > 0- but the ideal way is to use a for loop:
for i in range(n): # repeats the following line(s) of code n times
myList.append(random.randrange(0,9))
To find the average, take the sum and divide by the number of items (n).
If you are using Python 2.x, then note that an integer divided by another integer will round to an integer, so you should convert into a float (decimal) before division:
average = sum(myList)*1.0/n
For Python 3.x, int/int gives a float like you might expect:
average = sum(myList)/n
To return a value, use the return statement:
return average

It helps to break down what you're trying to do, if it's too complicated in a single explanation.
Take a positive integer, n
create a list of n length
each element should be a number 0-9
return the average of that list.
Let's tackle this one at a time:
take a positive integer, n
def randomNumbers(n):
if type(n)==int and n>0:
when you say def randomNumbers(n): you're saying
Hey, computer, this is a function called "randomNumbers",
and it's going to be called with a single thing in parentheses
and we're going to call that `n` from now on.
Here's what that function does:
But you haven't ensured that n is an integer greater than 0. It's just a thing. So we need to ensure that it is. if type(n)==int and n>0: does that by checking that the type of n is int and that n's value is positive (greater than 0).
That's the first bullet point done. Next is creating a list of n length with each element being an integer numbered 0-9. These should be random[1].
result=list()
for i in range(n):
result.append(random.randint(0,9))
This is less complicated than it seems. You start by creating a list that you'll call result (or whatever you want, I don't care). The for loop is just saying:
Hey, computer, you're gonna do the same thing a number of times,
and that number is "until you've counted from 0 to n times".
And when you do that, "i" is going to represent where you are
in that "0 to n" range. Here's what you're gonna do all those times:
So what are you going to do n times? You're going to append a random integer between 0 and 9 to that list we just called result. That's what result.append(random.randint(0,9)) does.
So next you want to return the average of that list. Well, the average of a list is the sum of the numbers in the list divided by the length.
return sum(result)/float(len(result))
sum and len can take any iterable, like a list, or a set, or whatever you please, and give you the sum, length, or whatever else you ask for. These are great tools to learn about. So do it. Elsewhere, preferably, frankly.
Now, if you've been really attentive, you'll see that so far we have this:
import random # I added this secretly, sorry!
def randomNumbers(n):
if type(n)==int and n>0:
result=list()
for i in range(n):
result.append(random.randint(0,9))
return sum(result)/float(len(result))
Which is great! That's what you need; try print(randomNumbers(5)) and you'll get exactly what you're looking for: the average of a bunch of random numbers.
But what if you try print(randomNumbers('foo'))? You probably get None, right? That's because it didn't fit in with the if statement we wrote, and so it never went down that path! You need to write an else statement so things that aren't positive integers still get some love.
else:
return "That's no good. Try a positive integer instead"
Stupid, but it works. Someday you'll learn about raising exceptions and all that smooth Jazz, but until then, it's fine just to say
Hey, computer, if n wasn't up to my stratospheric expectations,
then just spit back this message. I'll understand.
So at the end of the day you've got
import random
def randomNumbers(n):
if type(n)==int and n>0:
result=list()
for i in range(n):
result.append(random.randint(0,9))
return sum(result)/float(len(result))
else:
return "That's no good. Try a positive integer instead"
There's some stuff you can do with this code to make it more efficient. To make you curious, I'll give an example:
from random import randint
def randy(n:int):
return sum({randint(0,9) for i in range(n)})/n if n>0 else "Try again."
That gets into list comprehensions, sets, function annotations, and other stuff that you don't need to worry about. And frankly, that line of code might be too convoluted for good "Pythonic" code, but it's possible, which is cool.
Keep at it, and don't get discouraged. Python makes an effort to explain what you did wrong, and the community is generally pretty good if you've done your due diligence. Just don't abuse them(/us) by asking for help without seeking answers on your own first.
[1]technically they're pseudorandom but true randomness is hard to produce.

You are not on the right track. See this variate for the track.
import random
def randomNumbers(n):
l = random.sample(xrange(10), n)
return sum(l)/len(l)

Could be done more concisely with a list comprehension:
myList = [randrange(0, 9) for x in xrange(n)]
average = sum(myList) / len(myList)

You should think about making use of Numpy. This would make your task easy.
import numpy as np
def myfunc(n):
x = np.random.randint(low=0, high=10, size=n)
return np.mean(x)

Related

How to find the numbers that their sum equal to a given number?

This seems like a repost but it's not. Most people asked for the pair numbers. I need all numbers, not just two. Like n0+n1+n2+n3+n4+...+n100=x And also, each number must be lower than the number comes before him. For example for 8 output must be:
There are 5:
7+1
5+3
6+2
5+2+1
4+3+1
In here you can see 5>3 and 6>2 and vice versa.
I came so close with this code. I found this on stackoverflow, and then improved it to according to my needs. However I tested it on a super computer, that if you give 200 to this, it says it's wrong. I just don't get it how could this be wrong? Please can someone help me improve this? With my pc it takes a lot of time. Give this 50, and it will still take hours. Here is my code:
from itertools import combinations
def solution(N):
array=[]
counter=0
for i in range(N):
if(i==0):
continue
array.append(i)
for K in range(N):
for comb in combinations(array, K):
if sum(comb) == N:
counter+=1
#print(comb) uncomment this if you like, it prints pairs.
return counter
res=solution(50)
print(res)
By the way, can I do it without itertools at all? Maybe it causes problems.
I think I may have found a solution, I will share it and maybe you can check with me if it is correct :) I assumed that all numbers must be smaller than N.
To start, I am not so sure your code is necessarily wrong. I think it produces the right answers but maybe you should consider what is happening and why your code takes so long. Currently, you are checking for all combination of sums, but by iterating in another way you can exclude many possibilities. For example, suppose my goal is to find all sums that result in a total of 8.
Suppose I now have a sum of 6 + 5 = 11. Currently, you are still checking all other possibilities when adding other numbers (i.e. 6 + 5 + 4 and 6 + 5 + 3 etc etc), but we already know they all will be >8, hence we do not even have to compute them.
As a solution we can start with the highest number smaller than our goal, i.e. 7 in our example. Then we will try all combinations with numbers smaller than this. As soon as our sum gets bigger than 8, we do not follow the trail further. This sounds a lot like recursing, which is how I currently implemented it.
To get an idea (I hope it is correct, I haven't tested it extensively):
def solution(goal, total_solutions=0, current_sum=0.0, current_value=None):
if current_value is None:
current_value = goal
# Base condition
if current_sum >= goal:
if current_sum == goal:
return total_solutions + 1
return total_solutions
for new_value in range(current_value - 1, 0, -1):
total_solutions = solution(
goal, total_solutions, current_sum + new_value, new_value
)
return total_solutions
res = solution(8)
print(res) # prints 5
So as an answer to your question, yes you can do it with itertools, but it will take a long time because you will be checking a lot of sums of which you do not really need to check.
I compared this program with yours and it produces the same output up until N=30. But then your code really starts to blow up so I won't check further.
The Answer you're looking for is in the post : programming challenge: how does this algorithm (tied to Number Theory) work?
The classical method start taking some time at the 100th step but the use of memoization also called dynamic programming reduces the complexity drastically and allows your algorithm to compute at the 4000th step without taking any time at all.

sum of cubes using formula

Given
\sum_{k=0}^{n}k^3 = \frac{n^2(n+1)^2}{4}
I need to compute the left hand side. I should make a list of the first 1000 integer cubes and sum them.
Then I should compute the right hand side and to the same.
Also, I am supposed to compare the computational time for the above methods.
What I've done so far is:
import time
start = time.clock()
list = []
for n in range(0,1001):
list.append(n**3)
print(list)
print("List of the first 1000 integer cubes is:",list, "and their sum is:", sum(list))
stop = time.clock()
print("Computation time: ",stop-start, "seconds.")
a=0
for n in range (0,1001):
a=(int)(n*(n+1)/2)
print ("Sum of the first 1000 integer cubes is:",a*a)
First part for the left hand side works fine, but the problem is the right hand side.
When I type n=4, I will get the same result for the both sides, but problem occurs when n is big, because I get that one side is bigger than the other, i.e. they are not same.
Also, can you help me create a list for the right hand side, I've tried doing something like this:
a=[]
for n in range (0,10):
a.append(int)(n**2(n+1)**2/4)
But it doesn't work.
For the computational time, I think I am supposed to set one more timer for the right hand side, but then again I am not sure how to compare them.
Any advice is welcome,
Ok, I think what you tried in a for loop is completely wrong. If you want to prove the formula "the hard way" (non-inductive way it is) - you need to simply sum cubes of n first integers and compare it against your formula - calculated one time (not summed n times).
So evaluate:
n=100
s=0
for i in range(1,n+1):
s+=i**3
###range evaluates from 1 till n if you specify it till n+1
s_ind=(n**2)*((n+1)**2)/4
print(s==s_ind)
Otherwise if you are supposed to use induction - it's all on paper i.e. base condition a_1=1^3=((1)*(2)^2)/4=1 and step condition i.e. a_n-a_(n-1)=sum(i^3)[i=1,...,n]-sum(j^3)[i=1,...,n-1]=n^3 (and that it also holds assuming a_n=your formula here (which spoiler alert - it does ;) )
Hope this helps.

Code finding the first triangular number with more than 500 divisors will not finish running

Okay, so I'm working on Euler Problem 12 (find the first triangular number with a number of factors over 500) and my code (in Python 3) is as follows:
factors = 0
y=1
def factornum(n):
x = 1
f = []
while x <= n:
if n%x == 0:
f.append(x)
x+=1
return len(f)
def triangle(n):
t = sum(list(range(1,n)))
return t
while factors<=500:
factors = factornum(triangle(y))
y+=1
print(y-1)
Basically, a function goes through all the numbers below the input number n, checks if they divide into n evenly, and if so add them to a list, then return the length in that list. Another generates a triangular number by summing all the numbers in a list from 1 to the input number and returning the sum. Then a while loop continues to generate a triangular number using an iterating variable y as the input for the triangle function, and then runs the factornum function on that and puts the result in the factors variable. The loop continues to run and the y variable continues to increment until the number of factors is over 500. The result is then printed.
However, when I run it, nothing happens - no errors, no output, it just keeps running and running. Now, I know my code isn't the most efficient, but I left it running for quite a bit and it still didn't produce a result, so it seems more likely to me that there's an error somewhere. I've been over it and over it and cannot seem to find an error.
I'd merely request that a full solution or a drastically improved one isn't given outright but pointers towards my error(s) or spots for improvement, as the reason I'm doing the Euler problems is to improve my coding. Thanks!
You have very inefficient algorithm.
If you ask for pointers rather than full solution, main pointers are:
There is a more efficient way to calculate next triangular number. There is an explicit formula in the wiki. Also if you generate sequence of all numbers it is just more efficient to add next n to the previous number. (Sidenote list in sum(list(range(1,n))) makes no sense to me at all. If you want to use this approach anyway, sum(xrange(1,n) will probably be much more efficient as it doesn't require materialization of the range)
There are much more efficient ways to factorize numbers
There is a more efficient way to calculate number of factors. And it is actually called after Euler: see Euler's totient function
Generally Euler project problems (as in many other programming competitions) are not supposed to be solvable by sheer brute force. You should come up with some formula and/or more efficient algorithm first.
As far as I can tell your code will work, but it will take a very long time to calculate the number of factors. For 150 factors, it takes on the order of 20 seconds to run, and that time will grow dramatically as you look for higher and higher number of factors.
One way to reduce the processing time is to reduce the number of calculations that you're performing. If you analyze your code, you're calculating n%1 every single time, which is an unnecessary calculation because you know every single integer will be divisible by itself and one. Are there any other ways you can reduce the number of calculations? Perhaps by remembering that if a number is divisible by 20, it is also divisible by 2, 4, 5, and 10?
I can be more specific, but you wanted a pointer in the right direction.
From the looks of it the code works fine, it`s just not the best approach. A simple way of optimizing is doing until the half the number, for example. Also, try thinking about how you could do this using prime factors, it might be another solution. Best of luck!
First you have to def a factor function:
from functools import reduce
def factors(n):
step = 2 if n % 2 else 1
return set(reduce(list.__add__,
([i, n//i] for i in range(1, int(pow(n,0.5) + 1)) if n % i
== 0)))
This will create a set and put all of factors of number n into it.
Second, use while loop until you get 500 factors:
a = 1
x = 1
while len(factors(a)) < 501:
x += 1
a += x
This loop will stop at len(factors(a)) = 500.
Simple print(a) and you will get your answer.

Singpath Python Error. "Your code took too long to return."

I was playing around with the Singpath Python practice questions. And came across a simple question which asks the following:
Given an input of a list of numbers and a high number,
return the number of multiples
of each of those numbers that are less than the maximum number.
For this case the list will contain a maximum of 3 numbers
that are all relatively prime to each other.
I wrote this simple program, it ran perfectly fine:
"""
Given an input of a list of numbers and a high number,
return the number of multiples
of each of those numbers that are less than the maximum number.
For this case the list will contain a maximum of 3 numbers
that are all relatively prime to each other.
>>> countMultiples([3],30)
9
>>> countMultiples([3,5],100)
46
>>> countMultiples([3,5,7],30)
16
"""
def countMultiples(l, max):
j = []
for num in l:
i = 1
count = 0
while num * i < max:
if num * i not in j:
j.append(num * i)
i += 1
return len(j)
print countMultiples([3],30)
print countMultiples([3,5],100)
print countMultiples([3, 5, 7],30)
But when I try to run the same on SingPath, it gave me this error
Your code took too long to return.
Your solution may be stuck in an infinite loop. Please try again.
Has anyone experienced the same issues with Singpath?
I suspect the error you're getting means exactly what it says. For some input that the test program gives your function, it takes too long to return. I don't know anything about singpath myself, so I don't know exactly how long that might be. But I'd guess that they give you enough time to solve the problem if you use the best algorithm.
You can see for yourself that your code is slow if you pass in a very large max value. Try passing 10000 as max and you may end up waiting for a minute or two to get a result.
There are a couple of reasons your code is slow in these situations. The first is that you have a list of every multiple that you've found so far, and you are searching the list to see if the latest value has already been seen. Each search takes time proportional to the length of the list, so for the whole run of the function, it takes quadratic time (relative to the result value).
You could improve on this quite a lot by using a set instead of a list. You can test if an object is in a set in (amortized) constant time. But if j is a set, you don't actually need to test if a value is already in it before adding, since sets ignore duplicated values anyway. This means you can just add a value to the set without any care about whether it was there already.
def countMultiples(l, max):
j = set() # use a set object, rather than a list
for num in l:
i = 1
count = 0
while num * i < max:
j.add(num*i) # add items to the set unconditionally
i += 1
return len(j) # duplicate values are ignored, and won't be counted
This runs a fair amount faster than the original code, and max values of a million or more will return in a not too unreasonable time. But if you try values larger still (say, 100 million or a billion), you'll eventually still run into trouble. That's because your code uses a loop to find all the multiples, which takes linear time (relative to the result value). Fortunately, there is a better algorithm.
(If you want to figure out the better approach on your own, you might want to stop reading here.)
The better way is to use division to find how many times you can multiply each value to get a value less than max. The number of multiples of num that are strictly less than max is (max-1) // num (the -1 is because we don't want to count max itself). Integer division is much faster than doing a loop!
There is an added complexity though. If you divide to find the number of multiples, you don't actually have the multiples themselves to put in a set like we were doing above. This means that any integer that is a multiple of more than than one of our input numbers will be counted more than once.
Fortunately, there's a good way to fix this. We just need to count how many integers were over counted, and subtract that from our total. When we have two input values, we'll have double counted every integer that is a multiple of their least common multiple (which, since we're guaranteed that they're relatively prime, means their product).
If we have three values, We can do the same subtraction for each pair of numbers. But that won't be exactly right either. The integers that are multiples of all three of our input numbers will be counted three times, then subtracted back out three times as well (since they're multiples of the LCM of each pair of values). So we need to add a final value to make sure those multiples of all three values are included in the final sum exactly once.
import itertools
def countMultiples(numbers, max):
count = 0
for i, num in enumerate(numbers):
count += (max-1) // num # count multiples of num that are less than max
for a, b in itertools.combinations(numbers, 2):
count -= (max-1) // (a*b) # remove double counted numbers
if len(numbers) == 3:
a, b, c = numbers
count += (max-1) // (a*b*c) # add the vals that were removed too many times
return count
This should run in something like constant time for any value of max.
Now, that's probably as efficient as you need to be for the problem you're given (which will always have no more than three values). But if you wanted a solution that would work for more input values, you can write a general version. It uses the same algorithm as the previous version, and uses itertools.combinations a lot more to get different numbers of input values at a time. The number of products of the LCM of odd numbers of values get added to the count, while the number of products of the LCM of even numbers of values are subtracted.
import itertools
from functools import reduce
from operator import mul
def lcm(nums):
return reduce(mul, nums) # this is only correct if nums are all relatively prime
def countMultiples(numbers, max):
count = 0
for n in range(len(numbers)):
for nums in itertools.combinations(numbers, n+1):
count += (-1)**n * (max-1) // lcm(nums)
return count
Here's an example output of this version, which is was computed very quickly:
>>> countMultiples([2,3,5,7,11,13,17], 100000000000000)
81947464300342

Why does this Python 3.3 code not work? digc not defined

It prints diga and digb but doesnt work with c! Any help? It's supposed to be a Denary to Binary converter but only 1-64, once i've cracked the code will increase this! Thanks so much
denaryno=int(input("Write a number from 1-64 "))
if 64%denaryno > 0:
diga=0
remaindera=(64%denaryno)
if 32/denaryno<1:
digb=1
remainderb=(denaryno%32)
else:
digb =0
if 16/remainderb<1:
digc=1
remainderc=(denaryno%16)
else:
digc=0
if 8/remainderc<1:
digd=1
remainderd=(denaryno%8)
else:
digd=0
if 4/remainderd<1:
dige=1
remaindere=(denary%4)
else:
dige=0
if 2/remaindere<1:
digf=1
remainderf=(denary%2)
else:
digf=0
if 1/remainderf<1:
digg=1
remainderg=(denary%1)
else:
digg=0
print (str(diga)+str(digb))
You only set digc in one of the top if/else statement. If 32/denaryno<1 is True, you don't set digc at all.
Set digc at the top of the function (to 0 or whatever else you want it to be). This applies to all the digit variables, digd, dige, etc.
What you really should do, instead, is use a list of digits, and append either a 0 or a 1 to that list every time you divide the number by a factor.
You may want to take a look at the divmod() function; it returns both the quotient and the remainder. You could also do with some looping here to slash the number of if statements needed here:
number = int(input("Write a number from 1-64 "))
digits = []
factor = 64
while number:
quotient, number = divmod(number, factor)
digits.append(quotient)
factor //= 2
print(''.join(map(str, digits)))
Wow that was a lot of work, you don't have to do all that.
def bin_convert(x, count=8):
return "".join(map(lambda y:str((x>>y)&1), range(count-1, -1, -1)))
here are the functions comprising this one from easy->important
str() returns a string
range() is a way to get a list from 1 number to another. Written like this range(count-1, -1, -1) counts backwards.
"".join() is a way to take an iterable and put the pieces together.
map() is a way to take a function and apply it to an iterable.
lambda is a way to write a function in 1 line. I was being lazy and could have written another def func_name(y) and it would have worked just as well.
>> is a way to shift bits. (which I believe understanding this one is the key component to understanding your problem)

Categories