titi157 titi157 -4 years ago 215
Python Question

Shift and merge elements of a matrix


How can I shift and merge elements of a matrix to have the following result ?


Move right:
[[0,0,2,2,0,2],[8,4,2,2,0,2]]
==>
[[0,0,0,0,4,2],[0,0,8,4,4,2]]


or

Move left:
[[0,0,2,2,0,2],[8,4,2,2,0,2]]
==>
[[4,2,0,0,0,0],[8,4,4,2,0,0]]



It's like the 2048 game. For example, when the user do a left move, every numbers go to the left of the list and if 2 numbers side-by-side are equals, tere is an addition of the two numbers.


I would like to do it with loops.

I tried with some codes that I have found on the internet but as a begineer, I didn't found a straightforward code to understand how to do this.

Thanks in advance for the help.

Answer Source

Here is an example for moving the elements to the right:

def move_right(matrix):
    for row in matrix:
        for i, number in enumerate(row):
            if number == row[i-1]:
                row[i] = number + row[i-1]
                row[i-1] = 0
        row.sort(key=lambda v: v != 0)

    return matrix

Then doing:

matrix = [[0,0,2,2,0,2],[8,4,2,2,0,2]]
print(move_right(matrix))

Outputs:

[[0, 0, 0, 0, 4, 2], [0, 0, 8, 4, 4, 2]]

How it works:

  1. First we loop through the matrix. During the first iteration: row = [0, 0, 2, 2, 0, 2]
  2. Then we check loop over the numbers in that row using the enumerate() function. For the current row, this will output a result as so:

    i number 0 0 1 0 2 2 3 2 4 0 5 2

  3. Then we use the index (i) to refer to the previous number in the list. e.g. At index 3. The current number is 2, and the previous number (i-1) was 2. Since these are equal the code within the 'if' statement will execute.

  4. The current element will then be assigned to the sum of itself and the previous element. row[i] = number + row[i-1]

  5. The previous number will become 0, at it merged with the current number. row[i-1] = 0

  6. Once we have looped over every number, the row will be: [0, 0, 0, 4, 0, 2]. The code row.sort(key=lambda v: v != 0) will then sort so that the zeroes are pushed to the left. See here for more details. When moving elements to the left instead of the right, this would need to be changed to row.sort(key=lambda v: v != 0, reverse=True) to push the zeros in the other direction.

Recommended from our users: Dynamic Network Monitoring from WhatsUp Gold from IPSwitch. Free Download