I have case like this:
#!/usr/bin/python2.7
y = [[0 for i in xrange(size_of_array)] for j in xrange(size_of_array)]
offset_flag = 0
for i in xrange(size_of_array):
for j in xrange(size_of_array):
y[i][j] = starting_no + j + offset_flag
offset_flag += j + 1
I want list comprehension of nested for loop but also it should handle case like follows:
offset_flag += j + 1
How can I achieve this kind of list comprehension ?
Just use multiplication instead to calculate your offset:
y = [[starting_no + j + (i * size_of_array) for j in xrange(size_of_array)]
for i in xrange(size_of_array)]
which can be written a little more concisely using shorter variable names:
start, size = starting_no, size_of_array
y = [[start + j + (i * size) for j in xrange(size)] for i in xrange(size)]
Your offset value is nothing more than i * size_of_array here; each iteration of the outer loop you add j + 1, but j is always going to be set to size_of_array - 1. Substitute j for size_of_array - 1 and you get offset += size_of_array. The first iteration it is 0, then 1 * size_of_array, all the way up to (size_of_array - 1) * size_of_array, following the i variable.
Your entire code could be replaced with:
# Changing variables for cleaner expression:
# size_of_array -> s_a
# starting_no -> start
y = [[start + j + (i*s_a) for j in xrange(s_a)] for i in xrange(s_a)]
Related
I was trying out longest palindromic subsequence problem from leetcode.
One of the discussed solution is as follows:
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
n = len(s)
dp = [[0] * n for _ in range(n)]
for i in range(n - 1, -1, -1):
dp[i][i] = 1
for j in range(i+1, n):
if s[i] == s[j]:
dp[i][j] = dp[i + 1][j - 1] + 2
else:
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
return dp[0][n - 1]
So it starts from end of the string:
I was guessing if it is possible to begin from the starting of the string. That is if its possible to have loops something like this:
for i in range(0, n):
for j in range(i+1, n):
# ...
But dp[i + 1] wont be calculated for any given iteration of i and we need dp[i+1] for evaluating
dp[i][j] = dp[i + 1][j - 1] + 2 and
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
Is it possible to change these two updates to dp (and hence come up with new recurrence relation) in some way to make it possible to begin from the starting of the string or starting from the end of the string is the only way possible !? (I was not able to come up with any recurrence solution / index adjustments to make it possible. So I have started to believe that its indeed not possible. But I wanted to be sure.)
The first hint that you can do this from the beginning is that let's say you're given a string 'baabbcc' that this logic gets the answer for, the same logic will work for the reversed string as well ('ccbbaab').
The more robust reasoning for this can be derived from what dp[i][j] represents. The value represents the Longest Palindromic Subsequence between i and j inclusive. We calculate this dp array using two pointers, say i and j.
We iterate over all possible values of i and j, and if s[i] == s[j] then we know that the answer from i to j will be equal to the answer for i+1 to j-1 + 2 because we can take the answer from i+1 to j-1 and add s[i] and s[j] to the beginning and end of that. I hope this is clear from the code you provided.
What that means is that to calculate dp[i][j], you need dp[i+1][j-1].
The code you have provided does this by starting the i pointer from the ending and for every i, it loops from j = i till j = n-1. This means that i+1 is reached before i and j-1 is reached before j.
However, you can achieve the same effect starting from the beginning. This time, start by moving the j pointer from the beginning, and for every j, move the i pointer backward from i = j till i = 0. This ensures that j-1 is reached before j and i+1 is reached before i, which is what we're looking for.
The final code would look something like this (Which I've submitted and gotten accepted):
class Solution:
def longestPalindromeSubseq(self, s: str) -> int:
n = len(s)
dp = [[0] * n for _ in range(n)]
for j in range(0, n):
dp[j][j] = 1
for i in range(j-1, -1, -1):
if s[i] == s[j]:
dp[i][j] = dp[i + 1][j - 1] + 2
else:
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
return dp[0][n - 1]
My Y[], Y1[] both have range(0, 8736). When running the code below, why does the range extend by 1 to range(0, 8737)?
diff = []
for i in range(len(Y)):
if(Y[i]==0):
diff.append(1)
if(Y1[i]==0):
diff.append(1)
else:
var = Y[i] / Y1[i]
diff.append(var)
print(range(len(diff)))
When i = 0 you append 1 twice, therefore len(diff) = len(Y) + 1 = len(Y1) + 1
I want to count how many inversions there are in a list while sorting the list using mergesort. This is my code so far where 'x' counts the ammount of inversions while the rest sorts it:
import sys
x = 0
def merge_sort(A):
merge_sort2(A, 0, len(A) - 1)
def merge_sort2(A, first, last):
if first < last:
middle = (first + last) // 2
merge_sort2(A, first, middle)
merge_sort2(A, middle + 1, last)
merge(A, first, middle, last)
def merge(A, first, middle, last):
global x
L = A[first:middle + 1]
R = A[middle + 1:last + 1]
L.append(sys.maxsize)
R.append(sys.maxsize)
i = j = 0
for k in range(first, last + 1):
if L[i] <= R[j]:
A[k] = L[i]
i += 1
else:
A[k] = R[j]
j += 1
x += 1
x += len(L[first + 1:])
When I call merge sort using a list, the variable x is support to give the amount of inversions in the list. So If the list was '[4,3,2,1], x would be 6. If the list was [1,2,3] x would be 0. I change the value of x whenever the right is greater than the left in the merge definition however, the number always gets way too big. What am I doing wrong?
Check my work but, I think instead of:
x += 1
x += len(L[first + 1:])
you want:
x += middle + 1 + j - k
basically, you want to add the difference between where item k is actually coming from, and where you'd expect it to come from if everything was already sorted.
Your merge step is a little hard for me to understand — I'm not sure why you are doing this (maybe just another way to merge?):
L.append(sys.maxsize)
R.append(sys.maxsize)
but I couldn't get everything to work out with the extra elements added to the partitions. And I think you end up counting the extra element in L as an inversion with each merge move from R
I think that's causing some of the problems. But you also have two other issues:
Your last line isn't quite the right logic:
x += len(L[first + 1:])
the number of inversions will the number of elements in L that you jump over. You're counting almost every element of L each time. Something like this works better:
x += len(L[i:])
and then at the end, you may have elements left over whose inversions you haven't counted yet. Maybe that's not an issue with your extra elements but in a more traditional merge it is. Here's the way I would count the inversions:
def merge(A, first, middle, last):
global x
L = A[first:middle+1]
R = A[middle+1:last+1]
i = j = 0
k = first
print(L, R)
while i<len(L) and j<len(R):
if L[i] <= R[j]:
A[k] = L[i]
i += 1
else:
A[k] = R[j]
j += 1
# count how many left in L
x += len(L[i:])
k += 1
# take care of any leftovers in L or R
while i < len(L):
A[k] = L[i]
i += 1
k+=1
while j < len(R):
A[k] = R[j]
j += 1
k+=1
x += len(L[i:])
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.
I have the functions:
h(0) = 0
h(1) = 3
h(n) = h(n-1) + 2 * h(n-2), for n>= 2
I need to convert this into a for loop, while loop, and recursive function. I have the recursive function figured out, but I can't seem to output the correct answer. My attempt at the for loop is this:
def hForLoop(n):
sum = 3
for i in range(2, n):
sum = sum + ((i - 1) + 2 * (i - 2))
return sum
I can't seem to figure out why I'm outputting the wrong answer. Some insight would be very useful and I will be very grateful.
Here's the version that stores just the last two values in a series:
def hForLoop(n):
prev, cur = 0, 3
for i in range(2, n + 1):
cur, prev = cur + prev * 2, cur
return cur
The issue is in you for-loop, where you increment sum with ((i - 1) + 2 * (i - 2)).
If you understood the original functions, it should really be increment sum with the previously computed value stored at h(i-1) and h(i-2).
Here's my fix to your for-loop function:
def hForLoop(n):
sum = [0,3]
for i in range(2, n+1):
sum.append((sum[i - 1]) + 2 * (sum[i - 2]))
return sum[n]
You need to store the intermediate values for h(n-1) and h(n-2) for the next iteration of the loop, where you use the values to calculate the next h(n).
def hLoop(n):
# initally [h(2), h(1), h(0)]
h = [3, 3, 0]
# And in the following: [ h(i), h(i-1), h(i-2)]
for i in range(2, n + 1):
# calculate h(i)
h[0] = h[1] + 2 * h[2]
# move 'index' forward, h(n-1) becomes h(n-2), h(n-1) becomes h(n-0)
h[2] = h[1]
h[1] = h[0]
return h[0]
With original function:
h(0) = 0
h(1) = 3
h(n) = h(n-1) + 2 * h(n-2), for n>= 2
you actual code is:
h(0) = 0
h(1) = 3
h(n) = Σ((n-1) + 2 * (n-2)), for n>= 2
See the difference?