find least common multiple of numbers 1-20 - python

I am having some trouble with this algorithm. I am attempting to find the least common multiple for a given range of numbers. The following functions find the factors of a number, count the different factors in the number, counts the factors so that I can find the lcm of the range of numbers based on this algorithm, and then finally calculates the lcm; however, if you run this code, the print statement at the bottom does not print the correct answer. Instead I get a number that I KNOW for sure is not right. I mainly need a second set of eyes to point out the problem with this code. Can anyone help?
from collections import defaultdict
def factors_of(number):
factors = [];
i = 2
while number >= 2:
if number % i == 0:
factors.append(i)
number = number / i
else:
i += 1
return factors
def count_factors(number):
count = {}
factors = factors_of(number)
for factor in factors:
if not factor in count:
count[factor] = 1
else:
count[factor] += 1
return count
def count_factors_of_numbers_in_range(start, stop):
count = defaultdict(int)
for number in range(start, stop):
factor_count = count_factors(number)
for key in factor_count:
if count[key] < factor_count[key]:
count[key] = factor_count[key]
return dict(count)
def find_lcm_of_numbers_in_range(start, stop):
count = count_factors_of_numbers_in_range(start, stop)
lcm = 1
for key in count:
total = count[key] * key
lcm = total * lcm
return lcm
print find_lcm_of_numbers_in_range(1, 21)

why can't you simply find gcd by euclid's algorithm and the multiply the numbers and divide by gcd to find LCM?
def decorator(d):
"""This is a decorator that will decorate all decorators. This will add update_wrapper
to all decorators.
(fun) -> fun
"""
def _d(f):
return update_wrapper(d(f), f)
return update_wrapper(_d, d)
#decorator
def nary(f):
"""This is docp implementation of n_ary function above.
(function) -> function
Tue-23-April-2013
"""
def n_ary(x, *args):
if len(args) == 0:
return x
return f(x, n_ary(*args))
return n_ary
#nary
def gcd(a, b):
"""Calculate the Greatest Common Divisor of a and b.
Unless b==0, the result will have the same sign as b (so that when
b is divided by it, the result comes out positive).
"""
while b:
a, b = b, a%b
return a

I figured out what I did wrong. I guess I just needed a good night's sleep.
The problem did not lie in a quirk with Python (which was what I thought this might be) but in my own implementation of the algorithm. In my code
def find_lcm_of_numbers_in_range(start, stop):
count = count_factors_of_numbers_in_range(start, stop)
lcm = 1
for key in count:
total = count[key] * key
lcm = total * lcm
return lcm
I messed up multiplying all of the numbers together in the statement total. Instead of multiplying the number 2 by the number 4, I needed to multiply 2 by itself 4 times (2 ** 4). By simply tweaking the code to look like
def find_lcm_of_numbers_in_range(start, stop):
count = count_factors_of_numbers_in_range(start, stop)
lcm = 1
for key in count:
total = key ** count[key]
lcm = total * lcm
return lcm
everything worked out and I am now happy. :)

Related

Nearest Square Function with Python

