longest common subsequence matrix difference python - python

I'm working on a dynamic programming problem (longest common subsequence)
My issue: building the matrix.
I initially build my matrix with dp1. but it kept churning out the wrong answers. Then I referenced other answers and used dp2, which produces the right answer.
For example:
s1 = ELGGYJWKTDHLXJRBJLRYEJWVSUFZKYHOIKBGTVUTTOCGMLEXWDSXEBKRZTQUVCJNGKKRMUUBACVOEQKBFFYBUQEMYNENKYYGUZSP
s2 = FRVIFOVJYQLVZMFBNRUTIYFBMFFFRZVBYINXLDDSVMPWSQGJZYTKMZIPEGMVOUQBKYEWEYVOLSHCMHPAZYTENRNONTJWDANAMFRX
The right answer should be 27.
dp1 gives 30
dp2 gives 27
I'm puzzled. What's the difference? isn't "for _ in range(m+1)" essentially iterating whatever is before by m+1 times? please help me out.
def commonChild(s1, s2):
n, m = len(s1), len(s2)
dp1 = [[0] * (n+1)] * (m+1)
dp2 = [[0] * (n+1) for _ in range(m+1)]
for i in range(m):
for j in range(n):
if s2[i] == s1[j]:
dp[i+1][j+1] = dp[i][j] +1
else:
dp[i+1][j+1] = max(dp[i][j+1], dp[i+1][j])
return dp[-1][-1]

