Is there a way to write these ifs nicer?

Question:

I need to write these four ifs in Python. Notice what it does, is changing between four possible states in a loop: 1,0 -> 0,1 -> -1,0 -> 0,-1 and back to first.

if [dx, dy] == [1,0]:
    dx, dy = 0, 1
if [dx, dy] == 0, 1:
    dx, dy = -1, 0
if [dx, dy] == [-1, 0]
    dx, dy = 0, -1
if [dx, dy] == [0, -1]:
    dx, dy = 1, 0

Can anyone suggest me a better/nicer way to write this?

Asked By: manuel

||

Answers:

Magnus’ suggestion is undeniably the right answer to your question as posed, but generally speaking, you want to use a dictionary for problems like this:

statemap = {(1, 0): (0, 1), (0, 1): (-1, 0), (-1, 0): (0, -1), (0, -1): (1, 0)}

dx, dy = statemap[dx, dy]

Even in this case I could argue using a dictionary is better, since it’s clear that there are exactly four states and that they repeat, but it’s hard to resist the sheer beauty of all teh maths.

By the way, the code in your question has a bug in it, and, assuming that the values you test for are the only possible values, is equivalent to:

dx, dy = 1, 0

The bug is that you need elif for the second and subsequent conditions, otherwise you’re continuing to test dx and dy after changing them. If they’re 1 and 0, then all your conditions will be true and they end up the same at the end! If they start out as 0 and 1 then the second and all subsequent conditions will be true, and you again end up with 1, 0. And so on…

Answered By: kindall
dx, dy = -dy, dx

When in doubt, apply maths. 😉

Answered By: Magnus Hoff

While I would go with Magnus’ answer, here’s yet another approach for rotating over a set of values:

def rotate(*states):
    while 1:
        for state in states:
            yield state

for dx, dy in rotate((1, 0), (0, 1), (-1, 0), (0, -1)):
    pass

Note that there should be a break somewhere in the for dx, dy loop or else it will never end.

Answered By: yak

The values you’re working with appear to be a unit vector that continuously rotates – in other words, a phasor. Complex numbers are coordinates, so:

# at initialization
phase = 1
# at the point of modification
phase *= 1j
dx, dy = phase.real, phase.imag

Assuming my interpretation of the meaning of the dx,dy values is correct, this gives you extra flexibility in case it turns out later that you want to rotate by some other amount in each step.

Answered By: Karl Knechtel

Just extending Magnus answer. If you imagine [dx, dy] as a vector, what you’re actually doing is a rotation of 90 degrees (or PI/2).

To calculate this, you can use the following transformation:

two dimensional rotation

Which in your case translate to:

x = x * cos(90) - y * sin(90)
y = x * sin(90) + y * cos(90)

Since sin(90) = 1 and cos(90) = 0 we simplify it to:

x, y = -y, x

And there you have it!

Answered By: Andre Rodrigues
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.