I have this sample quiz question but not to sure how to approach it with while loops.
Implement the nearest_square function. The function takes an integer argument limit, and returns the largest square number that is less than limit.
A square number is the product of an integer multiplied by itself, for example 36 is a square number because it equals 6*6.
There's more than one way to write this code, but I suggest you use a while loop!
Here is a test case you can copy to test your code. Feel free to write additional tests too!
test1 = nearest_square(40)
print("expected result: 36, actual result: {}".format(test1))
I have managed to solve it. Thank you.
def nearest_square(limit):
limit = limit ** (0.5)
y = int (limit)
while y < limit :
y = y*y
return y
test1 = nearest_square(40)
print("expected result: 36,actual result:{}".format(test1))
Try using the following method to return the nearest square given the limit parameter:
def nearest_square(limit):
answer = 0
while (answer+1)**2 < limit:
answer += 1
return answer**2
Normally, it's more efficient to approach this kind of questions mathematically (maybe not for low inputs but certainly yes for pretty big numbers). That said, we have a good tool at hand: the square root.
If computing the square root of any number, n, yields a double value whose decimal part is fully composed by zeroes then your number is a perfect square (square of an integer).
Interestingly (and this is more related to your question), if you choose another number (that is not a perfect square) and apply a rounding operation (floor or ceil) you'll get the closest square (lower or bigger).
An example:
n = 24
sqrt = math.sqrt(n) # sqrt(24) = 4.898979485566356...
closest = [math.floor(sqrt)**2, math.ceil(sqrt)**2] # closest = [16, 25]
this is how i did it with while loop:
def nearest_square(value):
i = 2
while i < value:
square = i*i
if square == value:
return square
i+=1
value-=1
print (nearest_square(40))
def nearest_square(value):
i = 1
result = 1
while (result < value):
if (result == value):
return result
i+=1
result = i*i
return (i-1)*(i-1)
print (nearest_square(82))
Here is my code:
`
def nearest_square(limit):
while limit > 3:
i = 2
while i <= limit//2:
square = i*i
if square == limit:
return square
else:
i += 1
limit -= 1
return 1
`
Here's what i did.
def nearest_square(limit):
y = 0
while y**2 < limit:
y+=1
if y**2 == limit:
return(y)
return(y-1)
print(nearest_square(40))
Here is my implementation of it.
this one is with while loop
def near1(limit):
i = 1
square = 1
while (i*i) < limit:
square = i*i
i = i+1
return square
but the easiest one is below.
Simple math and modulo
import math
def near(limit):
i = int(math.pow(limit, .5))
return i*i
This is what i did.
import math
def nearest_square(limit):
a = math.sqrt(limit)
while type(a) != type(int()):
limit -=1
return limit

Python 3 Project Euler Run Time

This is my solution to the Project Euler Problem 3:
def max_prime(x):
for i in range(2,x+1):
if x%i == 0:
a = i
x = x/i
return a
max_prime(600851475143)
It takes too much time to run. What's the problem?
There are several problems with your code:
If you're using Python 3.x, use // for integer division instead of / (which will return a float).
You solution doesn't account for the multiplicity of the prime factor. Take 24, whose factorization is 2*2*2*3. You need to divide x by 2 three times before trying the next number.
You don't need to try all the values up to the initial value of x. You can stop once x has reached 1 (you know you have reached the highest divisor at this point).
Once you solve these three problems, your solution will work fine.
==> projecteuler3.py
import eulerlib
def compute():
n = 600851475143
while True:
p = smallest_prime_factor(n)
if p < n:
n //= p
else:
return str(n)
# Returns the smallest factor of n, which is in the range [2, n]. The result is always prime.
def smallest_prime_factor(n):
assert n >= 2
for i in range(2, eulerlib.sqrt(n) + 1):
if n % i == 0:
return i
return n # n itself is prime
if __name__ == "__main__":
print(compute())
Your solution is trying to iterate up to 600851475143, which isn't necessary. You only need to iterate up to the square root of the largest prime factor.
from math import sqrt
def max_prime_factor(x):
i = 2
while i ** 2 <= x:
while x % i == 0: # factor out ALL multiples of i
x //= i
i += 1
return x
print(max_prime_factor(600851475143))

Python function to approximate mathematical value of e

