Search code examples
pythonarraysalgorithmencodingbinary-data

Why is this list changing all of its values since the only time it is modified is through .append()?


I am trying to generate an array of all of the possible binary permutations for a given number of bits by appending a dynamic "instance" of the list of boolean values and iterating the True value at the highest index value through all the positions following it. Its purpose is for encoding all or some of the permutations of a given number of switches into a format which can be bound to a single or pair of base-36 numerals and encoded in a string to be logged as a save file.

When this iterating True reaches the last or 'omega' position, it is switched off and added to the 'omegaStack'; also the True value with the highest index value in 'instance' is moved up one position. If there are any values in the stack, an enumerate method is called on the instance to find the highest index position of a True value in the 'instance'.

If there are no True values for the omegaStack to populate in front of, it should empty into the alphaStack with an additional True to populate the instance from the [0] position upwards and start iterating the True in the highest index position in the list again.

If the omegaStack places a True value into the final index position in 'instance', after appending the instance to the array, it searches for any True values which are adjacent and places them all in the stack to be populated again into the highest index position(+1) which reads True from the enumerate(instance).

This should cause a cascading effect of an ever increasing and advancing number of "on" switches throughout a list of a designated size.

like this: with x, o as False, True

makeSwitchTable(4)

should print

[[ x , x , x , x ],
[ o , x , x , x ],
[ x , o , x , x ],
[ x , x , o , x ],
[ x , x , x , o ],
[ o , o , x , x ],
[ o , x , o , x ],
[ o , x , x , o ],
[ x , o , o , x ],
[ x , o , x , o ],
[ x , x , o , o ],
[ o , o , o , x ],
[ o , o , x , o ],
[ o , x , o , o ],
[ x , o , o , o ],
[ o , o , o , o ]]

...is what i should get...

What i get instead is this god awful looping madness with only the very first all false instance being correct. Every other time .append() is called, it changes each list in table[1:] to the same thing it is supposed to add to the end.

I am at a loss. I've never asked a question online about coding before because I have found that a little endurance and research tends to point out my foolishness sufficiently without broadcasting it, but I'm stumped and I don't have a clue how to google this one. I'm aware that my code is likely broken beyond just the appending but as far as my brain can follow the logic, it should be working. Clearly it is not. I also know that the code is not very minimal but if I knew how to distinguish the problem, I would not be asking this question.

This is my code.

def iTrack(instance):
    return [i for i, x in enumerate(instance) if x]


def makeSwitchTable(num):
    table = []
    allOff = [False for x in range(num)]
    end = [True for x in range(num)]
    table.append(allOff)
    instance = [False for x in range(num)]
    instance[0] = True
    table.append(instance)
    alphaStack = []
    iCheck = (iTrack(instance))
    omegaCounter = 0
    omegaStack = []
    print(table)
    for i in range(num):
        
        while omegaCounter < num:
            alphaCheck = len(alphaStack)
            omegaCheck = len(omegaStack)
            if alphaCheck:
                # populate from start
                print(instance, 'alpha')
                for sw in range(alphaCheck):
                    # populate
                    instance[sw] = alphaStack.pop(-1)
                    iCheck = (iTrack(instance))
                table.append(instance)
                if instance == end:
                    # should end the whole shebang if \
                    # the last instance appended == end
                    break
            elif omegaCheck:
                # populate from end
                print(instance, omegaStack, 'omega')
                for sw in range(omegaCheck):
                    # if there are trues left in instance
                    if iCheck:
                        # populate in front of the highest indexed True
                        instance[(iCheck[-1]+1)] = omegaStack.pop(-1)
                        iCheck = (iTrack(instance))
                    else:
                        # add an extra True to iterate
                        omegaCounter += 1
                        omegaStack.append(True)
                        for x in range(len(omegaStack)):
                            # pass omegaStack to alphaStack
                            print(omegaStack)
                            alphaStack.append(omegaStack.pop(-1))
                table.append(instance)
                print(instance, 'there')
                # if populate starts cascade
                if instance[-1]:
                    for sw in range(omegaCounter):
                        print('here')
                        # checks for adjacent Trues from end
                        if instance[-(sw+1)]:
                            # pop to the stack
                            instance[-(sw+1)] = False
                            omegaStack.append(True)
                        else:
                            # ends when no more adjacent to populate again
                            break
                    iCheck = (iTrack(instance))
            else:
                # iterate through last True in instance
                print(iCheck)
                instance[iCheck[-1]+1] = True
                instance[iCheck[-1]] = False
                print(instance, 'move')
                print(table)
                table.append(instance)
                # if it is in the final index position
                if instance[-1]:
                    # if first time through
                    if omegaCounter < 1:
                        omegaCounter += 1
                    # pop True into omegaStack
                    instance[-1] = False
                    omegaStack.append(True)
                    # if there is another True in instance
                    if len(iCheck) > 1:
                        # move it forward one spot
                        instance[iCheck[-2]+1] = True
                        instance[iCheck[-2]] = False
                    iCheck = (iTrack(instance))
                else:
                    iCheck = (iTrack(instance))
                
    print(table)
    
makeSwitchTable(4)

Any help for this amateur would be greatly appreciated. Thank you for your time.


Solution

  • Your table contains lots of references to the same instance. When you keep modifying that instance, it affects all references. Just change all occurrences of the following line:

    table.append(instance)
    

    to

    table.append(instance[:])
    

    which will append shallow copies instead.