I want to iterate over pairs of integers in order of the sum of their absolute values. The list should look like:
(0,0)
(-1,0)
(0,1)
(0,-1)
(1,0)
(-2,0)
(-1,1)
(-1,-1)
(0,2)
(0,-2)
(1,1)
(1,-1)
(2,0)
[...]
For pairs with the same sum of absolute values I don't mind which order they come in.
Ideally I would like to be able to create the pairs forever so that I can use each one in turn. How can you do that?
For a fixed range I can make the list of pairs in an ugly way with:
sorted([(x,y)for x in range(-20,21)for y in range(-20,21)if abs(x)+abs(y)<21],key=lambda x:sum(map(abs,x))
This doesn't allow me to iterate forever and it also doesn't give me one pair at a time.
This seems to do the trick:
from itertools import count # Creates infinite iterator
def abs_value_pairs():
for absval in count(): # Generate all possible sums of absolute values
for a in range(-absval, absval + 1): # Generate all possible first values
b = abs(a) - absval # Compute matching second value (arbitrarily do negative first)
yield a, b
if b: # If first b is zero, don't output again, otherwise, output positive b
yield a, -b
This runs forever, and operates efficiently (avoiding recomputing anything unnecessarily).
This will do it. If you really want it to be infinite, remove the firs if
statement.
import itertools
def makepairs(count=3):
yield (0,0)
for base in itertools.count(1):
if base > count: # optional escape
return # optional escape
for i in range(base+1):
yield (i, base-i)
if base != i:
yield (i, i-base)
if i:
yield (-i, base-i)
if base != i:
yield (-i, i-base)
print(list(makepairs(9)))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With