Python MemoryError when appending a list - python

I've a small Python (2.7.10) script, which you can see below.
def numbers_calc(max_num, num_step):
"""Returns every number from 0 to max_num with num_step as step."""
n = 0
l = []
while n < max_num + 1:
l.append(n)
n += n * num_step
return l
n_l = []
n_l.append(numbers_calc(25, 1))
print "Here are the numbers."
print n_l
The function numbers_calc is meant to take all the given args, form a list, and populate it with numbers (with num_step as the step when calculating) before it reaches max_num + 1. The script then does return it's local list named l.
However, every time I run the script, I encounter MemoryError. Here's what Python returned when I ran the script:
Traceback (most recent call last):
File "num.py", line 13, in <module>
n_l.append(numbers_calc(25, 1))
File "ex33.py", line 7, in numbers_calc
l.extend(i)
MemoryError
I tried looking it up, saw nothing helpful. I hope you can help me!

n starts at 0. n += n * num_step adds 0 to n. n never changes, and your loop keeps adding items to the list forever.
Cause n to change somehow.

The issue is in the line -
n += n * num_step
Here, you initialized n as 0 , and then you are multiplying n and num_step , whose result would always be 0 , and then adding it to n . So n always stays at 0 . If you are Try to loop from 0 to max_num+1 for every num_step, you should use range() function, Example -
def numbers_calc(max_num, num_step):
"""Returns every number from 0 to max_num with num_step as step."""
l = []
for i in range(0,max_num + 1,num_step):
l.append(i)
return l

anything times 0 is always going to be 0 so you have an infinite loop settingn = 0 set n to 1 initially:
def numbers_calc(max_num, num_step):
"""Returns every number from 0 to max_num with num_step as step."""
n = 1
l = []
while n < max_num + 1:
l.append(n)
n += n * num_step
print(n)
return l
n_l = []
n_l.append(numbers_calc(25, 1))
Output:
[[1, 2, 4, 8, 16]]
If you want a list of number just use the return value:
nl = numbers_calc(25, 1)
Which will give you [1, 2, 4, 8, 16]
If you actually want every number from 0 to max_num with num_step use += not *= and leave n at 0:
def numbers_calc(max_num, num_step):
"""Returns every number from 0 to max_num with num_step as step."""
n = 0
l = []
while n < max_num + 1:
l.append(n)
n += num_step
print(n)
return l
Or simply return range with a step:
def numbers_calc(max_num, num_step):
"""Returns every number from 0 to max_num with num_step as step."""
return list(range(max_num + 1,num_step))
You should be aware that if the step is not a multiple of max_num then you are not going to get max_num i.e numbers_calc(25, 2) will go to 24 .

Thanks everybody for helping! Didn't even realise I had math problems there. Thank you all! By the way, here's the final version of my script.
def numbers_calc(max_num, num_step):
"""Returns every number from 0 to max_num with num_step as step."""
i = 0
l = []
while i < max_num + 1:
l.append(i)
i += num_step
return l
n_l = numbers_calc(25, 5)
print "Here are the numbers."
print n_l

Related

Sum of N numbers in Fibonacci

