Python List Index Error - python

Here is my version of the code right now and I keep getting list index error.
n = 0
y = len(list1)-1
while n < y:
for k in list1:
if list1[n]+ k == g:
print("The 2 prime numbers that add up to ",g,"are ", list1[n]," and ",k,".")
break
else:
n = n+1

You are incrementing n in the for loop but testing its contraint in the outer while loop.
Perhaps this is what you wanted:
n = 0
y = len(list1)-1
found = 0
while n < y:
for k in list1:
if list1[n]+ k == g:
print("The 2 prime numbers that add up to ",g,"are ", list1[n]," and ",k,".")
found = 1
break # for loop
if found:
break # while loop
n = n + 1
A much better way to do it is using itertools.combinations_with_replacement:
import itertools
for (v1,v2) in itertools.combinations_with_replacement(list1, 2):
if v1 + v2 == g:
print("blah blah blah")
break
combinations_with_replacement(list1,2) will return all the unordered combinations of two elements of list1. For instance, combinations_with_replacement('ABC', 2) --> AA AB AC BB BC CC

You left a few bits of information out, but I gather that you are trying to find 2 primes that match a target. In order to access a list in this manner, you need to enumerate it.
y = len(list1) - 1
while n < y:
for n, k in enumerate(list1):
if list1[n]+ k == g :
print("The 2 prime numbers that add up to ",g,"are ", list1[n]," and ",k,".")
break
However, you don't really need the index, two for loops would accomplish the same thing.
target = 8
primes = [2, 3, 5, 7, 11, 13, 17, 19]
message = 'The 2 prime numbers that add up to {target} are {value1} and {value2}'
for index1, value1 in enumerate(primes):
for value2 in primes[index1 + 1:]:
if value1 + value2 == target:
print(message.format(target=target, value1=value1, value2=value2))

Related

Function to sum and compare two sides of an array

For example this is array = [1,2,3,4,3,2,1]
i want computer to choose i=4 and sum both left of the four and right of the four and then compare if they are equal to each other, program prints i value to the screen.
Now i write it in here and it works as long as the i value is 0 but if i want to make this search for i>0 then i gets complicated.
this is my main program:
# importing "array" for array creations
import array as arr
# Function to find sum
# of array exlcuding the
# range which has [a, b]
def sumexcludingrange(li, a, b): # I FOUND THIS FUNCTION ONLINE BUT ALSO DIDN`T WORK EITHER.
sum = 0
add = True
# loop in li
for no in li:
# if no != a then add
if no != a and add == True:
sum = sum + no
# mark when a and b are found
elif no == a:
add = False
elif no == b:
add = True
# print sum
return sum
#lis = [1, 2, 4, 5, 6]
#a = 2
#b = 5
#sumexcludingrange(arr, 0, i-1)
def my(arr):
for i in range(len(arr)):
if i == 0: #this works when array is like [1,0,0,1] and i equals zero
sum_left = arr[0]
sum_right = sum(arr) - arr[0]
while sum_left == sum_right:
print(i)
break
elif i > 0 : # i 1 2 3 4 5 6 7 8 9..
#sumleft and sumright are not right.. what is the issue here?
sum_left = sumexcludingrange(arr, 0, i-1) #result is 16, sumexcludingrange function didn`t
#work.
print (sum_left)
#print(i)
sum_right == sum(arr) - sum_left
#print(sum_right)
#break
while sum_left == sum_right:
print(sum_left)
print(sum_right)
print("they are equal now")
break
else:
print("index cannot be a negative number.")
something = arr.array('i', [1,2,3,4,3,2,1]) # len(arr) = 7
my(something)
After seeing that i need another function to compare two sides of the array, i created a new file and write it in here and somehow it outputs this:
1
13
13
2
10
10
#array[i] array[i+1] .. + array[length-1]
array = [1,2,3,4,5,6,7] # 7 element so length=7,
for i in range(len(array)):
if i > 0 :
ln = len(array) + 1
sum_right = sum(array[i+1:ln])
sum_left = sum(array) - sum_right
print(i)
print(sum_right)
print(sum_right)
the way i think is this:
# array[i] i>0 i={1,2,3,4..}
sum_total = sum(arr) = array[0] + ..+ array[i-1] + array[i] + array[i+1] + ... + array[length-1]
sum_right = array[i+1] + .. + array[length-1]
sum_left = sum_total - sum_right
Is there a better way to accomplish that?
If I understand your question correctly, the solution could be something like this:
array = [1,2,3,4,5,6,7]
a1 = array[:4] # first 4 numbers
a2 = array[-4:] # last 4 numbers
total = sum(array)
diff = total-sum(a2)

How to check if any item exists in the list