I am writing a function to approximate the mathematical value of e.
We are told to use the factorial function and the inverse function above. It is also suggested to use map.
I have this so far, but it gives me an error saying: ValueError: factorial() only accepts integral values.
def inverse(n):
"""Returns the inverse of n"""
return 1 / n
def e(n):
"""Approximates the mathematical value e"""
lst = range(1, n+1)
lst2 = map(inverse, lst)
lst3 = map(math.factorial, lst2)
return sum(lst3)
Could someone point me in the right direction please?
e can be defined by Σ(1/k!), where k = 0 .. ∞.
So, for each k,
compute k!
invert
add to total
It looks like you're doing the inversion before the factorial instead of after, and starting from 1 instead of 0.
Note that this is not the most efficient way of doing this computation, as the factorial is unnecessarily being computed from scratch for each k.
This is now working for me. I needed to change the range from (1, n+1) to (0, n+1) and reverse the order of doing the factorial first and then doing the inverse.
def inverse(n):
"""Returns the inverse of n"""
return 1 / n
def e(n):
"""Approximates the mathematical value e"""
lst = map(math.factorial, range(0, n+1))
return sum(map(inverse, lst))
As everyone else pointed out:
You are missing the first term in the series which is 1.
In python, the division gives you an integer value if both numbers are integers. i.e. 1/2 == 0.
You need something like this:
def inverse(n):
"""Returns the inverse of n"""
# Using 1 as a float makes the division return a float value.
return 1. / n
def e(n):
"""Approximates the mathematical value e"""
lst = range(1, n+1) # k=1...n
lst2 = map(math.factorial, lst)
return 1 + sum(map(inverse, lst2))
You can compare your approximation against math.exp:
>>> abs(math.exp(1) - e(20)) < 1e-10
True
I has some fun with that question, using generators and decorators. First, you can create a generator to yield consecutively more precise values of e:
def compute_e():
currentFactorial = 1
currentSum = 1
for i in itertools.count(start=1):
currentFactorial *= i
currentSum += 1/currentFactorial
yield currentSum
And, after that, I create a decorator to find a fixed point (with a maximum number of iterations, and wanted precision) :
def getFixedPoint(gen, maxiter=10000, precision=0):
def mywrap(*args, **kwargs):
instanceGen = gen(*args, **kwargs)
prevValue = next(instanceGen)
for n, value in enumerate(instanceGen):
if (value - prevValue < precision) or (n > maxiter):
return value
else:
prevValue = value
return mywrap
which gives me stuff like this:
In [83]: getFixedPoint(compute_e)()
Out[83]: 2.7182818284590455
In [84]: getFixedPoint(compute_e, maxiter=5)()
Out[84]: 2.71827876984127
In [85]: getFixedPoint(compute_e, precision = 0.001)()
Out[85]: 2.7182539682539684
Of cours, now I can change my way of computing each successive value of e, for example by using from decimal import Decimal:
#getFixedPoint
def compute_e():
currentFactorial = Decimal(1)
currentSum = Decimal(1)
for i in itertools.count(start=1):
currentFactorial *= i
currentSum += 1/currentFactorial
yield currentSum
compute_e()
Out[95]: Decimal('2.718281828459045235360287474')

An Explanation for the totient finder in this program

