Checker board algorithm implementation - python

def Checker(n):
p = [[7,3,5,6,1],[2,6,7,0,2],[3,5,7,8,2],[7,6,1,1,4],[6,7,4,7,8]] #profit of each cell
cost = [[0 for j in range(n)] for i in range(n)]
w = [[0 for j in range(n)] for i in range(n)] #w[i, j] store the column number (j) of the previous square from which we moved to the current square at [i,j]
for j in range(1,n):
cost[1][j] = 0
for i in range(2,n):
for j in range(1,n):
max = cost[i-1][j] + p[i-1][j]
w[i][j] = j
if (j > 1 and cost[i-1][j-1] + p[i-1][j-1] > max):
max = cost[i-1][j-1] + p[i-1][j-1]
w[i][j] = j-1
if (j < n and cost[i-1][j+1] + p[i-1][j+1] > max):
max = cost[i-1][j+1] + p[i-1][j+1]
w[i][j] = j+1
cost[i][j] = max
print cost[i][j]
maxd = cost[1][1]
maxj = 1
for j in range(2,n):
if cost[1][j] >maxd:
maxd = cost[1][j]
maxj = j
print "Maximum profit is: ",maxd
printsquares(w,n,maxj)
def printsquares(w,i,j):
if i == -1:
return
print "Square at row %d and column %d"%(i,j)
printsquares(w,i-1,w[i][j])
if __name__ == '__main__':
print "5*5 checker board problem"
n = 5
Checker(n)
The above program is implementation of checker board algorithm in python.
when i run the above code the following error is shown:
if (j < n and cost[i-1][j+1] + p[i-1][j+1] > max): IndexError: list
index out of range
what am i doing wrong and any one would propose solution for it?

To avoid the IndexError exceptions,
if (j < n and cost[i-1][j+1] + p[i-1][j+1] > max):
max = cost[i-1][j+1] + p[i-1][j+1]
should be written:
if (j < n-1 and cost[i-1][j+1] + p[i-1][j+1] > max):
max = cost[i-1][j+1] + p[i-1][j+1]
and
printsquares(w,i-1,w[i][j])
becomes
printsquares(w,i-1,w[i-1][j])
But as said by other fellows, I'm not certain that the algorithm is correctly implemented.

You're pretty much trying to do this:
L = range(5)
print L[5+1]
At cost[i-1][j+1].
There is no 6th element. There's only five. Hence the IndexError.
As for a solution, you probably only want n and not n+1 if you want the last element. However, I'm not 100% sure.

It looks like you are trying to adapt an algorithm from a language where lists start from 1 whereas they start from 0 in Python. As far I as checked, you never access cost[i][0].

Related

How to reduce time complexity of this program

The entry Y [i][j] stores the sum of the subarray X[i..j], but can I get a better time complexity?
def func(X, n):
Y = [[0 for i in range(n)] for j in range(n)]
for i in range(n):
for j in range(i, n):
for k in range(i, j+1):
Y[i][j] += X[k]
return Y
if __name__ == "__main__":
n = 500
X = list(range(n))
for i in range(30, 50):
print(X[i], end=" ")
print()
print(func(X, n)[30][49])
You could use a prefix sum array.
The idea is that you have an array where the entry ps[i] denotes the sum of all elements arr[0..i]. You can calculate it in linear time:
ps[0] = arr[0]
for i in range(1, len(arr)):
ps[i] = ps[i - 1] + arr[i]
Can you guess how to retrieve a sum Y(i, j) in constant time?
Solution: Y(i, j) = ps[j] - ps[i - 1]. You take the entire sum of the array from j to the start and subtract the part that you don't want again (which is from i-1 to the start).
Note: It is possible that I messed up some edge cases. Be wary for things like i=0, j=0, j<i, etc.

Why this Merge Sort does not work properly?