How to check whether a list and an element of a list with such an index exist in the list itself?
I have a list [[10,10,9], [10,10,10], [10,10,10]]
Then I enter the number of coordinates (k) and the coordinates themselves. At these coordinates, I have to subtract 8 from the cell and 4 with each cell standing next to it. But what if there are no cells nearby?
When checking if field [r + f] [c + s] in field: it always gives a negative answer. How to make a check?
for i in range(k):
for j in range(1):
f = drops[i][j]
s = drops[i][j + 1]
field[f][s] -= 8
for r in range(-1, 1):
for c in range(-1, 1):
if not (r == c == 1):
if field[r + f][c + s] in field:
field[r + f][c + s] -= 4
You just have to check whether the index isn't at the start or the end of the list.
n = 2
mylist = [4, 5, 8, 9, 12]
if len(mylist) > n+1:
mylist[n+1] -= 1
if n > 0:
mylist[n-1] -= 1
Slice assignment might help. You have to avoid letting an index go negative, but something like
s = slice(max(n-1,0), n+2)
x[s] = [v-1 for v in x[s]]
isn't too repetitive, while handling the edge cases n == 0 and n == len(s) - 1. (It won't work ifn` is explicitly set to a negative index, though.)

XOR greater than 4 of even-even or odd odd pair

Given an array of even and odd numbers, I want to get the number of (even-even) and (odd-odd) pairs whose XOR is greater than or equal to 4. I tried this with the code below but it runs in O(n^2), (yikes). Please can anyone suggest a means of optimization?
n = int(raw_input()) #array size
ar = map(int, raw_input().split()) #the array
cnt = 0
for i in xrange(len(ar)):
for j in xrange(i+1, len(ar)):
if ar[i] ^ ar[j] >= 4 and (not ar[i] & 1 and not ar[j] & 1):
cnt += 1; #print ar[i],ar[j],ar[i]^ar[j];
elif ar[i] ^ ar[j] >= 4 and (ar[i] & 1 and ar[j] & 1):
cnt += 1
print cnt
EDIT: I discovered something. any number x, which gives a remainder after % 4, i.e x % 4 != 0, will result to 2 when XORed to a number -2 itself. For example, 6. It is not divisible by 4, therefore, 6 XOR 6-2 (4),==> 2. 10 is not divisible by 4, hence, 10 XOR 10-2 (8) ==> 2. Can you please tell me how this could help me optimize my code? I just know now that I will just look for numbers divisible by 4 and find the count of their + 2.
For simplicity, let´s assume the array does not have duplicates. For the XOR between 2 numbers to be >= 4, they need to have any different bit (excluding lower 2 bits). Given that we already know they are even-even or odd-odd pairs, their lowest bit is the same.
Note that for any number X, X XOR (X + 4 + k) will always be >= 4. So the problem is considering what happens with X XOR (X + 1), X XOR (X + 2) and X XOR (X + 3).
X XOR (X + 1) will be >= 4 when the third lowest bit has changed by adding only 1. That means, we had X ending in 011 so X + 1 ends in 100 or we had X ending in 111 so X + 1 ends in 000. In both cases, this means X % 4 = 3. In any other case (X % 4 != 3), X XOR (X + 1) will be < 4.
For X XOR (X + 2) to be >= 4, the third lowest bit has changed by adding 2. This means, X ended in 011, 010, 111, or 110. So we now have X % 4 = 3 or X % 4 = 2.
For X Xor (X + 3) to be >= 4, the third lowest bit has changed by adding 3. This means, X ended in 011, 010, 001, 111, 110, 101. So we now have X % 4 = 3, X % 4 = 2 or X % 4 = 1.
Here is pseudocode:
for each element in array:
count[element] += 1
total += 1
for each X in sorted keys of count:
if X % 4 == 3:
answer += count[X + 1] + count[X + 2] + count[X + 3]
if X % 4 == 2:
answer += count[X + 2] + count[X + 3]
if X % 4 == 1:
answer += count[X + 3]
total -= count[X]
answer += total - (count[X + 1] + count[X + 2] + count[X + 3]) # all X + 4 + K work
To account for duplicates, we need to avoid counting a number against itself. You will need to keep the count of each number, and do the same as the above with the modification that the answer will be the count of that number * (all the others - the amount of X + 2 numebers)
You should work on separating your code, one improvement is the use of set to avoid repeating operations, although it may get more memory overhead.
import random
from operator import xor
import itertools
random.seed(10)
in_values = [random.randint(0, 10) for _ in range(100)]
def get_pairs_by(condition, values):
odds = set(filter(lambda x: x % 2 == 0, values))
evens = set(filter(lambda x: x % 2 == 1, values))
def filter_pairs_by_condition(values):
return (
(x, y) for x, y in set(
map(lambda x: tuple(sorted(x)),
itertools.product(iter(values), iter(values))))
if condition(xor(x, y))
)
return list(
itertools.chain.from_iterable(
(filter_pairs_by_condition(x) for x in (odds, evens))
)
)
print(get_pairs_by(lambda x: x >= 4, in_values))
The keypoint is:
set(map(lambda x: tuple(sorted(x)),
itertools.product(iter(values), iter(values)))))
What we are doing is that pairs of (5, 7) and (7, 5) should be evaluated as being the same, so we take rid of them there.
Here you have the live example
EDIT:
As a quick update to your code, you can use a dictionary to memoize previously computed pairs, hence:
n = int(raw_input()) #array size
ar = map(int, raw_input().split()) #the array
cnt = 0
prev_computed = {}
for i in xrange(len(ar)):
for j in xrange(i+1, len(ar)):
if any(x in prev_compued for x in ((ar[i], ar[j]), (ar[j], ar[i]))):
cnt += 1
continue
if ar[i] ^ ar[j] >= 4 and (not ar[i] & 1 and not ar[j] & 1):
cnt += 1; #print ar[i],ar[j],ar[i]^ar[j];
prev_computed[(ar[i], ar[j])] = True
prev_computed[(ar[j], ar[i])] = True
elif ar[i] ^ ar[j] >= 4 and (ar[i] & 1 and ar[j] & 1):
cnt += 1
prev_computed[(ar[i], ar[j])] = True
prev_computed[(ar[j], ar[i])] = True
print cnt
def xor_sum(lst)
even_dict = a dictionary with keys being all even numbers of lst and values being their frequencies
odd_dict = a dictionary with keys being all odd numbers of lst and values being their frequencies
total_even_freq = sum of all frequencies of even numbers
total_odd_freq = sum of all frequencies of odd numbers
even_res = process(even_dict, total_even_freq)
odd_res = process(odd_dict, total_odd_freq)
return even_res + odd_res
def process(dict, total_freq)
res = 0
for num in dict.keys
# LSB of XOR of 2 even numbers is always 0
# Let p = XOR of 2 even numbers; if p < 4 then p = 00000000 (minus_2) or 00000010 (plus_2)
plus_2 = num+2
minus_2 = num-2
count = 0
if( (plus_2 XOR num) < 4 and (plus_2 is a key of dict) )
count = count + frequency_of_plus_2
if( (minus_2 XOR num) < 4 and (minus_2 is a key of dict) )
count = count + frequency_of_minus_2
count = count + num
res = res + (total_freq+1-count)
return res
Complexity:
Assuming you have a good hash function for your dictionaries (a hashmap), the average time complexity is O(n)

Longest arithmetic progression with a hole

The longest arithmetic progression subsequence problem is as follows. Given an array of integers A, devise an algorithm to find the longest arithmetic progression in it. In other words find a sequence i1 < i2 < … < ik, such that A[i1], A[i2], …, A[ik] form an arithmetic progression, and k is maximal. The following code solves the problem in O(n^2) time and space. (Modified from http://www.geeksforgeeks.org/length-of-the-longest-arithmatic-progression-in-a-sorted-array/ . )
#!/usr/bin/env python
import sys
def arithmetic(arr):
n = len(arr)
if (n<=2):
return n
llap = 2
L = [[0]*n for i in xrange(n)]
for i in xrange(n):
L[i][n-1] = 2
for j in xrange(n-2,0,-1):
i = j-1
k = j+1
while (i >=0 and k <= n-1):
if (arr[i] + arr[k] < 2*arr[j]):
k = k + 1
elif (arr[i] + arr[k] > 2*arr[j]):
L[i][j] = 2
i -= 1
else:
L[i][j] = L[j][k] + 1
llap = max(llap, L[i][j])
i = i - 1
k = j + 1
while (i >=0):
L[i][j] = 2
i -= 1
return llap
arr = [1,4,5,7,8,10]
print arithmetic(arr)
This outputs 4.
However I would like to be able to find arithmetic progressions where up to one value is missing. So if arr = [1,4,5,8,10,13] I would like it to report that there is a progression of length 5 with one value missing.
Can this be done efficiently?
Adapted from my answer to Longest equally-spaced subsequence. n is the length of A, and d is the range, i.e. the largest item minus the smallest item.
A = [1, 4, 5, 8, 10, 13] # in sorted order
Aset = set(A)
for d in range(1, 13):
already_seen = set()
for a in A:
if a not in already_seen:
b = a
count = 1
while b + d in Aset:
b += d
count += 1
already_seen.add(b)
# if there is a hole to jump over:
if b + 2 * d in Aset:
b += 2 * d
count += 1
while b + d in Aset:
b += d
count += 1
# don't record in already_seen here
print "found %d items in %d .. %d" % (count, a, b)
# collect here the largest 'count'
I believe that this solution is still O(n*d), simply with larger constants than looking without a hole, despite the two "while" loops inside the two nested "for" loops. Indeed, fix a value of d: then we are in the "a" loop that runs n times; but each of the inner two while loops run at most n times in total over all values of a, giving a complexity O(n+n+n) = O(n) again.
Like the original, this solution is adaptable to the case where you're not interested in the absolute best answer but only in subsequences with a relatively small step d: e.g. n might be 1'000'000, but you're only interested in subsequences of step at most 1'000. Then you can make the outer loop stop at 1'000.

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