I am trying to implement the total sum of N whole numbers in Fibonacci
def fibo(n):
if n<2:
return 1
else:
res = fibo(n-1) + fibo(n-2)
sum = sum + res
return res, sum
n=7
sum = 0
for i in range(1, n):
print(fibo(i))
print("Suma", sum)
#example: if n=7 then print : 1,1,2,3,5,8,13 and sum is 32
The error I have is, when I put sum = sum + res
Doesnt print & run the program
Currently, how could you implement the total sum?
You simply need to calculate sum in the for loop, not in the fibo(n).
Here take a look:
def fibo(n):
if n<2:
return 1
else:
res = fibo(n-1) + fibo(n-2)
return res
n=7
sum = 0
for i in range(0, n):
r = fibo(i)
sum += r
print(r)
print("Suma", sum)
I used r in order to call fibo once in each loop.
Let me first point out that the sum of the first 7 terms of the Fibonacci sequence is not 32. That sum is 33. Now to the problem. Here is how I would solve the problem. I would first define the function that calculates the n th term of the Fibonacci sequence as follows:
def fibo(n):
if n in [1,2]:
return 1
else:
res = fibo(n-1) + fibo(n-2)
return res
Then I would define a function to calculate the sum of the first n terms of the Fibonacci sequence as follows.
def sum_fibo(n):
res = [fibo(i) for i in range(1, n+1)]
print(res)
return sum(res)
So if I do
[In] sum_fibo(7)
I get
[1, 1, 2, 3, 5, 8, 13]
out >>> 33
NOTE: In defining the functions above, I have assumed that the input of the function is always going to be a positive integer though the Fibonacci can be extended to cover all real and complex numbers as shown on this wiki page.
actually i don't think this needs to be that complicated the fibonacci sequence is very interesting in a maltitude of ways for example, if you want the sum up the 7th fibonacci number, then have checked what the 9th fibonacci number - 1 is? Now how do we find the n'th fibonacci number?
p = (1+5**.5)/2
q = (1-5**.5)/2
def fibo(n):
return 1/5**.5*(p**n-q**n)
and now we can can find the sum up to any number in one calculation! for example for 7
fibo(9)- 1
output
33
and what is the actual answer
1+1+2+3+5+8+13=33
summa summarum: the fibonachi number that is two places further down the sequence minus 1 is the sum of the fibonachi numbers up to the number
def sumOfNFibonacciNumbers(n):
# Write your code here
i = 1
sum = 2
fib_list = [0, 1, 1]
if n == 1:
return 0
if n == 2:
return 1
if n == 3:
return 2
for x in range(1,n-2):
m = fib_list[-1] + fib_list[-2]
fib_list.append(m)
sum = sum + m
return sum
result = sumOfNFibonacciNumbers(10)
print(result)
Made some modifications to your code:
def fibo(n):
print(1)
counter = 1
old_num = 0
new_num = 1
sum_fib = 1
while counter < n:
fib = old_num + new_num
print(fib)
if counter < n:
old_num = new_num
new_num = fib
sum_fib = sum_fib + fib
counter = counter + 1
print('sum:' + str(sum_fib))
#fibo(5)
First of all, the line sum = sum + res makes no sense because you never defined sum in the first place.
So, your function should look like
def fibo(n):
if n<2:
return 1
else:
return fibo(n-1) + fibo(n-2)
Second, you can get the sum by simply
sum_ = 0
for i in range(0, n):
sum_ += fibo(i)
Or maybe
sum_ = sum(fibo(i) for i in range(0, n))
Notice that the latter would only work if you have not overridden the built-in function named sum
You are referring the variable sum before assignment.
You may want to use the variable sum inside the for loop and assign the fibo to it.
def fibo(n):
if n<2:
return 1
else:
return fibo(n-1) + fibo(n-2)
n=7
sum = 0
for i in range(1, n):
sum += fibo(i)
print(fibo(i))
print("suma", sum)
Considering the start of the Fibonacci series with 1 rather than 0.
def fib(no_of_elements):
elements, start = [], 1
while start <= no_of_elements:
if start in [1, 2]:
elements.append(1)
elif start >= 3:
elements.append(elements[start-2]+elements[start-3])
start += 1
return elements, sum(elements)
print(fib(8))
Output:
([1, 1, 2, 3, 5, 8, 13, 21], 54)

Find whether the largest element in the array is at least twice as much as every other number in the array?

