0

I am relatively new to python as a language and am having some difficulty with the pop() function.

I have a very large 3D python list. It is storing data about possible permutations. I am systematically removing permutations within this list that are invalid. To do this I am using python pop as shown below:

    for k in range(0, len(invalid)):
        index = len(invalid) - k - 1
        possibilitiesRows[i].pop(invalid[index])

The issue with this is it is removing all values at the index invalid[index]. For example, if the list looked like:

   [[['-', '-', '-'], ['-', '-', 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], ['-', 1, '-'], ['-', 1, 1], [1, '-', '-'], [1, '-', 1], [1, 1, '-'], [1, 1, 1]]]

It is a list of dimension, 3,7,3. When I am calling the above pop for i = 0 and invalid[index] = 6 it removes the fourth element in all three of the lists, despite the specification of i = 0. So in this example, it returns:

    [[['-', '-', '-'], ['-', '-', 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, '-', '-'], [1, '-', 1], [1, 1, 1]]]

I have tried a lot of things to fix this, including different ways of assigning the list and updating my python to a newer version. I am running python 2.7.16, but it also doesn't work in python 3.7.3. Any help here would be greatly appreciated.

The full program can be found below if you would like some more context. Note it is very long and some of the indices used in the for loops aren't the most intelligent, just because my text editor doesn't display j's in a particularly clear way.

import math
import time

input_file = open("pic3.txt", "r")

gridSize = int(input_file.readline())

rows = []
cols = []

grid = []
for i in range(0,gridSize):
    grid.append([])
    for j in range(0,gridSize):
        grid[i].append("u")

for i in range(0,gridSize):
    rows.append(list(map(int, input_file.readline().split())))

for i in range(0,gridSize):
    cols.append(list(map(int, input_file.readline().split())))

unSolved = True

def toBin(a):
    ans = ["0"] * gridSize
    num = a
    digit = gridSize
    while True:
        digit -= 1
        if num >= 2 ** digit:
            num -= 2 ** digit
            ans[gridSize - 1 - digit] = "1"
        if num == 0:
            break
    return "".join(ans)

possibilitiesCols = []
possibilitiesRows = []
possibilityRow = []
for k in range(0,2 ** gridSize):
    bin = toBin(k)
    possibility = []
    for m in range(0,gridSize):
        if bin[m] == "1":
            possibility.append(1)
        else:
            possibility.append("-")
    possibilityRow.append(possibility)

for i in range(0,gridSize):
    possibilitiesCols.append(possibilityRow)
    possibilitiesRows.append(possibilityRow)

print("")
iterations = 0
startTime = time.time()

timeTaken = 0.0

queueRows = []
queueCols = []
for i in range(0,gridSize):
    queueRows.append(i)
    queueCols.append(i)

print(possibilitiesRows)
while unSolved:
    timeTaken = (time.time() - startTime) - timeTaken
    print("iteration",iterations,"completed in", math.floor(10*timeTaken)/10,"seconds")
    print("iteration",iterations,"completed after", (math.floor(10*(time.time() - startTime)))/10,"seconds")
    if iterations > 15:
        print("breaking")
        break
    unSolved = False
    iterations += 1

    done = []
    for hca in range(0, len(queueRows)): #looping through every row
        i = queueRows[hca]
        row = grid[i]
        if "u" in row:
            unSolved = True

        invalid = []
        for k in range(0, len(possibilitiesRows[i])):
            begun = False
            next = False
            block = 0
            currentBlock = 0
            valid = True
            for m in range(0, gridSize):
                if begun:
                    if possibilitiesRows[i][k][m] == 1:
                        block += 1
                    elif block != rows[i][currentBlock]:
                        valid = False
                        break
                    if block == rows[i][currentBlock]:
                        begun = False
                        if possibilitiesRows[i][k][m] == 1:
                            next = True
                        if currentBlock + 1 != len(rows[i]):
                            currentBlock += 1
                            block = 0
                        else:
                            for p in range(m + 1, gridSize):
                                if possibilitiesRows[i][k][p] != "-":
                                    valid = False
                                    break
                            break
                else:
                    if possibilitiesRows[i][k][m] == 1:
                        block = 1
                        begun = True
                        if next:
                            valid = False
                            break
                    else:
                        next = False
            if (block != rows[i][-1] or currentBlock + 1 != len(rows[i])) and valid:
                valid = False

            if valid == False:
                invalid.append(k)

        for k in range(0, len(invalid)):
            index = len(invalid) - k - 1
            possibilitiesRows[i].pop(invalid[index])

        invalid = []
        for k in range(0, len(possibilitiesRows[i])):
            for m in range(0,gridSize):
                if str(possibilitiesRows[i][k][m]) != str(row[m]) and row[m] != "u":
                    invalid.append(k)
                    break

        for k in range(0, len(invalid)):
            index = len(invalid) - k - 1
            possibilitiesRows[i].pop(invalid[index])


        known = possibilitiesRows[i][0]
        for k in range(1,len(possibilitiesRows[i])):
            for m in range(0, gridSize):
                if possibilitiesRows[i][k][m] != known[m]:
                    known[m] = "u"
        for k in range(0,gridSize):
            if known[k] == "u":
                known[k] = row[k]
        grid[i] = known
        row = known

        grid[i] = row

        if "u" in row:
            adh = True
        else:
            done.append(i)

    for i in range(0,len(done)):
        possibilitiesRows.pop(queueRows.index(done[i]))
        queueRows.pop(queueRows.index(done[i]))
