I was trying to create a code for a identity matrix and came out with this code:
def identidade(n):
i =0
l = [0] * n
l1 = [l.copy()] *n
for i in range (n):
l1[i][i] = 1
print(l1)
return l1
the output is:
[[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1],
[1, 1, 1, 1, 1]]
But i came along with a very similar code in the internet:
def identity(n):
m=[[0 for x in range(n)] for y in range(n)]
for i in range(0,n):
m[i][i] = 1
return m
that returns:
[[1, 0, 0, 0, 0],
[0, 1, 0, 0, 0],
[0, 0, 1, 0, 0],
[0, 0, 0, 1, 0],
[0, 0, 0, 0, 1]]
So, my question is why my code doesn't return the correct output when selecting the element in the list of lists (l1[i][i] = 1) ?
tks in advance
The actual problem here is that you are using the * operator to create (as you hope) the copies of the '[l.copy()]' list, but it actually creates references. Using the copy() inside of the square brackets just breaks the connection to the original 'l' list, but does not solve the problem with creation of references to the newly created copy.
Just try to replace the * operator with for loop - this will solve your problem.
Related
Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
This post was edited and submitted for review 1 year ago and failed to reopen the post:
Original close reason(s) were not resolved
Improve this question
Given some m by n grid of 1's and 0's, how would you find how much water would be captured by it, where the 1's are 'walls', and 0's are empty space?
Examples:
[1, 1, 1, 1, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 1, 1, 1, 1]
This grid would capture 9 units of water.
[1, 1, 1, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 1, 1, 1, 1]
However, because this grid has a 'leak' in one of its walls, this would capture 0 units of water.
[1, 1, 1, 0, 1],
[1, 0, 1, 0, 1],
[1, 0, 1, 0, 1],
[1, 0, 1, 0, 1],
[1, 1, 1, 1, 1]
Likewise, because there is a partition between the two sections, the leaky one does not affect the other, and as such this grid would capture 3 units of water.
I'm just really uncertain of how to start on this problem. Are there any algorithms that would be helpful for this? I was thinking depth-first-search or some sort of flood-fill, but now I'm not sure if those are applicable to this exercise.
You can create a list of leaks starting from the positions of 0s on the edges. Then expand that list with 0s that are next to the leaking positions (until no more leaks can be added). Finally, subtract the number of leaks from the total number of zeros in the grid.
def water(G):
rows = len(G)
cols = len(G[0])
# initial leaks are 0s on edges
leaks = [ (r,c) for r in range(rows) for c in range(cols)
if G[r][c]==0 and (r==0 or c==0 or r==rows-1 or c==cols-1) ]
for r,c in leaks:
for dr,dc in [(-1,0),(1,0),(0,-1),(0,1)]: # offsets of neighbours
nr,nc = r+dr, c+dc # coordinates of a neighbour
if nr not in range(rows): continue # out of bounds
if nc not in range(cols): continue # out of bounds
if G[nr][nc] != 0: continue # Wall
if (nr,nc) in leaks: continue # already known
leaks.append((nr,nc)) # add new leak
return sum( row.count(0) for row in G) - len(leaks)
Output:
grid = [[1, 1, 1, 1, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 1, 1, 1, 1]]
print(water(grid)) # 9
grid = [[1, 1, 1, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 0, 0, 0, 1],
[1, 1, 1, 1, 1]]
print(water(grid)) # 0
grid = [[1, 1, 1, 0, 1],
[1, 0, 1, 0, 1],
[1, 0, 1, 0, 1],
[1, 0, 1, 0, 1],
[1, 1, 1, 1, 1]]
print(water(grid)) # 3
Note that this only looks for leaks in horizontal and vertical (but not diagonal) directions. To manage leaking through diagonals, you'll need to add (-1,-1),(-1,1),(1,-1),(1,1) to the list of offsets.
Removing zeros starting at the edges, representing the coordinates of zeros with a set (for fast lookup) of complex numbers (for easy neighbor calculation):
def water(G):
m, n = len(G), len(G[0])
zeros = {complex(i, j)
for i in range(m) for j in range(n)
if G[i][j] == 0}
for z in list(zeros):
if z.real in (0, m-1) or z.imag in (0, n-1):
q = [z]
for z in q:
if z in zeros:
zeros.remove(z)
for a in range(4):
q.append(z + 1j**a)
return len(zeros)
Or with Alain's style of a single BFS, initializing the queue with all edge zeros:
def water(G):
m, n = len(G), len(G[0])
zeros = {complex(i, j)
for i in range(m) for j in range(n)
if G[i][j] == 0}
q = [z for z in zeros
if z.real in (0, m-1) or z.imag in (0, n-1)]
for z in q:
if z in zeros:
zeros.remove(z)
for a in range(4):
q.append(z + 1j**a)
return len(zeros)
I'm following this link to write a DP solution for Subset problem.
def subsetSum(input, target):
row, col = len(input)+1, target+1
db = [[False] * col] * row
for i in range(row):
db[i][0] = True
for i in range(1, row):
for j in range(1, col):
db[i][j]=db[i-1][j]
if db[i][j]==False and j>=input[i-1]:
db[i][j] = db[i-1][j-input[i-1]]
return db[i][j]
target = 5
input = [1,3,9,2]
subsetSum(input, target)
Interestingly after every iteration of "j", db[i-1] (the previous row where we are referring to the values) is also getting updated. I'm really lost whats happening here. Please suggest.
Please find this link for the printed statements.
The issue is in this line
db = [[False] * col] * row.
When you use the * operator, a copy of the original list is made that refers to the original list.
Consider the following example:
l = [[1]*5]*3
print(l) # prints [[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]]
l[0][0] = 0
print(l) # prints [[0, 1, 1, 1, 1], [0, 1, 1, 1, 1], [0, 1, 1, 1, 1]]
Each inner list refers to the same object. Thus, when the first element of the first list is changed, all lists appear to change.
To remedy this, you can use a list comprehension:
l = [[1]*5 for _ in range(3)]
print(l) # prints [[1, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]]
l[0][0] = 0
print(l) # prints [[0, 1, 1, 1, 1], [1, 1, 1, 1, 1], [1, 1, 1, 1, 1]]
Specifically, you can replace your assignment to db with the following:
db = [[False]*col for _ in range(row)].
This is my code:
def string2bin(s):
y = []
for x in s:
q = []
q.append(str(bin(ord(x))[2:].zfill(8)))
y.append(q)
return y
It is supposed to output:
string2bin('abc')
[[0, 1, 1, 0, 0, 0, 0, 1], [0, 1, 1, 0, 0, 0, 1, 0],
[0, 1, 1, 0, 0, 0, 1, 1]]
But instead outputs:
string2bin('abc')
[['01100001'], ['01100010'], ['01100011']]
Also how do you segment a string?
Thanks for any help!
Convert the string to a list of digits.
def string2bin(s):
y = []
for x in s:
q = [int(c) for c in (str(bin(ord(x))[2:].fill(8)))]
y.append(q)
return y
Probably the easiest edit to your code would be to simply change the append from string to list. As you are adding it to a list as a string, because the way ord works you are simply adding the string as a whole, not as individual values.
def string2bin(s):
y = []
for x in s:
q = []
q.append(list(bin(ord(x))[2:].zfill(8)))
y.append(q)
return y
Try this:
def string2bin(s):
return [list(map(int, str(bin(ord(x)))[2:].zfill(8))) for x in s]
print(string2bin('abc'))
It produces (up to indentation):
[[0, 1, 1, 0, 0, 0, 0, 1],
[0, 1, 1, 0, 0, 0, 1, 0],
[0, 1, 1, 0, 0, 0, 1, 1]]
You just missed the map(int, ...) and list(...) part.
So you're taking 1 char at a time out of the string then converting it to bin, removing the 0b and then filling in the rest with 0's to keep the length at 8.
The issue is this in turn gives you a string to append, not an array.
Here's my solution, not the most Pythonic but it's easy to read:
def string2bin(s):
y = []
for x in s:
q = []
adjusted = list(str(bin(ord(x)))[2:].zfill(8))
for num in adjusted:
q.append(int(num))
y.append(q)
return y
print(string2bin('abc'))
This outputs exactly what you've requested:
[[0, 1, 1, 0, 0, 0, 0, 1], [0, 1, 1, 0, 0, 0, 1, 0], [0, 1, 1, 0, 0, 0, 1, 1]]
I'm working on a problem that requires developing code for a context model:
P(A|x)=∑a∈A𝕊(x,a)/∑a∈A𝕊(x,a)+∑b∈B𝕊(x,b)
which calculates the probability of that a novel stimulus x belongs to the category A. The S is a similarity function I defined earlier as:
def calculate_similarity(x, y, theta=0.1):
return (np.prod([1 if x[i] == y[i] else theta for i in range(len(x))]))
The function takes in the test stimuli, exemplars, exemplar names and theta and wants us to return an array of the probabilities that each stimulus belongs to A.
def context_model(test_stimuli, exemplars, exemplar_categories, theta=0.1):
I know that I should be iterating over every test stimuli and calculating the similarity between it and the exemplars- I can even do this by the exemplar category name "A" and "B", but when I run my code I get and index error.
result = []
a_data = np.argwhere(exemplar_categories == 'A')
b_data = np.argwhere(exemplar_categories == 'B')
for x in test_stimuli:
a = [calculate_similarity(x, exemplars[i, :], theta) for a_data[i] in range(0, len(a_data))]
b = [calculate_similarity(x, exemplars[i, :], theta) for b_data[i] in range(0, len(b_data))]
final = sum(a)/ (sum(a) + sum(b))
result = np.append(result, final)
return result
When I run,
stimuli = np.array([
[1, 1, 1, 1, 0],
[0, 0, 1, 1, 0],
[1, 0, 0, 1, 1],
[1, 1, 0, 1, 1]])
exemplars = np.array([
[0, 0, 1, 0, 1],
[0, 1, 1, 1, 0],
[1, 0, 0, 0, 1],
[0, 0, 1, 1, 1],
[0, 0, 1, 0, 0],
[1, 0, 0, 1, 1]])
exemplar_categories = np.array(['B', 'A', 'B', 'B', 'B', 'A'])
context_model(stimuli, exemplars, exemplar_categories, theta=0.1)
I get the statement "index 2 is out of bounds for axis 0 with size 2
I've been working on this problem for days and don't know where to go from here. I've tried applying the function to every X in the stimuli and then parsing out the A and B data, but nothing is working.
Any help would be greatly appreciated!! I'm still new to coding and this problem is driving me crazy.
Having a bit of writing out the code.
For example, if I have an array of:
a = ([0, 0, 1, 2], [0, 1, 1, 0], [0, 0, 1, 0], [1, 0, 1, 3], [0, 1, 1, 3])
if I want to add first element of each item,
as in to return a list of 0 + 0 + 0 + 1 + 0, 0 + 1 + 0, 0 + 0 ...
I wrote the code:
def test(lst):
sum = 0
test_lst = []
i = 0
while i in range(0, 4):
for j in range(0, len(lst)):
sum += lst[j][i]
test_lst.append(sum)
i += 1
return test_lst
I get index size error.
How can I go about this?
sum(zip(*a)[0])
zip is a function that takes any number of n-length sequences and returns n tuples (among other things). The first of these tuples has the elements that came first in the tuples passed to zip. sum adds them together.
EDIT:
In Python 3, the above doesn't work. Use:
sum(next(zip(*a)))
instead. For all such sums,
map(sum, zip(*a))
a = ([0, 0, 1, 2], [0, 1, 1, 0], [0, 0, 1, 0], [1, 0, 1, 3], [0, 1, 1, 3])
Try using list comprehensions:
sum([item[0] for item in a])
The line above takes the first element of each list in the tuple, then puts it into a temporary list. We then call sum on that temporary list, which yields the answer.