I need an explanation for the program suggested in the edit in the first answer over here. It is a program to find the totients of a range of numbers. Can somebody provide a simple explanation? (Ignore the summation part for now, I need to find out how the init method finds the totients.) I know there is an explanation in the answer, but that is an explanation for different programs, I need an explanation for this particular one.
class Totient:
def __init__(self, n):
self.totients = [1 for i in range(n)]
for i in range(2, n):
if self.totients[i] == 1:
for j in range(i, n, i):
self.totients[j] *= i - 1
k = j / i
while k % i == 0:
self.totients[j] *= i
k /= i
def __call__(self, i):
return self.totients[i]
if __name__ == '__main__':
from itertools import imap
totient = Totient(10000)
print sum(imap(totient, range(10000)))
It's a variant of the Sieve of Eratosthenes for finding prime numbers.
If you want to know the totient of a single number n, the best way to find it is to factor n and take the product of 1 less than each factor; for instance, 30 = 2 * 3 * 5, and subtracting 1 from each factor, then multiplying, gives the totient 1 * 2 * 4 = 8. But if you want to find the totients of all the numbers less than a given n, a better approach than factoring each of them is sieving. The idea is simple: Set up an array X from 0 to n, store i in each Xi, then run through the array starting from 0 and whenever Xi = i loop over the multiples of i, multiplying each by i − 1.
Further discussion and code at my blog.
I'm not completely sure what the code is doing -- but frankly it looks pretty bad. It clearly is trying to use that Euler's totient function is multiplicative, meaning that a,b are relatively prime then t(a,b) = t(a)*t(b), together with the fact that if p is a prime then t(p) = p-1. But -- it seems to be using crude trial division to determine such things. If you really want to calculate the totient of all numbers in a given range then you should use an algorithm that sieves the numbers as you go along.
Here is a version which sieves as it goes and exploits the multiplicative nature to the hilt. At each pass through the main loop it starts with a prime, p which hasn't yet been processed. It determines all powers of p <= n and then uses a direct formula for these powers (see https://en.wikipedia.org/wiki/Euler%27s_totient_function ). Once these totients have been added, it forms all possible products <= n of these powers and the numbers for which the totients have been previously computed. This gives a whole slew of numbers to add to the list of previously determined numbers. At most sqrt(n) passes need to be made through the main loop. It runs almost instantly for n = 10000. It returns a list where the ith value is the totient of i (with t(0) = 0 for convenience):
def allTotients(n):
totients = [None]*(n+1) #totients[i] will contain the t(i)
totients[0] = 0
totients[1] = 1
knownTotients = [] #known in range 2 to n
p = 2
while len(knownTotients) < n - 1:
powers = [p]
k = 2
while p ** k <= n:
powers.append(p ** k)
k +=1
totients[p] = p - 1
for i in range(1,len(powers)):
totients[powers[i]] = powers[i] - powers[i-1]
#at this stage powers represent newly discovered totients
#combine with previously discovered totients to get still more
newTotients = powers[:]
for m in knownTotients:
for pk in powers:
if m*pk > n: break
totients[m*pk] = totients[m]*totients[pk]
newTotients.append(m*pk)
knownTotients.extend(newTotients)
#if there are any unkown totients -- the smallest such will be prime
if len(knownTotients) < n-1:
p = totients.index(None)
return totients
For completeness sake, here is a Python implementation of the algorithm to compute the totient of a single number which user448810 described in their answer:
from math import sqrt
#crude factoring algorithm:
small_primes = [2,3,5,7,11,13,17,19,23,29,31,37,41,43,47,
53,59,61,67,71,73,79,83,89,97]
def factor(n):
#returns a list of prime factors
factors = []
num = n
#first pull out small prime factors
for p in small_primes:
while num % p == 0:
factors.append(p)
num = num // p
if num == 1: return factors
#now do trial division, starting at 101
k = 101
while k <= sqrt(num):
while num % k == 0:
factors.append(k)
num = num // k
k += 2
if num == 1:
return factors
else:
factors.append(num)
return factors
def totient(n):
factors = factor(n)
unique_factors = set()
t = 1
for p in factors:
if p in unique_factors:
t *= p
else:
unique_factors.add(p)
t *= (p-1)
return t

Optimise the solution to Project Euler 12 (Python)

