2

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.

titi157
  • 157
  • 4
  • 12

2 Answers2

1

If I don't misunderstand your meaning,I write some code,hope this helps:

a = [[0, 0, 2, 2, 0, 2], [8, 4, 2, 2, 0, 2]]
f = lambda x: [2 * x[0]] if x[0] == x[1] else x

def move_left(l):
    c, l = [], l + [0] if len(l) % 2 else l

    for i in range(0, len(l), 2):
        c = c + f(l[i:i + 2])
    c = list(filter(lambda x: x != 0, c))
    return c + ([0] * (len(l) - len(c)))


def move_right(l):
    c, l = [], l + [0] if len(l) % 2 else l

    for i in range(len(l), 0, -2):
        c = f(l[i - 2:i]) + c
    c = list(filter(lambda x: x != 0, c))
    return ([0] * (len(l) - len(c))) + c

for i in a:
    print(move_left(i))

Output:

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

It seems that you're using Python3.x,so you should use list(filter(lambda x: x != 0, c)) to get the list.

McGrady
  • 10,869
  • 13
  • 47
  • 69
0

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

def move_right(matrix):
    for row in matrix:
        for i, number in reversed(list(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. We then apply reversed() to go traverse the list backwards as to not combine a previous sum with another element in a single turn. e.g: [4,4,8] => [0, 8, 8] => [0, 0, 16]. This should actually equal [0, 0, 8] For the current row, this will output a result as so:

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

  3. Then we use the index (i) to refer to the previous number in the list. e.g. At index 2. 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.

Community
  • 1
  • 1
Tom
  • 1,636
  • 2
  • 13
  • 21
  • Your code works well but can yo explain me what the following line of code does ? `row.sort(key=lambda v: v != 0)` – titi157 Mar 23 '17 at 09:53
  • See this link http://stackoverflow.com/questions/23844828/move-all-zeroes-to-the-beginning-of-a-list-in-python. If you still have questions fell free to ask. – Tom Mar 23 '17 at 09:54
  • Is there a way to move all 0 in a matrix to the top or the bottom ? For example : [[0,0,0,0],[0,0,0,0],[1,1,1,1],[0,0,0,0]] would become [[1,1,1,1][0,0,0,0],[0,0,0,0],[0,0,0,0]] or [[0,0,0,0],[0,0,0,0],[0,0,0,0],[1,1,1,1]]. I did it with a loop but I would like to know if there is a built-in fnction to do that. :) – titi157 Mar 29 '17 at 11:55
  • I worked with your function but it appears that there is a problem with it. For example with the following matrix [[0,0,0],[4,4,8],[0,0,0]], it returns me [[0,0,0],[0,0,16], [0,0,0]] instead of [[0,0,0],[0,8,8],[0,0,0]] because the last number of the line gonna be equal to the previous one. How can I fix it ? :) – titi157 Mar 29 '17 at 18:49
  • Nice spot, I updated the code in my answer. Let me know if you have any more issues. – Tom Mar 29 '17 at 21:51