Here are some hints on how to approach problems like this generally:
- Look for commonly repeated expressions, and name them.
Here, ceil(shift * (i / 2))
happens a lot. Let's name that:
offset = ceil(shift * (i / 2))
if i % 2 == 1 or i == 0:
if x1 > x:
ny = y + offset
ny1 = y1 + offset
elif x1 == x:
ny = y
ny1 = y1
elif x1 < x:
ny = y - offset
ny1 = y1 - offset
if y1 > y:
nx = x - offset
nx1 = x1 - offset
elif y1 == y:
nx = x
nx1 = x1
elif y1 < y:
nx = x + offset
nx1 = x1 + offset
else:
if x1 > x:
ny = y - offset
ny1 = y1 - offset
elif x1 == x:
ny = y
ny1 = y1
elif x1 < x:
ny = y + offset
ny1 = y1 + offset
if y1 > y:
nx = x + offset
nx1 = x1 + offset
elif y1 == y:
nx = x
nx1 = x1
elif y1 < y:
nx = x - offset
nx1 = x1 - offset
return nx, ny, nx1, ny1
- Use Python's simultaneous assignment to group related assignments.
This is pretty straightforward:
offset = ceil(shift * (i / 2))
if i % 2 == 1 or i == 0:
if x1 > x:
ny, ny1 = y + offset, y1 + offset
elif x1 == x:
ny, ny1 = y, y1
elif x1 < x:
ny, ny1 = y - offset, y1 - offset
if y1 > y:
nx, nx1 = x - offset, x1 - offset
elif y1 == y:
nx, nx1 = x, x1
elif y1 < y:
nx, nx1 = x + offset, x1 + offset
else:
if x1 > x:
ny, ny1 = y - offset, y1 - offset
elif x1 == x:
ny, ny1 = y, y1
elif x1 < x:
ny, ny1 = y + offset, y1 + offset
if y1 > y:
nx, nx1 = x + offset, x1 + offset
elif y1 == y:
nx, nx1 = x, x1
elif y1 < y:
nx, nx1 = x - offset, x1 - offset
return nx, ny, nx1, ny1
- Exploit symmetries and parallels. (The reason I make simple syntax tweaks like the simultaneous assignment first is that, by reducing the line count, we can bring symmetrical things visually closer together, and thus notice symmetry more easily.)
What I mean by a "symmetry" or "parallel" is that we do fundamentally the same thing with different variables (or a related thing with some small, patterned alteration). There are two of these here: first, there's the way that the code depends on the i % 2 == 1 or i == 0
. We can quickly see that the effect of this - propagated through all the if
/elif
logic - is that when the condition is false, offset
is subtracted where it would otherwise be added, and vice versa. We can use elementary algebra to simplify that, by simply replacing offset
with -offset
when the condition isn't met. Thus:
offset = ceil(shift * (i / 2))
if not(i % 2 == 1 or i == 0):
offset = -offset
if x1 > x:
ny, ny1 = y + offset, y1 + offset
elif x1 == x:
ny, ny1 = y, y1
elif x1 < x:
ny, ny1 = y - offset, y1 - offset
if y1 > y:
nx, nx1 = x - offset, x1 - offset
elif y1 == y:
nx, nx1 = x, x1
elif y1 < y:
nx, nx1 = x + offset, x1 + offset
return nx, ny, nx1, ny1
- Make algebraic simplifications.
Pattern recognition is useful here. We are doing three-way comparisons, and depending on that comparison we either add, subtract or don't use a given value. We could represent that "add, subtract or don't use" by instead multiplying our offset
by 1, -1 or 0 respectively. If we extract that idea:
def threeway_compare(a1, a):
if a1 > a:
return 1
elif a1 < a:
return -1
return 0 # a1 == a
then we find the hidden symmetry (i.e., we did that kind of three-way comparison twice):
offset = ceil(shift * (i / 2))
if not(i % 2 == 1 or i == 0):
offset = -offset
y_offset = threeway_compare(x1, x)
ny, ny1 = y + y_offset, y1 + y_offset
# Since the changes made to the nx/nx1 values were reversed,
# we negate the comparison result before using it this way.
x_offset = -threeway_compare(y1, y)
nx, nx1 = x + x_offset, x1 + x_offset
return nx, ny, nx1, ny1
- Scrap everything and try a different approach.
Sometimes this is called for. In this particular case, using ceil
in order to calculate an "adjustment" is a warning sign that something is going wrong. It might have been better to compute the nx
etc. values directly, rather than computing x
etc. and then having to adjust them in this way. Perhaps this indicates something wrong about the original question.