IndexError: list index out of range exeption in python - python

I try to write an algorithm in python, and i dont understand why its out of range.I am realy dont understand where is the problem
This is my code
B = [1, 2, 3, 4]
n = 4
def b(m, i):
if m % 2 == 0 and m > 2:
if i < m - 1:
return 1
else:
return m - 2
else:
return m - 1
def PERM(m):
if m == 1:
print(P)
else:
for i in range(0, m):
PERM(m - 1)
if i < m:
k = P[m]
P[m] = P[b(m, i)]
P[b(m, i)] = k
PERM(n)

in for i in range(0, m):, the loop is iterting from 0 to 4 which is total of 5 index so better you change the n = 4 to n = 3, hope this help :)

Related

Infinite loop in binary search algorithm

I'm a newbie in algorithms. I have recently started studying binary search and tryed to implement it on my own. The task is simple: we have an array of integers a and an integer x. If a contains x the result should be its index, otherwise the function should return -1.
Here is the code I have written:
def binary_search(a, x):
l = 0
r = len(a)
while r - l > 0:
m = (l + r) // 2
if a[m] < x:
l = m
else:
r = m
if a[l] == x:
return l
return -1
But this code stucks in infinite cycle on a = [1, 2] and x = 2. I suppose, that I have incorrect cycle condition (probably, should be r - l >= 0), but this solution does not help. Where am I wrong?
Let me do some desk checking. I'll assume a = [1, 2] and we are searching for a 2
So we start with
l = 0
r = 2
Since r - l = 2 > 0, we enter the while-loop.
m = (l + r) / 2 = (0 + 2) / 2 = 1
a[m] = a[1] = 2 == x (hence not less than x)
r = m = 1 (and l remains the same)
Now r - l = 1 - 0 = 1 > 0, so we continue
m = (l + r) / 2 = (0 + 1) / 2 = 0
a[m] = a[0] = 1 < x
l = m = 0 (and r remains the same)
After this iteration both r and l have the same value as before, which then produces an endless loop.
Ashok's answer is a great fix. But I think it'll be educational to do some desk checking on the fixed code and look what improves it.
Basically the problematic situation arises, when l + 1 = r.
Then m will always evaluate to l, a[l] < x and l is set to m again, which doesn't change the situation.
In a larger piece of code it'll make sense to make a table that contains a column for each variable to watch and a column to write down the code line that was evaluated. A column for remarks won't harm either.
As Mani mentioned you are not considering when A[m]==x. Include that case (at that point you've found a so just return m), and once you have that case we can let l=m+1 when we are still below x. Like this:
def binary_search(a, x):
l = 0
r = len(a)
while r - l > 0:
m = (l + r) // 2
if a[m] < x:
l = m + 1
elif a[m]==x:
return m
else:
r = m
if l<len(a) and a[l] == x:
return l
return -1

Find n integers in list that after multiplying equal to m

I need to print out n indexes of elements of list that after multiplying equal to some given integer. It's guaranteed that the combination exists in a list. For example, for the following input(number of elements in array, multiplication wanted number, number of elements in wanted sublist and given array):
7 60 4
30 1 1 3 10 6 4
I should get in any order
1 2 4 5
Because 1*1*10*6==60. If there are more than 1 solution I need to print any of them.
My solution works but pretty slow, how can I make it work faster?
from itertools import chain, combinations
arr = list(map(int, input().split()))
numbers = list(map(int, input().split()))
s = sorted(numbers)
def filtered_sublists(input_list, length):
return (
l for l in all_sublists(input_list)
if len(l) == length
)
def all_sublists(l):
return chain(*(combinations(l, i) for i in range(len(l) + 1)))
def multiply(arr):
result = 1
for x in arr:
result = result * x
return result
def get_indexes(data):
indexes = []
for i in range(len(data)):
if arr[1] == multiply(data[i]):
for el in data[i]:
if numbers.index(el) in indexes:
all_ind = [i for i, x in enumerate(numbers) if x == el]
for ind in all_ind:
if ind not in indexes:
indexes.append(ind)
break
else:
indexes.append(numbers.index(el))
break
return indexes
sublists = list(filtered_sublists(numbers, arr[2]))
print(*get_indexes(sublists))
The key is don't test every combination.
def combo(l, n=4, target=60, current_indices=[], current_mul=1):
if current_mul > target and target > 0:
return
elif len(current_indices) == n and current_mul == target:
yield current_indices
return
for i, val in enumerate(l):
if (not current_indices) or (i > current_indices[-1] and val * current_mul <= target):
yield from combo(l, n, target, current_indices + [i], val * current_mul)
l = [30,1,1,3,10,6,4]
for indices in combo(l, n=4, target=60):
print(*indices)
Prints:
1 2 4 5
More testcases:
l = [1,1,1,2,3,3,9]
for c, indices in combo(l, n=4, target=9):
print(*indices)
Prints:
0 1 2 6
0 1 4 5
0 2 4 5
1 2 4 5
We can use a memoized recursion for an O(n * k * num_factors), solution, where num_factors depends on how many factors of the target product we can create. The recurrence should be fairly clear from the code. (Zeros aren't handled but those should be pretty simple to add extra handling for.)
Pythonesque JavaScript code:
function f(A, prod, k, i=0, map={}){
if (i == A.length || k == 0)
return []
if (map[[prod, k]])
return map[[prod, k]]
if (prod == A[i] && k == 1)
return [i]
if (prod % A[i] == 0){
const factors = f(A, prod / A[i], k - 1, i + 1, map)
if (factors.length){
map[[prod, k]] = [i].concat(factors)
return map[[prod, k]]
}
}
return f(A, prod, k, i + 1, map)
}
var A = [30, 1, 1, 3, 10, 6, 4]
console.log(JSON.stringify(f(A, 60, 4)))
console.log(JSON.stringify(f(A, 60, 3)))
console.log(JSON.stringify(f(A, 60, 1)))
You could start from the target product and recursively divide by factors in the remaining list until you get down to 1 and after using the specified number of factors. This has the advantage of quickly eliminating whole branches of recursion under numbers that are not a factor of the target product.
Handling zero values in the list and a target product of zero requires a couple of special conditions at the start and while traversing factors.
For example:
def findFactors(product, count, factors, offset=0):
if product == 0: return sorted((factors.index(0)+i)%len(factors) for i in range(count))
if not count: return [] if product == 1 else None
if not factors: return None
for i,factor in enumerate(factors,1):
if factor == 0 or product%factor != 0: continue
subProd = findFactors(product//factor,count-1,factors[i:],i+offset)
if subProd is not None: return [i+offset-1]+subProd
r = findFactors(60, 4, [30,1,1,3,10,6,4])
print(r) # [1, 2, 4, 5]
r = findFactors(60, 4, [30,1,1,0,3,10,6,4])
print(r) # [1, 2, 5, 6]
r = findFactors(0, 4, [30,1,1,3,10,6,0,4])
print(r) # [0, 1, 6, 7]

Python Quicksort implementation

I tried to implement the recursive quicksort in Python, but it doesn't work. I know that there is the problem that the array doesn't get sorted because the pivot is always higher than i, which results in the problem that i is always equals to m.
def partition(array):
pivot = array[-1]
m = 0
for i in range(len(array) - 1):
if array[i] < pivot:
array[i], array[m] = array[m], array[i]
m += 1
else:
continue
array[m], array[len(array)-1] = array[len(array)-1], array[m]
return m
def quicksort(array):
if len(array) > 1:
m = partition(array)
quicksort(array[:m])
quicksort(array[m+1:])
return array
def main():
testarray = [3,6,2,4,5,1,9,8,7,10,14]
print(quicksort(testarray))
if __name__ == '__main__':
main()
Two things. Firstly, you forgot to return array when it's of length 1, and secondly you aren't actually modifying array before returning. This will work.
def quicksort(array):
if len(array) > 1:
m = partition(array)
# return the concatenation of the two sorted arrays
return quicksort(array[:m]) + quicksort(array[m:])
else:
return array
For those looking for an iterative/non-recursive version of Quicksort, here's an implementation I came up with in Python:
from random import randint
def default_comparator_fn(a, b):
return -1 if a < b else (1 if a > b else 0)
def reverse_comparator_fn(a, b):
return default_comparator_fn(b, a)
def quick_sort(A, comparator_fn=default_comparator_fn):
n = len(A)
if n < 2:
# The list has only 1 element or does not have any.
return A
# There are at least 2 elements.
partitions = [[0, n - 1]] # [[start, end]]
while len(partitions):
partition = partitions.pop()
start = partition[0]
end = partition[1]
pivot_index = randint(start, end)
pivot = A[pivot_index]
A[pivot_index], A[start] = A[start], A[pivot_index]
breakpoint_index = start
k = start + 1
m = end
while k <= m:
res = comparator_fn(A[k], pivot)
if res < 0:
breakpoint_index = k
else:
while m > k:
res = comparator_fn(A[m], pivot)
if res < 0:
breakpoint_index = k
A[m], A[k] = A[k], A[m]
m -= 1
break
m -= 1
k += 1
A[start], A[breakpoint_index] = A[breakpoint_index], A[start]
if start < breakpoint_index - 1:
partitions.append([start, breakpoint_index - 1])
if breakpoint_index + 1 < end:
partitions.append([breakpoint_index + 1, end])
return A
# Example:
A = [4, 2, 5, 1, 3]
quick_sort(A) # Sort in ascending order ([1, 2, 3, 4, 5]).
quick_sort(A, reverse_comparator_fn) # Sort in descending order ([5, 4, 3, 2, 1]).
This implementation of Quicksort accepts an optional custom comparator function which defaults to a comparator which compares the elements of the list in ascending order.

Function which measures time M times

I am to measure how much time does it take for the function below to represent: C in range [0, 10] with the numbers in list N. (M measurements for each C).
import itertools
def amount(C):
N = [1, 2, 5]
#N = list(N)
N = sorted(N)
while C < max(N):
N.remove(max(N))
res = []
for i in range(1, C):
for j in list(itertools.combinations_with_replacement(N, i)):
res.append(sum(list(j)))
m = 0
for z in range (0, len(res)):
if res[z] == C:
m += 1
if N[0] == 1:
return m + 1
else:
return m
EDITED:
import itertools
def amount(C):
N = [1, 2, 5]
res = []
for i in range(1, C):
for j in list(itertools.combinations_with_replacement(N, i)):
res.append(sum(list(j)))
m = 0
for z in range (0, len(res)):
if res[z] == C:
m += 1
if N[0] == 1:
return m + 1
else:
return m
I would like to make 10 measurements and then take for example median of all those measurements.
There is my code but something unfortunately doesn't work properly and I have no idea what is wrong:
import time
def time_counter(amount, n=11, M=11):
res = list(range(n))
def count_once():
start = time.perf_counter()
amount(res)
return time.perf_counter() - start
return [count_once() for m in range(M)]
You are again passing a list and trying to do range(1,C) where C is a list
Here is how your program should be
import itertools
import time
def amount(C):
N = [1, 2, 5]
res = []
for i in range(1, C):
for j in list(itertools.combinations_with_replacement(N, i)):
res.append(sum(list(j)))
m = 0
for z in range (0, len(res)):
if res[z] == C:
m += 1
if N[0] == 1:
return m + 1
else:
return m
def time_counter(amount, n=11, M=11):
res = list(range(n))
def count_once(c):
start = time.perf_counter()
amount(c)
return time.perf_counter() - start
return [count_once(m) for m in range(M)]
#testing
print(time_counter(amount))

NZEC error in Python spoj

Please have a look at my code and tell me where I am going wrong.
I am trying to solve a problem on SPOJ and the online judge gives me a runtime error (NZEC)
I am trying to solve this problem - http://www.spoj.com/problems/PRIME1/
def isprime(n):
if n < 2:
return 1
if n == 2 or n == 3:
return 0
if n % 2 == 0 or n % 3 == 0:
return 1
for i in range(5, int(n ** 0.5) + 1, 6):
if n % i == 0 or n % (i + 2) == 0:
return 1
return 0
t = int(raw_input())
for i in range(0,t):
m = int(raw_input())
n = int(raw_input())
for j in range(m,n+1):
if isprime(j) == 0:
print j
print
From my experience NZEC just means some exception along the way. Most likely input-related.
For example my input for the problems looks like:
t = int(raw_input())
data = sys.stdin.readlines()
for line in data:
n, m = map(int, line.split())
And indeed raw_input gets the whole line, which you're trying to convert to int. But the problem states both m and n are on the same line:
Input:
2
1 10
3 5

Categories

Resources