0
def helper(mat):
    for row in mat:
        zero_list = []
        for subrow in row:
            if subrow == 0:
                row.remove(0)
                zero_list.append(0)
        row.extend(zero_list)
    return mat


def merge_left(mat):
    result = mat.copy()
    helper(mat)
    counter = 0 
    for i in range(len(mat)):
        current_tile = 0
        for j in range(len(mat)):
            if mat[i][j] == current_tile:
                mat[i][j-1] *= 2
                mat[i][j] = 0
                counter += mat[i][j-1]
            current_tile = mat[i][j]
    helper(mat)
    return result == mat

print(merge_left([[2, 2, 0, 2], [4, 0, 0, 0], [4, 8, 0, 4], [0, 0, 0, 2]]))

Hey guys,

The result I get for merge_left in the above code is True for the test case. Given that result is a duplicate copy of mat. How is it so that result has also been altered in a similar way to mat through this code? I'd understand this to be the case if I had written

result = mat instead of result = mat.copy()

Why is this the case? I'm aiming to compare the two states of the input mat. Before the code alters mat and after it does.

  • Does this answer your question? [Copying nested lists in Python](https://stackoverflow.com/questions/2541865/copying-nested-lists-in-python) – ggorlen Mar 21 '20 at 04:17

1 Answers1

0

list.copy() only clones the outer list. The inner lists are still aliases, so modifying one of them modifies result and mat. Here's a minimal reproduction of the problem:

>>> x = [[1, 2]]
>>> y = x.copy()
>>> y[0][0] += 1
>>> y
[[2, 2]]
>>> x
[[2, 2]]

You can use [row[:] for row in mat] to deep copy each row within the matrix. Slicing and copy are pretty much the same.

You can also use copy.deepcopy, but it's overkill for this.

Also, row.remove(0) while iterating over row, as with iterating over any list while adding or removing elements from it, is very likely a bug. Consider a redesign or use for subrow in row[:]: at minimum.

ggorlen
  • 44,755
  • 7
  • 76
  • 106