I need to implement Merge Sort using Python 3. I coded it. But It doesn't give proper output. Can anybody check it please?
Here my code is,
def mergeSort(A, p, r):
if p < r:
q = (p + r) // 2
mergeSort(A, p, q)
mergeSort(A, q+1, r)
Merge(A, p, q, r)
def Merge(A, p, q, r):
i = 1
j = q+1
k = 0
TEMP = [0] * (r+1)
while i <= q and j <= r:
if A[i] <= A[j]:
TEMP[k] = A[i]
k += 1
i += 1
else:
TEMP[k] = A[j]
k += 1
j += 1
if (j > r) :
for t in range(0, q-1):
A[r-t] = A[q-t]
for t in range(0, k-1):
A[p+t] = TEMP[t+1]
A = [15, 16, 13, 10, 19, 18]
mergeSort(A, 0, len(A)-1)
print(A)
Thank you
The way you perform merge looks weird (to me), but I will correct on what you have so far.
1- Initialization value of i is wrong, it should be:
i = p
because i is the first element you will look in array A.
2- Initialization value of size of TEMP array is wrong, it should be:
(r - p + 1)
3- There seems a mistake in filling in TEMP array and/or replacing A array elements, here is the fixed code. I wrote a comment about the part after first while loop to indicate what needs to be done at that point.
def mergeSort(A,p,r):
if p < r:
q = (p+r)//2
mergeSort(A,p,q)
mergeSort(A,q+1,r)
Merge(A,p,q,r)
def Merge(A,p,q,r):
i = p
j = q+1
k=0
TEMP = [0]*(r - p + 1)
while i <= q and j <= r:
if A[i] <= A[j]:
TEMP[k] = A[i]
k += 1
i += 1
else:
TEMP[k] = A[j]
k += 1
j += 1
"""
There are currently 2 cases
1- i > q, means we exhausted left but there are elements in the right
2- j > r, means we exhausted right but there are elements in the left
"""
if (j > r):
# copy elements at the left side to temp
while (i <= q):
TEMP[k] = A[i]
i += 1
k += 1
else:
# copy elements at the right side to temp
while (j <= r):
TEMP[k] = A[j]
j += 1
k += 1
# replace elements in A with elements in TEMP
for t in range(k):
A[p+t] = TEMP[t]
A = [15,16,13,10,19,18]
mergeSort(A,0,len(A)-1)
print(A)
The error lies in the Merge() function.
Initialisation of i=p and not i=1
After the while loop terminates, there's a chance that either i<q or j<r. We need to accommodate those cases as well.
Size of array TEMP was incorrect.
Corrected Merge Function:
def Merge(A,p,q,r):
i = p
j = q+1
k=0
TEMP = [0]*(r-p+1)
while i <= q and j <= r:
if A[i] <= A[j]:
TEMP[k] = A[i]
k += 1
i += 1
else:
TEMP[k] = A[j]
k += 1
j += 1
while i<=q:
TEMP[k] = A[i]
k+=1
i += 1
while j<=r:
TEMP[k] = A[j]
k+=1
j += 1
for t in range (p,r+1):
A[t] = TEMP[t-p]
Note: Please try using more meaningful variable names.

Dynamic Programming: Rod cutting and remembering where cuts are made

So I have this code in python and currently it only returns the maximum value for cutting a rod. How can I modify this to also give me where the cuts were made? It takes a list of prices whose indices+1 correspond to the value of the rod at each length, and n, for length of the rod.
the problem:http://www.radford.edu/~nokie/classes/360/dp-rod-cutting.html
def cutRod(price, n):
val = [0 for x in range(n+1)]
val[0] = 0
for i in range(1, n+1):
max_val = 0
for j in range(i):
max_val = max(max_val, price[j] + val[i-j-1])
val[i] = max_val
return val[n]
If this is the question : Rod cutting
Assuming code works fine, You will have to add a condition instead of Max operation to check which of two was picked and push that one in an array :
def cutRod(price, n):
val = [0 for x in range(n+1)]
val[0] = 0
output = list()
for i in range(1, n+1):
max_val = 0
cur_max_index = -1
for j in range(i):
cur_val = price[j] + val[i-j-1]
if(cur_val>max_val):
max_val = cur_val #store current max
cur_max_index = j #and index
if cur_max_index != -1:
output.append(cur_max_index) #append in output index list
val[i] = max_val
print(output) #print array
return val[n]
I know this is old but just in case someone else has a look...I was actually just looking at this problem. I think the issue is here that these dp problems can be tricky when handling indices. The previous answer is not going to print the solution correctly simply because this line needs to be adjusted...
cur_max_index = j which should be cur_max_index = j + 1
The rest...
def cut_rod(prices, length):
values = [0] * (length + 1)
cuts = [-1] * (length + 1)
max_val = -1
for i in range(1, length + 1):
for j in range(i):
temp = prices[j] + values[i - j - 1]
if temp > max_val:
max_val = prices[j] + values[i - j - 1]
cuts[i] = j + 1
values[i] = max_val
return values[length], cuts
def print_cuts(cuts, length):
while length > 0:
print(cuts[length], end=" ")
length -= cuts[length]
max_value, cuts = cut_rod(prices, length)
print(max_value)
print_cuts(cuts, length)
Well, if you need to get the actual pieces that would be the result of this process then you'd probably need a recursion.
For example something like that:
def cutRod(price, n):
val = [0 for x in range(n + 1)]
pieces = [[0, 0]]
val[0] = 0
for i in range(1, n + 1):
max_val = 0
max_pieces = [0, 0]
for j in range(i):
curr_val = price[j] + val[i - j - 1]
if curr_val > max_val:
max_val = curr_val
max_pieces = [j + 1, i - j - 1]
pieces.append(max_pieces)
val[i] = max_val
arr = []
def f(left, right):
if right == 0:
arr.append(left)
return
f(pieces[left][0], pieces[left][1])
f(pieces[right][0], pieces[right][1])
f(pieces[n][0], pieces[n][1])
return val[n], arr
In this code, there is an additional array for pieces which represents the best way to divide our Rod with some length.
Besides, there is a function f that goes through all pieces and figures out the optimal way to divide the whole Rod.