I have the following code for Project Euler Problem 12. However, it takes a very long time to execute. Does anyone have any suggestions for speeding it up?
n = input("Enter number: ")
def genfact(n):
t = []
for i in xrange(1, n+1):
if n%i == 0:
t.append(i)
return t
print "Numbers of divisors: ", len(genfact(n))
print
m = input("Enter the number of triangle numbers to check: ")
print
for i in xrange (2, m+2):
a = sum(xrange(i))
b = len(genfact(a))
if b > 500:
print a
For n, I enter an arbitrary number such as 6 just to check whether it indeed returns the length of the list of the number of factors.
For m, I enter entered 80 000 000
It works relatively quickly for small numbers. If I enter b > 50 ; it returns 28 for a, which is correct.
My answer here isn't pretty or elegant, it is still brute force. But, it simplifies the problem space a little and terminates successfully in less than 10 seconds.
Getting factors of n:
Like #usethedeathstar mentioned, it is possible to test for factors only up to n/2. However, we can do better by testing only up to the square root of n:
let n = 36
=> factors(n) : (1x36, 2x18, 3x12, 4x9, 6x6, 9x4, 12x3, 18x2, 36x1)
As you can see, it loops around after 6 (the square root of 36). We also don't need to explicitly return the factors, just find out how many there are... so just count them off with a generator inside of sum():
import math
def get_factors(n):
return sum(2 for i in range(1, round(math.sqrt(n)+1)) if not n % i)
Testing the triangular numbers
I have used a generator function to yield the triangular numbers:
def generate_triangles(limit):
l = 1
while l <= limit:
yield sum(range(l + 1))
l += 1
And finally, start testing:
def test_triangles():
triangles = generate_triangles(100000)
for i in triangles:
if get_factors(i) > 499:
return i
Running this with the profiler, it completes in less than 10 seconds:
$ python3 -m cProfile euler12.py
361986 function calls in 8.006 seconds
The BIGGEST time saving here is get_factors(n) testing only up to the square root of n - this makes it heeeaps quicker and you save heaps of memory overhead by not generating a list of factors.
As I said, it still isn't pretty - I am sure there are more elegant solutions. But, it fits the bill of being faster :)
I got my answer to run in 1.8 seconds with Python.
import time
from math import sqrt
def count_divisors(n):
d = {}
count = 1
while n % 2 == 0:
n = n / 2
try:
d[2] += 1
except KeyError:
d[2] = 1
for i in range(3, int(sqrt(n+1)), 2):
while n % i == 0 and i != n:
n = n / i
try:
d[i] += 1
except KeyError:
d[i] = 1
d[n] = 1
for _,v in d.items():
count = count * (v + 1)
return count
def tri_number(num):
next = 1 + int(sqrt(1+(8 * num)))
return num + (next/2)
def main():
i = 1
while count_divisors(i) < 500:
i = tri_number(i)
return i
start = time.time()
answer = main()
elapsed = (time.time() - start)
print("result %s returned in %s seconds." % (answer, elapsed))
Here is the output showing the timedelta and correct answer:
$ python ./project012.py
result 76576500 returned in 1.82238006592 seconds.
Factoring
For counting the divisors, I start by initializing an empty dictionary and a counter. For each factor found, I create key of d[factor] with value of 1 if it does not exist, otherwise, I increment the value d[factor].
For example, if we counted the factors 100, we would see d = {25: 1, 2: 2}
The first while loop, I factor out all 2's, dividing n by 2 each time. Next, I begin factoring at 3, skipping two each time (since we factored all even numbers already), and stopping once I get to the square root of n+1.
We stop at the square_root of n because if there's a pair of factors with one of the numbers bigger than square_root of n, the other of the pair has to be less than 10. If the smaller one doesn't exist, there is no matching larger factor.
https://math.stackexchange.com/questions/1343171/why-only-square-root-approach-to-check-number-is-prime
while n % 2 == 0:
n = n / 2
try:
d[2] += 1
except KeyError:
d[2] = 1
for i in range(3, int(sqrt(n+1)), 2):
while n % i == 0 and i != n:
n = n / i
try:
d[i] += 1
except KeyError:
d[i] = 1
d[n] = 1
Now that I have gotten each factor, and added it to the dictionary, we have to add the last factor (which is just n).
Counting Divisors
Now that the dictionary is complete, we loop through each of the items, and apply the following formula: d(n)=(a+1)(b+1)(c+1)...
https://www.wikihow.com/Determine-the-Number-of-Divisors-of-an-Integer
All this formula means is taking all of the counts of each factor, adding 1, then multiplying them together. Take 100 for example, which has factors 25, 2, and 2. We would calculate d(n)=(a+1)(b+1) = (1+1)(2+1) = (2)(3) = 6 total divisors
for _,v in d.items():
count = count * (v + 1)
return count
Calculate Triangle Numbers
Now, taking a look at tri_number(), you can see that I opted to calculate the next triangle number in a sequence without manually adding each whole number together (saving me millions of operations). Instead I used T(n) = n (n+1) / 2
http://www.maths.surrey.ac.uk/hosted-sites/R.Knott/runsums/triNbProof.html
We are providing a whole number to the function as an argument, so we need to solve for n, which is going to be the whole number to add next. Once we have the next number (n), we simply add that single number to num and return
S=n(n+1)2
S=n2+n2
2S=n2+n
n2+n−2S=0
At this point, we use the quadratic formula for : ax2+bx+c=0.
n=−b±√b2−4ac / 2a
n=−1±√1−4(1)(−2S) / 2
n=−1±√1+8S / 2
https://socratic.org/questions/how-do-you-solve-for-n-in-s-n-n-1-2
So all tri_number() does is evaluate n=1+√1+8S / 2 (we ignore the negative equation here). The answer that is returned is the next triangle number in the sequence.
def tri_number(num):
next = 1 + int(sqrt(1+(8 * num)))
return num + (next/2)
Main Loop
Finally, we can look at main(). We start at whole number 1. We count the divisor of 1. If it is less than 500, we get the next triangle number, then try again and again until we get a number with > 500 divisors.
def main():
i = 1
while count_divisors(i) < 500:
i = tri_number(i)
return i
I am sure there are additional ways to optimize but I am not smart enough to understand those ways. If you find any better ways to optimize python, let me know! I originally solved project 12 in Golang, and that run in 25 milliseconds!
$ go run project012.go
76576500
2018/07/12 01:56:31 TIME: main() took 23.581558ms
one of the hints i can give is
def genfact(n):
t = []
for i in xrange(1, n+1):
if n%i == 0:
t.append(i)
return t
change that to
def genfact(n):
t=[]
for i in xrange(1,numpy.sqrt(n)+1):
if(n%i==0):
t.append(i)
t.apend(n/i)
since if a is a divisor than so is b=n/a, since a*b=a*n/b=n, That should help a part already (not sure if in your case a square is possible, but if so, add another case to exclude adding the same number twice)
You could devise a recursive thing too, (like if it is something like for 28, you get 1,28,2,14 and at the moment you are at knowing 14, you put in something to actually remember the divisors of 14 (memoize), than check if they are alraedy in the list, and if not, add them to the list, together with 28/d for each of the divisors of 14, and at the end just take out the duplicates
If you think my first answer is still not fast enough, ask for more, and i will check how it would be done to solve it faster with some more tricks (could probably make use of erastothenes sieve or so too, and some other tricks could be thought up as well if you would wish to really blow up the problem to huge proportions, like to check the first one with over 10k divisors or so)
while True:
c=0
n=1
m=1
for i in range(1,n+1):
if n%i==0:
c=c+1
m=m+1
n=m*(m+1)/2
if c>500:
break
print n
this is not my code but it is so optimized.
source: http://code.jasonbhill.com/sage/project-euler-problem-12/
import time
def num_divisors(n):
if n % 2 == 0: n = n / 2
divisors = 1
count = 0
while n % 2 == 0:
count += 1
n = n / 2
divisors = divisors * (count + 1)
p = 3
while n != 1:
count = 0
while n % p == 0:
count += 1
n = n / p
divisors = divisors * (count + 1)
p += 2
return divisors
def find_triangular_index(factor_limit):
n = 1
lnum, rnum = num_divisors(n), num_divisors(n + 1)
while lnum * rnum < 500:
n += 1
lnum, rnum = rnum, num_divisors(n + 1)
return n
start = time.time()
index = find_triangular_index(500)
triangle = (index * (index + 1)) / 2
elapsed = (time.time() - start)
print("result %s returned in %s seconds." % (triangle, elapsed))

Categories