I'm trying to run a program that finds the index of the number that is at least two times larger than all other number in the array.
Here's my code
def dominantIndex(self, nums):
max_num = max(nums)
max_i =nums.index(max_num)
if len(nums) == 1:
return nums.index(max_num)
for num in nums:
if max_num >= 2*num:
return num.index(max_num)
return -1
However , it doesn't work perfectly for all inputs. Could someone please fix it and check for inputs like :
[1,0]
[0,3,4,8]
[0,3,5,2]
This checks for many possible input problems.
Then it sorts the list to get the answer you are looking for. I decided to sort, for simplicity, but you could use other methods as well. I added comments so everything is clear, especially about the input tests, as asked.
def dominantIndex(nums):
# If the array is empty or None or not a list, return -1
if not nums or type(nums) != list:
return -1
# If the array is of length 1, return the only index, 0
elif len(nums) == 1:
return 0
sorted_numbers = sorted(nums)
# If the highest number is twice the second largest, return it's index
if sorted_numbers[-2] * 2 <= sorted_numbers[-1]:
return nums.index(sorted_numbers[-1])
else:
return -1
There actually is a library function nlargest in the heapq module.
>>> L1 = [1, 0]
>>> L2 = [0, 3, 4, 8]
>>> L3 = [0, 4, 5, 2]
>>>
>>> from heapq import nlargest
>>> def dom_ind(nums):
... a, b = nlargest(2, range(len(nums)), key=nums.__getitem__)
... return a if nums[a] >= 2 * nums[b] else -1
...
>>>
>>> dom_ind(L1)
0
>>> dom_ind(L2)
3
>>> dom_ind(L3)
-1
Use below code
def check(nums):
if len(nums) == 1:
return 0
max_num = max(nums)
ind = nums.index(max_num)
updated_array = map(lambda x: x if x != max_num else -1, nums)
if max_num >= 2*max(updated_array):
return ind
return -1
Output:
check([1,0])
0
>>> check([0,3,4,8])
3
>>> check([0,3,5,2])
-1
You can get the second highest as well;:
def dominantIndex(nums):
max_num = max(nums)
secondHighest = max( n for n in nums if n != max_num)
if max_num > 2 * secondHighest:
return nums.index(max_num)
return -1
print(dominantIndex( [1,2,39,7]))
print(dominantIndex( [1,2,3,5]))
Output:
2
-1
I'd iterate over the list and find the two largest elements. Then, if the largest element is at least twice as large as the second largest, you can return its index.
def dominantIndex(nums):
# Assumption - nums has a length of at least 2.
# Bootsrap the rist two indexes
if nums[0] > nums[1]:
max_ind = 0
next_ind = 1
else:
max_ind = 1
next_ind = 0
# Go over the rest
for i in range(2, len(nums)):
if nums[i] > nums[max_ind]:
next_ind = max_ind
max_ind = i
elif nums[i] > nums[next_ind]:
next_ind = i
if nums[max_ind] >= nums[next_ind] * 2:
retrun max_ind
return -1
I think none of the other suggested solutions works if the largest number appears multiple times in nums. This does:
def dominantIndex(self, nums):
s = sorted(nums)
if s[-1] >= 2 * s[-2]:
return nums.index(s[-1])
else:
return -1
In addition, you might want to check if nums has more than one element.

palindromic numbers in python