Python: What is wrong with the indexing logic in my code?

"You are given an array of n integers and an integer k. Find and print the number of (i,j) pairs where i<j and a[i] + a[j] is evenly divisible by k."
Sample input would be:
6 3
1 3 2 6 1 2
where 6 is n, 3 is k and the second line is the array of integers. The output for this input would be 5.
Here is my code, but i am not passing the test cases and am almost positive it has to do with how i am indexing it.
import sys
n,k = input().strip().split(' ')
n,k = [int(n),int(k)]
a = [int(a_temp) for a_temp in input().strip().split(' ')]
count=0;
for i in range(n):
curr = n-i
for j in range(curr):
if i < i + j:
if k % (a[i] + a[i+j]) ==0:
count = count + 1
print(count)
Also, followup question: Is this method i am approaching an efficient way of going about it?
you can try this ...
import sys
n,k = input().strip().split(' ')
n,k = [int(n),int(k)]
a = [int(a_temp) for a_temp in input().strip().split(' ')]
print(sum([1 for i in range(n) for j in range(i) if (a[i]+a[j])%k==0]))
k % ... means "k is divisible by ...", not "... is divisible by k".
if i < i + j is not very useful; you're better off doing what furas recommends in comments.
What you need is to make use of itertools.combinations:
from itertools import combinations
count = 0
for i, j in combinations(range(n), 2):
if i < j and (a[i] + a[j]) % k == 0:
print i, j
count += 1
Discussion
range(n) returns a list of indices 0 .. n-1
combinations(range(n), 2) will yield a list of two indices (without duplications)
(a[i] + a[j]) % k == 0 is the test that your asked
Note that combinations will yield pairs of i, j where i is always less than j, but the test i < j is there as a paranoid measure

Finding median of two sorted arrays. Can some inequality checks be eliminated?

Working on this problem and post code, my question is whether it is safe to change this line of code
j > 0 and i < m and B[j-1] > A[i]
to
i < m and B[j-1] > A[i]
and also it is safe to change this line of code
i > 0 and j < n and A[i-1] > B[j]
to
i > 0 and A[i-1] > B[j]
I think remove the condition check of j is safe since we already making sure size of A is no bigger than size of B.
Problem statement
There are two sorted arrays nums1 and nums2 of size m and n respectively. Find the median of the two sorted arrays. The overall run time complexity should be O(log (m+n)).
Implementation
def median(A, B):
m, n = len(A), len(B)
if m > n:
A, B, m, n = B, A, n, m
if n == 0:
raise ValueError
imin, imax, half_len = 0, m, (m + n + 1) / 2
while imin <= imax:
i = (imin + imax) / 2
j = half_len - i
if j > 0 and i < m and B[j-1] > A[i]:
# i is too small, must increase it
imin = i + 1
elif i > 0 and j < n and A[i-1] > B[j]:
# i is too big, must decrease it
imax = i - 1
else:
# i is perfect
if i == 0: max_of_left = B[j-1]
elif j == 0: max_of_left = A[i-1]
else: max_of_left = max(A[i-1], B[j-1])
if (m + n) % 2 == 1:
return max_of_left
if i == m: min_of_right = B[j]
elif j == n: min_of_right = A[i]
else: min_of_right = min(A[i], B[j])
return (max_of_left + min_of_right) / 2.0
Yes I think, you can remove the condition j > 0, because
j = half_len - i
and you already check that i<m and (m + n + 1) / 2 must be bigger than m since n>=m
same for the second condition j < n. You already make sure that i>0, which ensures that j can at most be (2n+1)/2 - 1 which is smaller than n and thus automatically satisfies your condition

Categories

Resources