1

I am trying to make it so the object X is the background and A is an object to be moved up or down, but once i use loop to change the A to X, the loop finds the a in the next line and does it once again, how do i make it so it only changes once and moves on?

newlist = ['X','X','A','X','X','X','X']

for i in range(len(newlist)):

    print(newlist[i])

    if newlist[i] == 'A':

        newlist[i] = 'X'

        newlist[i+1] = 'A'

It should show

X
X
X
A
X
X
X

from

X
X
A
X
X
X
X

but right now it shows

X
X
X
A
A
A
A
3
  • 1
    What's the output for newlist = ['X','X','X','X','X','X','A'] Commented Jul 28, 2019 at 15:39
  • This seems like an XY problem. I mean, if the only thing important about 'A' is its position, why not scrap the list and use an int to represent its position? Commented Jul 28, 2019 at 15:41
  • That output's not right. I just ran the code and got 2 X's and 5 A's, then an IndexError. Commented Jul 28, 2019 at 15:47

5 Answers 5

1

While doing the downshift as well (just for myself) I found an even better approach than in my previous answer:

deque adds rotation functionality to iterables.

from collections import deque

newlist = ['X', 'X', 'A', 'X', 'A', 'X', 'A']
print(f'Original:\n{newlist}')  # debug

a = deque(newlist)
b = deque(newlist)

a.rotate(1)
newlist = list(a)
print(f'Shift up:\n{newlist}')

b.rotate(-1)
newlist = list(b)
print(f'Shift down:\n{newlist}')

Result:

Original:
['X', 'X', 'A', 'X', 'A', 'X', 'A']
Shift up:
['A', 'X', 'X', 'A', 'X', 'A', 'X']
Shift down:
['X', 'A', 'X', 'A', 'X', 'A', 'X']
Sign up to request clarification or add additional context in comments.

1 Comment

Good choice. deque does this efficiently by using dynamic index windows of some sort.
0

The code is self-explanatory. There is an if case to check the existence of [index+1]

list = ['X','X','A','X','X','X','X']

try:
    for el in list:
        print(list)
        if el == 'A':
            index = list.index(el)
            if list[index+1]:
                list[index+1] = el 
            list[index] = 'X'
except:
    print('Out of index!!')

Result:

C:\Desktop>python test.py
['X', 'X', 'A', 'X', 'X', 'X', 'X']
['X', 'X', 'A', 'X', 'X', 'X', 'X']
['X', 'X', 'A', 'X', 'X', 'X', 'X']
['X', 'X', 'X', 'A', 'X', 'X', 'X']
['X', 'X', 'X', 'X', 'A', 'X', 'X']
['X', 'X', 'X', 'X', 'X', 'A', 'X']
['X', 'X', 'X', 'X', 'X', 'X', 'A']
Out of index!!

1 Comment

Never name a variable using list which is a built in type. Also, instead of calling .index - use for i, el in enumerate(ls)
0

just use the command break after doing the change:

newlist = ['X','X','A','X','X','X','X']

for i in range(len(newlist)):

    if newlist[i] == 'A':

        newlist[i] = 'X'

        newlist[i+1] = 'A'

        break
print " ". join(newlist)

or with continue:

newlist = ['X','X','A','X','X','X','X']
k = -1
for i in range(len(newlist)):

    if k == i:
        continue

    if newlist[i] == 'A':

        newlist[i] = 'X'

        newlist[i+1] = 'A'

        k = i+1
print " ". join(newlist)

2 Comments

What if newlist = ['X','X','A','X','A','X','X']?
then use the command continue instead for the next value.
0

With itertools.islice and next() you can manipulate the iterable.
Kudos to my source: How do I skip a few iterations in a for loop.

Also handled an 'A' at the very end and works with several 'A' in the list.

from itertools import islice

newlist = ['X', 'X', 'A', 'X', 'A', 'X', 'A']
print(newlist)  # debug

numbers = iter(range(len(newlist)))

for i in numbers:
    if newlist[i] == 'X':
        print(newlist[i])

    if newlist[i] == 'A':
        newlist[i] = 'X'
        print(newlist[i])
        if i < len(newlist) - 2:
            newlist[i+1] = 'A'
            print(newlist[i+1])
        next(islice(numbers, 1, 1), None)

print(newlist)  # debug

Result:

['X', 'X', 'A', 'X', 'A', 'X', 'A']
X
X
X
A
X
A
X
['X', 'X', 'X', 'A', 'X', 'A', 'X']

Comments

0

In mixing the state output and state change operations, you've presented only one item of the list for each row. This is akin to using a super high frame rate without vertical blank synchronisation. Every row shows only a fraction of the whole picture, in this case the moment when the A appears in every position from its origin down. You could easily visualise this by printing newlist instead of newlist[i].

The operation to move the A has several issues in itself. It's in a loop that we could assume is meant to find the A, but that's more efficiently done with the index method. More significantly, once found, you keep looping and therefore will continue moving the A until it hits the end - in this case with an IndexError, as there will be no newlist[i+1] entry to swap with. The traditional way to ensure the task is done once is to break out of a search loop. Another solution may be to never alter the list you're iterating over, but create a new generation derived from it; then you'll never read a newly modified position.

Yet another approach here works on the basis that X is the background and all As move in the same direction, including off the end of the list:

newstate = ['X']+oldstate[:-1]    # Shift to higher indices

And here is one where As move only if they can, based on a rule table:

moves = {('X', 'A', 'X'): 'X',  # Moved off to the right
         ('A', 'A', 'X'): 'X',  # Moved off to the right
         ('A', 'X', 'X'): 'A',  # Moved in from the left
         ('A', 'X', 'A'): 'A',  # Moved in from the left
        }
newstate = [moves.get((l,h,r), h) for (l,h,r) in 
            zip(['X']+oldstate, oldstate, oldstate[1:]+['A'])]

This uses an X as the left boundary and A as the right boundary to avoid As walking off the edges. It might be useful to define another cell state to represent a wall. On that note, this is an example of a cellular automaton.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.