How to check if any item exists in the list - python

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.)

Related

Loop gets stuck on the third index

Good day. I need to make a function that returns a sum of the two lowest positive integers in the list.
It didn't work out so I've made it print its each step and then I saw that it gets stuck on the third index for some reason. It says 'list index out of range' but I can't quite understand why is it if there are 5 positions in the list. Can't figute it out on my own.
def sum_two_smallest_numbers(numbers):
a = 2147483647
numers = numbers
b = a
for i in range(0, len(numbers)):
print(numbers[i])
if numbers[i] < a and numbers[i] > 0:
a = numbers[i]
numbers.pop(i)
for j in range(0, len(numers)):
if numers[j] < b and numers[j] > 0:
b = numers[j]
numers.pop(j)
return a + b
print(sum_two_smallest_numbers([19, 5, 42, 2, 77]))
This works.
a = [-1, 2, 34, 22, 4]
a = [i for i in a if i > 0]
first_min = min(a)
a.remove(first_min)
second_min = min(a)
print(first_min+second_min)
pop removes a value from the list so each time you use pop the length of your list gets shorter and right now you keep deleting numbers from your list using this algorithm.
def sum_two_smallest_numbers(numbers):
a = 2147483647
numers = numbers
b = a
ind = -1
for i in range(0, len(numbers)):
# print(numbers[i])
if numbers[i] < a and numbers[i] > 0:
a = numbers[i]
ind = i
numbers.pop(ind)
for j in range(0, len(numbers)-1):
if numers[j] < b and numers[j] > 0:
b = numers[j]
return a + b
print(sum_two_smallest_numbers([19, 5, 42, 2, 77]))
Note that this algorithm assumes there are at least 2 positive numbers in your list. Also, there are more efficient ways to do this with only one for loop.
First the rule is never modify a list while iterating on it. You are trying to circumvent it by using indices, but you compute the range before starting the loop and then remove elements from the list => at a time you get an index that is greater or equal than the size of the list.
In addition, you will remove more elements than the smallest one. Let us assume that we fixed the above error and see what happens
first iteration: 19 is less than 2147483647: a = 19 and 19 is removed from the list
next: 5 is less that 19: again a = 5 and 5 is removed which is bad because it is the second smallest element !
So you should at least change your algo to only remove the final smallest element:
def sum_two_smallest_numbers(numbers):
a = 2147483647
numers = numbers
b = a
for i in range(0, len(numbers)):
print(numbers[i])
if numbers[i] < a and numbers[i] > 0:
a = numbers[i]
numbers.remove(a)
for j in range(0, len(numers)):
if numers[j] < b and numers[j] > 0:
b = numers[j]
numers.remove(b)
return a + b
print(sum_two_smallest_numbers([19, 5, 42, 2, 77]))
But this is un-pythonic because Python lists are iterable, and not efficient because you iterate the array twice. This would be better:
def sum_two_smallest_numbers(numbers):
a = b = 2147483647 # a and b will be the 2 smallest elements
for i in numbers:
print(i)
if i < b: # if i >= b : nothing to do
if i < a: # new element is the current smallest
b = a
a = i
else: # new element is the current second smallest
b = i
# uncomment both following line if you want to remove the elements from the array
# as a side effect
# numbers.remove(a)
# numbers.remove(b)
return a + b

IndexError: list index out of range in while loop

I cant get to understand why i`m getting Index Error.
at a = array1[item]
while item <= n:
a = array1[item]
t = mid - a
l = h_f(t)
ab += l
if ab > k:
item+=1
break
ae += h_f(t + 1) - 1
item+=1
n - number of inputed values, item = 0
array1 = [2, 3, 4]
Any help?
An list with n elements has items in indexes 0 through n-1. I.e., your loop should stop before n, not at it. Replace <= with < and you should be OK:
while item < n:
# Here -^
Arrays start indexing from 0 so last index is 2.
While n can be 3 code can get out of bounds
while item < n:

Python List Index Error

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))

Disjoint maxsubarray with alternate signs

i would like to find an algorithm to find the max disjoint subarray with alternated signs (not necessarily contiguos), for example in (2, -3, 4., 5, -4, 3, -3, 5, -2, 1) it returns 7 that is the greatest sum, and the subarray is (5,-3,5)
I tried something like this using dp:
A=[2,-3,4,5,-4,3,-3,5,-2,1]
m = A[0]
flag = A[0] #flag has the same sign of the previously taken element
maximum = m #temporary maxsum
for i in range(1,10):
if A[i]>0 and flag<0 or A[i]<0 and flag>0: #i look only for alternate signs
m = max(m ,A[i]+m)
if m > maximum:
flag = -flag
maximum = m
else:
if A[i]>maximum:
maximum=A[i]
flag=-flag
print(maximum)
it gives 7 but it's only a coincidence
Should i have to use another For nested in order to properly compare every possible subarray?
A=[2,-3,4,5,-4,3,-3,5,-2,1]
dp = [[([], 0), ([], 0)]]
for i, x in enumerate(A):
curr = list(dp[-1])
if x < 0 and curr[0][1] + x > curr[1][1]:
curr[1] = (curr[0][0] + [i], curr[0][1] + x)
elif x > 0 and curr[1][1] + x > curr[0][1]:
curr[0] = (curr[1][0] + [i], curr[1][1] + x)
dp.append(curr)
print dp[-1][0]
This will print a tuple with the indices of the elements to take, and the maximum sum.
Each element in dp represents the best solution up to that point in the list for the case where the next number needs to be positive (first element) and where the next number needs to be negative (second element). Within each of those best solutions, we a list of indices to get to that point, and the maximum sum. The answer is always going to be from the last element in dp where the most recently taken number was positive.
If you don't need to track the elements used:
A=[2,-3,4,5,-4,3,-3,5,-2,1]
dp = [[0, 0]]
for i, x in enumerate(A):
curr = list(dp[-1])
if x < 0 and curr[0] + x > curr[1]:
curr[1] = curr[0] + x
elif x > 0 and curr[1] + x > curr[0]:
curr[0] = curr[1] + x
dp.append(curr)
print dp[-1][0]

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.

Categories