Trying to find the largest palindrome that's the product of two three-digit numbers. Before I look up the infinitely more efficient and - more importantly - working solution, could you tell me what's wrong with my code? I just keep getting the empty set.
def palindrome():
n = 100
m = 100
palind = []
while n<=999:
while m<=999:
prod = n * m
if str(prod) == str(prod)[::-1] and prod > palind[0]:
palind.pop(0)
palind.append(prod)
return palind
m = m + 1
n = n + 1
return palind
print palindrome()
You have 3 problems.
Problem 1: Returning early.
while n<=999:
while m<=999:
prod = n * m
if str(prod) == str(prod)[::-1] and prod > palind[0]:
palind.pop(0)
palind.append(prod)
# Here
return palind
m = m + 1
n = n + 1
# And here
return palind
A return statement means the function is over now. It stops where it is, the caller gets the return value, and the caller goes on its way. You don't want to do that until the function is completely done with its work. Let's move the return to after the loops, when the function is done computing.
Problem 2: palind[0] is uninitialized.
while n<=999:
while m<=999:
prod = n * m
# Here v
if str(prod) == str(prod)[::-1] and prod > palind[0]:
palind.pop(0)
palind.append(prod)
m = m + 1
n = n + 1
return palind
Suppose your program is going along and it finds its first palindrome. It tries to compare it to palind[0], but there is no palind[0]! You need to take the first palindrome without trying to compare it to one that doesn't exist. Let's fix that.
Problem 3: Not resetting m.
palind = None
while n<=999:
while m<=999:
prod = n * m
if str(prod) == str(prod)[::-1]:
if palind is None or prod > palind:
palind = prod
m = m + 1
n = n + 1
return palind
After the first iteration of the n loop, you need to go back through all possible m values with n=101. You don't do that; your code keeps m at 1000, so it doesn't go through the inner loop again. You could explicitly reset m, but it's much easier to use for loops instead of whiles. With all 3 problems fixed, your code looks like
palind = None
for n in xrange(100, 1000):
for m in xrange(100, 1000):
prod = n * m
if str(prod) == str(prod)[::-1]:
if palind is None or prod > palind:
palind = prod
return palind
This shortcuts when it's impossible to return an i*j > the largest recorded and correctly returns 906609 (note, if you're in python 2, the below would work for you, but you'd prefer to use xrange instead of range to avoid creating unnecessary lists in memory):
def palindrome(floor=0, upto=999):
'''
return the largest palindrome product for all number from (but not including)
floor to (and including) upto
'''
start = upto
largest = None
for i in range(start, floor, -1): # decreasing from upto
if i * upto < largest: # if True, impossible for higher product from combo
break
for j in range(start, i-1, -1): # decrease from upto to not including i-1
product = i*j
if str(product) == str(product)[::-1]:
if product > largest:
largest = product
return largest
Usage:
>>> palindrome(99,999)
906609
>>> palindrome(10,13)
121
>>> palindrome(0,10)
9
The short-cutting is important because if given a very large number, it can take quite a while to return:
>>> palindrome(upto=100000000)
9999000000009999L
I also created a generator that hits every single combination from 0 to 999, and it returns 906609.
def palindrome(upto=1000):
return max(i*j for i in range(upto) for j in range(upto)
if str(i*j) == str(i*j)[::-1])
But when running this palindrome as in:
>>> palindrome(upto=100000000)
The complete search will search all 100000000^2, and take far too long.
I first had written it like this, with the idea that it would short-cut and avoid iterating over every possible combination, but this is incorrect, it returns 888888:
def palindrome():
start = 999
largest = 0
for i in range(start, 0, -1): # decreasing from 999
if i * 999 < largest:
return largest
for j in range(start, i, -1): # decreasing from 999 to i
if str(i*j) == str(i*j)[::-1]:
largest = i*j
It first multiplies 999 times 999, then 998 times 999, then
998*998
997*999
997*998
997*997
...
But the results aren't monotonically decreasing (that is, each result is not guaranteed to be smaller than the previous.)
You are not re-initializing m = 100, after every iteration of the outer while loop
You are returning early. Remove the return statement in the inner loop
The last return statement should NOT be inside the outer while loop.
You never initialized palind list (Thanks to #user2357112)
Suggestions:
Don't use a list to maintain the biggest number. A simple variable is enough.
You don't have to convert the number to string twice in the same expression. Store the stringified number in a variable.
Use range functions to loop through the numbers
If I were to write this program, I would have done it like this
from itertools import product
def palindrome():
numbers, result = range(1000, 100, -1), -1
for num1, num2 in product(numbers, repeat = 2):
prod = num1 * num2
sprod = str(prod)
if sprod == sprod[::-1] and prod > result:
result = prod
return result
print palindrome() # 906609
This is may not answer the question, but if you looking for to get palindromic numbers between range you can do this
def getPalindrome(lower, upper):
listPalind = []
for n in range(lower, upper):
if str(n) == str(n)[::-1]:
listPalind.append(n)
return listPalind
# Usage
print(getPalindrome(100, 300))
# Results
[101, 111, 121, 131, 141, 151, 161, 171, 181, 191, 202, 212, 222, 232, 242, 252, 262, 272, 282, 292]
def is_palindromic(s):
if s == s[::-1]:
return True
else:
return False
palind = []
for i in range(100, 1000):
for j in range(100,1000):
product = i * j
if is_palindromic(str(product)):
palind.append(product)
return max(palind)
#result :
906609
def isPalindrome(self, x: int):
temp = 0
x1 = x
while x > 0:
y = x % 10
temp = temp * 10 + y
x = x//10
if(temp == x1):
return True
else:
return False

Fibonacci list how do i make a conditional that excludes a number

fib = [0,1]
a = 1
b = 0
i = 0
while i < n:
i = a+b
a,b = i, a
fib.append(i)
This works in cases where 'n' (which is a given variable) is a number in an actual Fibonacci sequence, like 21 or 13. However, if the number is something like six, it adds one more number than it should. The list should not contain a number that is greater than n.
You could always add a to the list first, then do your incrementing.
fib = [0]
a, b = 1, 0
while a <= n:
fib.append(a)
a,b = a+b, a
Using the classic shnazzy recursive Fibonacci function (which took me a few tries to remember and get right):
def fib(num):
if ((num == 0) or (num == 1)): return 1
fib_num = fib(num - 1) + fib(num - 2)
return fib_num
x, n, i = 2, 15, []
while (fib(x) < n):
i.append(fib(x))
x += 1

Euler Project No. 2 with Python

Can somebody tell me why this should be wrong?
#Each new term in the Fibonacci sequence is generated
#by adding the previous two terms. By starting with 1 and 2,
#the first 10 terms will be:
#1, 2, 3, 5, 8, 13, 21, 34, 55, 89, ...
#Find the sum of all the even-valued terms in the sequence
#which do not exceed four million.
sum=2
list = [1,2]
for x in range(2,100):
a = list[x-2]+list[x-1]
print(a)
list.append(a)
if a % 2 == 0:
sum += a
print('sum', sum)
if sum >= 4000000:
break
Here's a completely different way to solve the problem using a generator and itertools:
def fib():
a = b = 1
while 1:
yield a
a, b = b, a + b
import itertools
print sum(n for n in itertools.takewhile(
lambda x: x <= 4000000, fib()) if n % 2 == 0)
Output:
4613732
So your code, even though it is wrong (see other answers), happens to give the correct answer.
replace
sum += a
print('sum', sum)
if sum >= 4000000:
break
with
if a > 4000000:
break
sum += a
print('sum', sum)
You should compare "a" with 4000000, not "sum", like Daniel Roseman said.
The question asked for the sum of even terms which do not exceed four million. You're checking if the sum doesn't exceed 4m.
I'm trying to solve the same problem - although I understand the logic to do it, I don't understand why this works (outputs the right sum)
limit = 4000000
s = 0
l = [1,2]
while l[-1]<limit:
n = l[-1]+l[-2]
l.append(n)
print n
And then then moment I put in the modulo function, it doesn't output anything at all anymore.
limit = 4000000
s = 0
l = [1,2]
while l[-1]<limit:
n = l[-1]+l[-2]
if n % 2 == 0 :
l.append(n)
print n
I'm sure this is fairly simple...thanks!
This is the code I used. It is very helpful and teaches you about generators.
def fib():
x,y = 0,1
while True:
yield x
x,y = y, x+y
def even(seq):
for number in seq:
if not number % 2:
yield number
def under_a_million(seq):
for number in seq:
if number > 4000000:
break
yield number
print sum(even(under_a_million(fib())))
-M1K3
Keep it simple and it should take you less than 0.1 seconds.
from datetime import datetime
x, y = 1, 1
total = 0
for i in xrange (1, 100):
x = x + y
if x % 2 == 0 and x <= 4000000:
total += x
y = y + x
if y % 2 == 0 and x <= 4000000:
total += y
print total
starttime = datetime.now()
print datetime.now() - starttime

Categories