#----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    done = []
    for hda in range(0, len(queueCols)): #looping through every column
        i = queueCols[hda]
        col = [0] * gridSize
        for j in range(0, gridSize):
            col[j] = grid[j][i]

        possibilities = []
        for k in range(0,2 ** gridSize):
            bin = toBin(k)
            possibility = []
            for m in range(0,gridSize):
                if bin[m] == "1":
                    possibility.append(1)
                else:
                    possibility.append("-")
            possibilities.append(possibility)

        invalid = []
        for k in range(0, 2 ** gridSize):
            begun = False
            next = False
            block = 0
            currentBlock = 0
            valid = True
            for m in range(0, gridSize):
                if begun:
                    if possibilities[k][m] == 1:
                        block += 1
                    elif block != cols[i][currentBlock]:
                        valid = False
                        break
                    if block == cols[i][currentBlock]:
                        begun = False
                        if possibilities[k][m] == 1:
                            next = True
                        if currentBlock + 1 != len(cols[i]):
                            currentBlock += 1
                            block = 0
                        else:
                            for p in range(m + 1, gridSize):
                                if possibilities[k][p] != "-":
                                    valid = False
                                    break
                            break
                else:
                    if possibilities[k][m] == 1:
                        block = 1
                        begun = True
                        if next:
                            valid = False
                            break
                    else:
                        next = False

            if (block != cols[i][-1] or currentBlock + 1 != len(cols[i])) and valid:
                valid = False

            if valid == False:
                invalid.append(k)

        for k in range(0, len(invalid)):
            index = len(invalid) - k - 1
            possibilities.pop(invalid[index])

        invalid = []
        for k in range(0, len(possibilities)):
            for m in range(0,gridSize):
                if str(possibilities[k][m]) != str(col[m]) and col[m] != "u":
                    invalid.append(k)
                    break

        for k in range(0, len(invalid)):
            index = len(invalid) - k - 1
            possibilities.pop(invalid[index])

        known = possibilities[0]
        for k in range(1,len(possibilities)):
            for m in range(0, gridSize):
                if possibilities[k][m] != known[m]:
                    known[m] = "u"


        for k in range(0,gridSize):
            if known[k] == 'u':
                known[k] = col[k]

        for k in range(0,gridSize):
            grid[k][i] = known[k]
        col = known

        for k in range(0,gridSize):
            grid[k][i] = col[k]

        if "u" in col:
            adh = True
        else:
            done.append(i)

for i in range(0,len(done)):
    queueCols.pop(queueCols.index(done[i]))

for i in range(0,gridSize):
    for j in range(0,gridSize):
        grid[i][j] = str(grid[i][j])
    print("".join(grid[i]))

print("")
if unSolved:
    print("Solved after",iterations,"iterations")
else:
    print("Solved after",iterations -1,"iterations")

1 Answers1

2

Your grid is holding multiple references to the very same list object. The simplest fix is to use shallow copies when filling your initial grid:

for i in range(0, gridSize):
    possibilitiesCols.append(possibilityRow[:])
    possibilitiesRows.append(possibilityRow[:])
user2390182
  • 72,016
  • 6
  • 67
  • 89