We have an input integer let's say 13. We can find consistent subarray of fibonacci numbers that sums to 10 - [2,3,5]. I need to find next number that is not a sum of consistent subarray. In this case this number will be 14. I have this code, but the catch is, it can be optimized to not iterate through all of the N's from starting Left Pointer = 1 and Right Pointer = 1 but somehow "import" from previous N and i have no clue how to do it so maybe someone smarter might help.
def fib(n):
if n == 1: return 1
if n == 2: return 1
return fib(n-1) + fib(n-2)
def fibosubarr(n):
L_pointer = 1
R_pointer = 2
sumfibs = 1
while sumfibs != n:
if sumfibs > n and L_pointer < R_pointer:
sumfibs -= fib(L_pointer)
L_pointer += 1
elif sumfibs < n and L_poiner < R_pointer:
sumfibs += fib(R_pointer)
R_pointer += 1
else: return False
return True
n = int(input())
while fibosubarr(n):
n += 1
print(n)
Here's a technique called "memoizing". The fib function here keeps track of the current list and only extends it as necessary. Once it has generated a number, it doesn't need to do it again.
_fib = [1,1]
def fib(n):
while len(_fib) <= n:
_fib.append( _fib[-2]+_fib[-1] )
return _fib[n]
With your scheme, 200000 caused a noticeable delay. With this scheme, even 2 billion runs instantaneously.
To get the next subarray sum, you only need one call of the function -- provided you keep track of the least sum value that was exceeding n.
I would also use a generator for the Fibonacci numbers:
def genfib():
a = 1
b = 1
while True:
yield b
a, b = b, a + b
def fibosubarr(n):
left = genfib()
right = genfib()
sumfibs = next(right)
closest = float("inf")
while sumfibs:
if sumfibs > n:
closest = min(sumfibs, closest)
sumfibs -= next(left)
elif sumfibs < n:
sumfibs += next(right)
else:
return n
return closest
Now you can do as you did -- produce the next valid sum that is at least the input value:
n = int(input())
print(fibosubarr(n))
You could also loop to go from one such sum to the next:
n = 0
for _ in range(10): # first 10 such sums
n = fibosubarr(n+1)
print(n)
Related
I've got a question- how do I write a function sum_even_factorials that finds the sum of the factorials of the even numbers that are less than or equal to n.
Eg:
sum_even_factorials(1)=
1
sum_even_factorials (3)=
3
sum_even_factorials (6)=
747
This is my current code:
Is there a logical error in the current code?
Is there a logical error in the current code?
To begin with, function sum_even_factorial doesn't return a value in every execution flow:
if cond1:
return val1
elif cond2:
return val2
else: # this part is missing in your code
return val3
In addition, note that when you call this function, you are not doing anything with the value that it returns:
sum_even_factorial(6)
Finally, although parts of your code are not visible in your question, I tend to guess that you cannot recursively compute the factorials of even numbers the way you did it, because the factorial of an even number n depends on the factorial of the odd number n - 1.
I think the code needs a loop. I'd write it like so:
def factorial(n):
if n == 0 or n == 1:
return 1;
else:
return n * factorial(n-1)
def sum_even_factorial(n):
current_sum = 0
while n >= 0:
if n % 2 == 0:
current_sum += factorial(n)
n -= 1
return current_sum
print(sum_even_factorial(6))
If you return tuples from the function, you can do it with one single function. See the comments in the code on how it works ...
def factorial_with_sum(n):
if n < 2:
return 1, 0 # first item of the tuple is the factorial, second item is the sum
else:
f, s = factorial_with_sum(n - 1) # calc factorial and sum for n - 1
f = f * n # factorial = n * factorial (n - 1)
if n % 2 == 0:
s = s + f # if n is even, add the current factorial to the sum
return f, s
fact, sum = factorial_with_sum(6)
print(fact)
print(sum)
You can also do it iteratively with a simple for loop as follows
def factorial_with_sum_iterative(n):
s = 0 # initialize sum
f = 1 # and factorial
for i in range(2, n + 1): # iterate from 2 to n
f = f * i # calculate factorial for current i
if i % 2 == 0:
s = s + f # if current i is even, add it to sum
return f, s
I'm playing with the Codality Demo Task. It's asking to design a function which determines the lowest missing integer greater than zero in an array.
I wrote a function that works, but Codility tests it as 88% (80% correctness). I can't think of instances where it would fail.
def solution(A):
#If there are negative values, set any negative values to zero
if any(n < 0 for n in A):
A = [(i > 0) * i for i in A]
count = 0
else: count = 1
#Get rid of repeating values
A = set(A)
#At this point, we may have only had negative #'s or the same # repeated.
#If negagive #'s, or repeated zero, then answer is 1
#If repeated 1's answer is 2
#If any other repeated #'s answer is 1
if (len(A) == 1):
if (list(A)[0] == 1):
return 2
else:
return 1
#Sort the array
A = sorted(A)
for j in range(len(A)):
#Test to see if it's greater than zero or >= to count. If so, it exists and is not the lowest integer.
#This fails if the first # is zero and the second number is NOT 1
if (A[j] <= count or A[j] == 0): #If the number is lt or equal to the count or zero then continue the count
count = count + 1
elif (j == 1 and A[j] > 1): return 1
else:
return count
return count
UPDATE:
I got this to 88% with the fixes above. It still fails with some input. I wish Codility would give the inputs that fail. Maybe it does with a full subscription. I'm just playing with the test.
UPDATE 2: Got this to 100% with Tranbi's suggestion.
def solution(A):
#Get rid of all zero and negative #'s
A = [i for i in A if i > 0]
#At this point, if there were only zero, negative, or combination of both, the answer is 1
if (len(A) == 0): return 1
count = 1
#Get rid of repeating values
A = set(A)
#At this point, we may have only had the same # repeated.
#If repeated 1's answer is 2
#If any other repeated #'s only, then answer is 1
if (len(A) == 1):
if (list(A)[0] == 1):
return 2
else:
return 1
#Sort the array
A = sorted(A)
for j in range(len(A)):
#Test to see if it's >= to count. If so, it exists and is not the lowest integer.
if (A[j] <= count): #If the number is lt or equal to the count then continue the count
count = count + 1
else:
return count
return count
Besides that bug for len=1, you also fail for example solution([0, 5]), which returns 2.
Anyway... Since you're willing to create a set, why not just make this really simple?
def solution(A):
A = set(A)
count = 1
while count in A:
count += 1
return count
I don't think this is true:
#At this point, we may have only had negative #'s or the same # repeated. If so, then the answer is 1+ the integer.
if (len(A) == 1):
return list(A)[0]+1
If A = [2] you should return 1 not 3.
Your code is quite confusing though. I think you could replace
if any(n < 0 for n in A):
A = [(i > 0) * i for i in A]
with
A = [i for i in A if i > 0]
What's the point of keeping 0 values?
I don't think this is needed:
if (len(A) == 1):
if (list(A)[0] == 1):
return 2
else:
return 1
It's already taken into account afterwards :)
Finally got a 100% score.
def solution(A):
# 1 isn't there
if 1 not in A:
return 1
# it's easier to sort
A.sort()
# positive "hole" in the array
prev=A[0]
for e in A[1:]:
if e>prev+1>0:
return prev+1
prev=e
# no positive "hole"
# 1 is in the middle
return A[-1]+1
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))
i need to create a mathematical sequence of type:
P(n)= P(n-1) + P(n-2)
We know that P(0)=0 and P(1)=1
I really struggle creating a sequence, i tried to create it, here is some of what I’ve written...
def fibonacci(n):
number = 0
if n == 0:
number = 0
return (number)
if n == 1:
number = 1
return (number)
if n > 1:
def compute(limit):
for x in range(2, limit):
fibonacci(x) = fibonacci(x-1) + fibonacci(x-2)
for i in range(0, n):
number += compute(i)
First: you don't need to use brackets when you use 'return' statement
Solution:
def fibonacci(n):
number = 0
if n == 0:
number = 0
return number
if n == 1:
number = 1
return number
if n > 1:
return fibonacci(n-1)+fibonacci(n-2)
This code works fine, but u can calculate fibonacci more effective if u will use dynamic programming
Example:
fibonacci = [0,1]
for i in range(2,n+1):
fibonacci.append(fibonacci[i-1]+fibonacci[i-2])
print(fibonacci[-1])
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))