Cannot append 2D array

Question:

I’m trying to create an eight-puzzle game solver, and I have a little problem. My states are being stored as grids(represented by 2D- lists). I am trying to keep track of every resulting state by appending to a succ_states list whenever a move is made by the computer. However, my succ_states 2D array only shows the current state and erases previous states in the list.

Here’s my code snippet for the downward move:

def actions(self, state):
    actions = []
    succ_states = []
    print()
    rows = [row for row in state]
    for row in rows:
        for i in row:
            # D
            if i == 0 and state.index(row) != 2:
                print(row, "down action, finally!")
                print("Index of i = ", row.index(i))
                new_row = rows[state.index(row) + 1]
                zero = i
                zero_index = row.index(zero)
                row[zero_index] = new_row[zero_index]
                new_row[zero_index] = zero
                actions.append("D")
                succ_states.append(rows)
    return actions, succ_states

Using the initial state [[1, 3, 0], [6, 7, 8], [4, 2, 5]], actions returns [[[8, 7, 3], [5, 4, 6], [2, 1, 0]], [[8, 7, 3], [5, 4, 6], [2, 1, 0]]]. I don’t get why it removes the first resulting state and appends the second state twice. I tried changing the position of the append statements and even tried to extend, but nothing is working.

Asked By: anonS

||

Answers:

You are appending rows, but this appends a reference to the list, not a copy. This means that when you later modify rows (or one of the items in row, which are lists in themselves), you modify the contents of succ_states as well.

The fix is to append a copy of rows. And, in this case that rows is a list of lists, then you need to use deepcopy.

I believe this will implement the behavior you seek:

import copy
def actions(self,state):
    actions = []
    succ_states = []
    print()
    rows = [row for row in state]
    for row in rows:
        for i in row:
            # D
            if i == 0 and state.index(row) != 2:
                print(row, "down action, finally!")
                print("Index of i = ", row.index(i))
                new_row = rows[state.index(row) + 1]
                zero = i
                zero_index = row.index(zero)
                row[zero_index] = new_row[zero_index]
                new_row[zero_index] = zero
                actions.append("D")
                succ_states.append(copy.deepcopy(rows))
    return actions, succ_states
Answered By: jokogarcia