>>> a=[[0] * (5) for i in range(4)]
>>> a
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
>>> a[0][0]=1
>>> a
[[1, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
>>> a=[[0] * (5) ]*4
>>> a[0][0]=1
>>> a
[[1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0], [1, 0, 0, 0, 0]]
You can see the difference yourself,
in [[0]*(n+1)]*(m+1) it is referring to the same array [0] * (n+1) so changing one array value changes the same value in all

Related

How to loop by specific step

I have a nested loop data=
[[1,43,344,546],[2,34,45,565]....[10,1,1,1],
[1,15,111,151],[2,152,28,19]....[10,2,2,2],
[1,21,45,1647],[2,288,65,90]....[10,3,3,3]
.....]
so basically, all the inside lists can be grouped by 10lists with the first element always starting from 1 to 10. taking the every 10th list as a key, so I want to calculate a newlist by subtracting every list's number by the 10th list accordingly, for example
[[1,43-1,344-2,546-3], [2,34-1,45-2,565-3].... [10,1,2,3],
[1,15-21,111-22,151-23],[2,152-21,28-22,19-23]....[10,21,22,23],
[1,21-31,45-32,1647-33],[2,288-31,65-32,90-33]....[10,31,32,33]
.....]
My code seems don't work, can someone plz help with this? thanks
line = 0
while line <= (len(data) - 10):
for i in range(line, line + 10):
temp = data[i]
if temp[0] == 10: #find the every 10 th keys and store them to x, y, z
x = temp[1]
y = temp[2]
z = temp[3]
break
for sublist in data:
sublist[1] = sublist[1] - x# assign new elements to original list data
sublist[2] = sublist[2] - y
sublist[3] = sublist[3] - z
line += 10
return data
This is one way to do what you want
from pprint import pprint
def next_mul(n):
"returns next multiple of 10 greater than n"
return n + (10 - n % 10)
# sample data
data = [[i for i in range(4)] for i in range(20)]
for i in range(len(data)):
if i % 10 == 0:
continue
data[i-1][1:] = [k-l for k,l in zip(data[next_mul(i)-1][1:], data[i-1][1:])]
pprint(data)
Output (originally every sublist of data was just [0, 1, 2, 3]):
[[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 1, 2, 3],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 0, 0, 0],
[0, 1, 2, 3]]
Hope this helps. Please let me know if there are any questions/concerns!

How to produce this specific list of lists

I have a bit of a complicated problem. I'm trying to make a function which takes in a list of 0s and 1s and returns a list of lists. It's easiest if I just show an example
input :
[0,0,0,1,0,1]
output :
[[0,0,0,0,0,0,0],[1,0,0,0,1,0,0],[1,0,0,0,1,0,1],[1,0,0,0,0,0,1],[1,0,0,0,0,0,0]]
Another example
input :
[1,0,1]
output :
[[0,0,0,0],[1,1,0,0],[1,0,0,1],[1,1,0,1],[1,0,0,0]]
I have a solution right now, where I first produce all the the combinations and then filters out the ones that are not allowed. But this demands massive amount of memory so I'm looking for a better solution.
def func(input):
A = list(itertools.product(range(2), repeat=int(len(input)+1)))
# Filters out all the lists which have first element equal to 0
# and 1s anywhere else
A = [item for item in A if not (item[0] == 0 \
and sum(item) >= 1 or item[A.index(item)+1] == 1) ]
# Filter out all lists which has 1s at places the input does not have
A = [item for item in action_space if not \
sum(np.bitwise_and(np.bitwise_xor(item[1:], \
self.adj_mat[node.get_node_nr()]),item[1:])) > 0]
return A
You can get a list of the indices to mutate, then use itertools.product to generate all the possible variations.
from itertools import product
def func(l):
indicies = [i for i, x in enumerate(l, start=1) if x]
prod = product([0, 1], repeat=len(indicies))
yield [0] * (len(l) + 1)
for variation in prod:
temp = [1, *l]
for index, value in zip(indicies, variation):
temp[index] = value
yield temp
print(list(func([0,0,0,1,0,1])))
# [[0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 1, 0, 0], [1, 0, 0, 0, 1, 0, 1]]
print(list(func([1,0,1])))
# [[0, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 1], [1, 1, 0, 0], [1, 1, 0, 1]]
Idea: Get indices. Then take all subsets of indices to generate sublists to add to result
from itertools import chain, combinations
def powerset(iterable):
s = list(iterable)
return chain.from_iterable(combinations(s, r) for r in range(len(s)+1))
lst = [0,0,0,1,0,1]
indices = [i for i, x in enumerate(lst) if x == 1]
result = [[0] * (len(lst)+1)]
for element in powerset(s):
new_element = [[0] * (len(lst)+1)]
new_element[0][0] = 1
for pos in element:
new_element[0][pos+1] = int(1)
result.extend(new_element)
print(result) # [[0, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 0, 0, 0], [1, 0, 0, 0, 1, 0, 0], [1, 0, 0, 0, 0, 0, 1], [1, 0, 0, 0, 1, 0, 1]]
Use itertools.permutations, and just prepend a 1 to each of them.
from itertools import permutations
def augment(xs):
yield [0] + [0 for _ in xs]
for x in permutations(xs):
yield [1] + list(x)
out = list(augment([1,0,1])
If you'd rather write a single expression rather than a generator function, its just
from itertools import chain, permutations
xs = [1, 0, 1]
out = list(chain([[0] + [0 for _ in xs]], ([1] + list(x) for x in permutations(xs))))
Using itertools.product and a generator:
def get_combinations(lst):
yield [0]*(len(lst)+1)
idxs = [idx for idx, x in enumerate(lst) if x]
for vals in product(*[[0, 1]]*2):
vals_i = iter(vals)
yield [1] + [0 if idx not in idxs else next(vals_i) for idx in range(len(lst))]
Then list(get_combinations([0, 0, 0, 1, 0, 1])) prints
[[0, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 0],
[1, 0, 0, 0, 0, 0, 1],
[1, 0, 0, 0, 1, 0, 0],
[1, 0, 0, 0, 1, 0, 1]]

How to construct matrix based on condition and position?

I have a matrix A=
np.matrix([[0, 0, 0, 0, 0],
[0, 0, 0, 1, 1],
[0, 0, 1, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 1, 1, 1]]
I wanna build a matrix B where B[i,j]=5 if A[i,j]=1 and (i+1)%3=0; B[i,j]=0 otherwise.
The B should be: B=
np.matrix([[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 5, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 5, 0, 0]]
Is there any possible method to achieve this without using for loop, just like matrix calculation? Thank you.
UPDATED ANSWER:
I have not thought of a way to eliminate the for-loop in the list comprehension for filtering on the remainder condition, but the "heavy" part of the computation exploits numpy's optimizations.
import numpy as np
newdata = 5 * np.array([(i + 1) % 3 == 0 for i in range(data.shape[-1])]) * np.array(data)
ORIGINAL ANSWER (prior to condition that for-loops cannot be used):
Assuming your matrix is stored as data, then you can use list comprehension syntax to get what you want.
newdata = [[5 if val == 1 and (idx + 1) % 3 == 0 else 0
for idx, val in enumerate(row)]
for row in data]

Multiplying a list by a number creates items have relation with the original one? [duplicate]

This question already has answers here:
List of lists changes reflected across sublists unexpectedly
(17 answers)
Closed 9 years ago.
I have a list of List say mysolution:
>>>mySolution
[[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
>>> mySolution[0][0] = 1
>>> mySolution
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
Intended output:
[[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
why is it that all the 1st elements in my list of list's is being changed to 1?
I would only like to change the first element of the first list to 1.
What matters is how you created your original mysolution list. As it seems, it contains four times the same list which is why changing it once will make it change in all four locations.
To initialize independent zero-filled lists like that, you can do the following:
mysolution = [[0] * 4 for i in range(4)]
It's quite possible that you created the list like this:
mySolution = [0]*4
mySolution = [mySolution]*4
Or equivalently:
mySolution = [[0]*4]*4
Either of the above snippets will create a list with four sublists which are copies of the exact, same sublist, so any modification on one sublist will be reflected on the others - they're one and the same. The solution is to create four different sublists:
mySolution = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
Or a bit shorter:
mySolution = [[0]*4 for _ in xrange(4)]
Because all the contained lists are actually the same list. When you do:
l = [0, 0, 0, 0]
my_solution = [l, l, l]
Then, my_solution[0], my_solution[1], and my_solution[2] are references to the same object (l).
If you modify the list in one location, it changes everywhere. That is because lists are mutable objects.
Instead, use multiple lists:
l1 = [0, 0, 0, 0]
l2 = [0, 0, 0, 0]
l3 = [0, 0, 0, 0]
my_solution = [l1, l2, l3]
Which will work as intended.
please note that this is doing fine:
mySolution = [[0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
mySolution[0][0] = 1
print mySolution
>>>
[[1, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 0, 0, 0]]
it all depends on how you initialized your solution. this
mySolution = [[0, 0, 0, 0]]*4
mySolution[0][0] = 1
print mySolution
gives
>>>
[[1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0], [1, 0, 0, 0]]
>>>
because here each array [0, 0, 0, 0] in mySolution is a copy of initialization array [0, 0, 0, 0] in [[0, 0, 0, 0]]*4. if you change first element of first array, copy of it also change.
with this initialization mySolution = [[0, 0, 0, 0] for x in range(4)] you are not copying the array but appending [0,0,0,0] four times, giving the result that you are expecting.

Insert newline print statement into (nested)? for loop?

I'm trying to print a matrix with user assigned variable for the length and width, but have used manual assignment for easier reading. Right now my output doesn't include any new lines, but that is what I'm attempting to do.
def matrix(rows,cols):
grid = [[0 for i in range(cols)] for i in range(rows)]
return grid
rows = 5
cols = 5
print(matrix(rows,cols))
Is it possible to insert a print("\n") statement into the for statement to properly print out the matrix. Currently the output is as follows:
[[0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0], [0, 0, 0, 0, 0]]
Desired output:
[[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0],
[0, 0, 0, 0, 0]]
That happens to be the exact behaviour of pprint.
from pprint import pprint
def matrix(rows,cols):
grid = [[0 for i in range(cols)] for i in range(rows)]
return grid
rows = 5
cols = 5
pprint(matrix(rows,cols))
pprint doing what you need is nice, but shouldn't you be using a class for your matrix type? Using a naked list of lists may bite you later.

Categories