I'm doing the Project Euler problem 78
Let p(n) represent the number of different ways in which n coins can be separated into piles. For example, five coins can be separated into piles in exactly seven different ways, so p(5)=7
Find the least value of n for which p(n) is divisible by one million.
I'm trying to solve this problem using recursion. I know is not the optimal solution neither the fastest one, but I want to make this work if possible. Around n = 6000 it gives me:
MemoryError: Stack overflow
And that is not the only problem. I checked online and the solution is around 53,000. My matrix goes only to 10,000x10,000. If i go to 60,000x60,000 it return a MemoryError.
Here is my code:
import sys
from time import process_time as timeit
sys.setrecursionlimit(100000)
table = [10000 * [0] for i in range(10000)]
def partition(sum, largestNumber):
if (largestNumber == 0):
return 0
if (sum == 0):
return 1
if (sum < 0):
return 0
if (table[sum][largestNumber] != 0):
return table[sum][largestNumber]
table[sum][largestNumber] = partition(sum,largestNumber-1) + partition(sum-largestNumber,largestNumber)
return table[sum][largestNumber]
def main():
result = 0
sum = 0
largestNumber = 0
while (result == 0 or result%100000 != 0):
sum += 1
largestNumber += 1
result = int(partition(sum,largestNumber))
if sum%1000 == 0:
print('{} {}'.format(sum,timeit()))
print("n = {}, resultado = {}".format(sum,result))
print('Tempo = {}'.format(timeit()))
if __name__ == '__main__':
main()
Related
I'm a new at programming, I like solving this euler questions and I know there are solutions for this problem but it's not about the problem at all actually.
So, i managed to create a working function for finding example: 33. triangular number. It works but i couldn't manage to properly desing my while loop. I wanted to make it like, it starts from first triangular checks it's divisors make list of it's divisors, checks the length of the divisors, because problem wants "What is the value of the first triangle number to have over five hundred divisors?" . But i never managed to work the while loop. Thank you for reading.
nums = [1]
triangles = [1]
divisors = []
def triangularcreator(x):
if x == 1:
return 1
n = 1
sum = 0
while n!=0:
n += 1
nums.append(n)
for i in range(len(nums)):
sum += nums[i]
triangles.append(sum)
sum = 0
if x == len(triangles):
n = 0
return triangles[-1]
counter = 1
while True:
for i in range(1, triangularcreator(counter) + 1):
if triangularcreator(counter) % i == 0:
divisors.append(i)
if len(divisors) == 500:
print(triangularcreator(counter))
break
counter +=1
divisors.clear()
You should try to change a few things, starting with calculating just once the value of triangularcreator(counter) and assigning this value to a variable that you can use in different points of your code.
Second, you create a loop which will be calculate always triangularcreator(1). At the end of each iteration you increase the value of counter+=1, but then at the beginign of the new iteration you assignt it again value 1, so it will not progress as you expect. Try this few things:
counter = 1
while True:
triangle = triangularcreator(counter)
for i in range(1, triangle + 1):
if triangle % i == 0:
divisors.append(i)
if len(divisors) == 500:
print(triangle )
break
counter +=1
Also these two arrays nums = [1], triangles = [1] should be declared and initialized inside the def triangularcreator. Otherwise you would be appending elements in each iteration
Edit: I believe it is better to give you my own answer to the problem, since you are doing some expensive operations which will make code to run for a long time. Try this solution:
import numpy as np
factor_num = 0
n = 0
def factors(n):
cnt = 0
# You dont need to iterate through all the numbers from 1 to n
# Just to the sqrt, and multiply by two.
for i in range(1,int(np.sqrt(n)+1)):
if n % i == 0:
cnt += 1
# If n is perfect square, it will exist a middle number
if (np.sqrt(n)).is_integer():
return (cnt*2)-1
else:
return (cnt*2)-1
while factor_num < 500:
# Here you generate the triangle, by summing all elements from 1 to n
triangle = sum(list(range(n)))
# Here you calculate the number of factors of the triangle
factor_num = factors(triangle)
n += 1
print(triangle)
Turns out that both of your while loop are infinite either in triangularcreatorin the other while loop:
nums = [1]
triangles = [1]
divisors = []
def triangularcreator(x):
if x == 1:
return 1
n = 1
sum = 0
while n:
n += 1
nums.append(n)
for i in range(len(nums)):
sum += nums[i]
triangles.append(sum)
sum = 0
if len(triangles) >= x:
return triangles[-1]
return triangles[-1]
counter = 1
while True:
check = triangularcreator(counter)
for i in range(1, check + 1):
if check % i == 0:
divisors.append(i)
if len(divisors) >= 500:
tr = triangularcreator(counter)
print(tr)
break
counter +=1
Solution
Disclaimer: This is not my solution but is #TamoghnaChowdhury, as it seems the most clean one in the web. I wanted to solve it my self but really run out of time today!
import math
def count_factors(num):
# One and itself are included now
count = 2
for i in range(2, int(math.sqrt(num)) + 1):
if num % i == 0:
count += 2
return count
def triangle_number(num):
return (num * (num + 1) // 2)
def divisors_of_triangle_number(num):
if num % 2 == 0:
return count_factors(num // 2) * count_factors(num + 1)
else:
return count_factors((num + 1) // 2) * count_factors(num)
def factors_greater_than_triangular_number(n):
x = n
while divisors_of_triangle_number(x) <= n:
x += 1
return triangle_number(x)
print('The answer is', factors_greater_than_triangular_number(500))
Good day! I am currently writing a code that solves the way in which a line with n number of people with varying heights can be arranged so that m number of people can see "with no obstruction". A person is "with no obstruction" when all the people in front of that person is shorter than the person itself.
I answered this by using recursion:
def notObstruct(n, m):
if n == 0 and m == 0: return 0
if m == 0 and n >= 1: return 0
if m == n: return 1
if m > n: return 0
return notObstruct(n-1, m-1) + (n-1) * notObstruct(n-1, m)
I used stirling number of the first kind to solve this problem. However, I need to solve this using permutation and combination as a restriction from the problem itself.
notObstruct(5, 3) = 35
notObstruct(7, 2) = 1764
notObstruct(10, 3) = 1172700
I'm learning Python by doing Project Euler questions and am stuck on Problem #3.
I think I've found a solution that works, but when inserting the large number 600851475143 it just doesn't return anything. I believe that it just loads and loads cause even with 6008514 it takes 10 secs to return the answer.
# What is the largest prime factor of the number x?
import math
def isPrime(x):
try:
sqr = math.sqrt(x)
if x == 0 or x == 1:
return 0
for n in range (2 , int(sqr)+1):
if x % n == 0:
return 0
return 1
except:
return 'Give positive numbers.'
def largestPrimeFactor(x):
if isPrime(x) == 1:
return 'This number is prime.'
else:
largest = -1
mid = x/2
for n in range(2,int(mid)+1):
if isPrime(n):
if x % n == 0:
largest = n
if largest == -1:
return 'Enter numbers above 1.'
else:
return largest
print(largestPrimeFactor(600851475143))
This code should work:
import math
def isPrime(x):
try:
sqr = math.sqrt(x)
if x == 0 or x == 1:
return 0
n = 2
highest = x
while n < highest:
if x%n ==0:
return 0
highest = x/ n
n +=1
return 1
except:
return 'Give positive numbers.'
def largestPrimeFactor(x):
if isPrime(x) == 1:
return 'This number is prime.'
n = 2
highest = x
largest = 1
while n < highest:
if x%n == 0:
if isPrime(n):
largest = n
highest = x/n
n +=1
return largest
print(largestPrimeFactor(600851475143))
I made an optimization:
you check if every number is a factor of x while if for example 2 is not a factor of x for sure the maximum factor of x can be x/2. Hence if n is not a factor of x the maximum possible factor of x can just be x/n.
The code for large numbers just takes really long time, as pointed out by comments. I report other bugs.
Bug 1. Inappropriate use of try/except clause. It is recommended that try contains a single command and except catches the error. PEP8 also recommends specifying the type of error. Moreover, for your function, the error is never raised.
Bug 2. Redundancy. If x is not prime, you call isPrime for each value (let's call it i) from 2 to x/2. isPrime cycles for each number from 2 to sqrt(i). Therefore, isPrime(i) takes O(sqrt(i)) time, and we call it for i from 2 to x/2. Roughly, its running time is about O(x^(3/2)). Even if don't know a more optimal approach, this approach asks for memoization.
i have another way:
def Largest_Prime_Factor(n):
prime_factor = 1
i = 2
while i <= n / i:
if n % i == 0:
prime_factor = i
n /= i
else:
i += 1
if prime_factor < n:
prime_factor = n
return prime_factor
it faster than previous
try it:
import math
def maxPrimeFactors (n):
maxPrime = -1
while n % 2 == 0:
maxPrime = 2
n >>= 1
for i in range(3, int(math.sqrt(n)) + 1, 2):
while n % i == 0:
maxPrime = i
n = n / i
if n > 2:
maxPrime = n
return int(maxPrime)
n = 600851475143
print(maxPrimeFactors(n))
Problem statement:
Let p(n) represent the number of different ways in which n coins can be separated into piles. For example, five coins can be separated into piles in exactly seven different ways, so p(5)=7
Find the least value of n for which p(n) is divisible by one million.
So that's a code i got using recursion to solve this problem. I know that's not the optimal aproach, but should give me the right answer... But for some reason I don't understand it gives me back that n = 2301 has a p(n) = 17022871133751703055227888846952967314604032000000, which is divisible by 1,000,000 and is the least n to do that. So why this is not the correct answer?
I checked the for n<20 and it matches. So what's wrong with my code?
import numpy as np
import sys
sys.setrecursionlimit(3000)
table = np.zeros((10000,10000))
def partition(sum, largestNumber):
if (largestNumber == 0):
return 0
if (sum == 0):
return 1
if (sum < 0):
return 0
if (table[sum,largestNumber] != 0):
return table[sum,largestNumber]
table[sum,largestNumber] = partition(sum,largestNumber-1) + partition(sum-largestNumber,largestNumber)
return table[sum,largestNumber]
def main():
result = 0
sum = 0
largestNumber = 0
while (result == 0 or result%1000000 != 0):
sum += 1
largestNumber += 1
result = int(partition(sum,largestNumber))
print("n = {}, resultado = {}".format(sum,result))
return 0
if __name__ == '__main__':
main()
I believe the NumPy data type used in your np.zeroes declaration is a restricted rather than unlimited number. The number of partitions of 2301 is in fact 17022871133751761754598643267756804218108498650480 and not 17022871133751703055227888846952967314604032000000, which you can see if you run your (correct) program with a regular table declaration like
table = [10000 * [0] for i in xrange(10000)]
and then call on the table appropriately.
I came across a brain teaser problem. Im trying to simulate it, but having trouble getting the answer. The problem goes like this: there is one amoeba. every minute, an amoeba either may die, stay the same, split into 2 or split into 3 with equal probability. All of its offspring will behave the same way, independent of other amoebas. What is the probability that amoeba population will die?
My implementation in python:
import numpy as np
def simulate(n):
prob = np.array([0.25]*4)
ans = np.random.choice(np.arange(4),1,p=prob)
if ans == 0:
n = n - 1
if ans == 1:
pass
if ans == 2:
n = n * 2
if ans == 3:
n = n*3
return n
count = 0
for i in range(10000):
nold = 1
while True:
nnew = simulate(nold)
if nnew == 0: #amoeba has died
count += 1
break;
nold = nnew
Im getting an infinite loop. Can anybody help? thanks. The answer is 41%
The While loop needs to have some sort of breakpoint.
You have not set what is False.
while count < 10000:
...