Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Iterate over pairs in order of sum of absolute values

Tags:

python

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.

like image 838
graffe Avatar asked Oct 19 '21 21:10

graffe


2 Answers

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).

like image 69
ShadowRanger Avatar answered Oct 20 '22 00:10

ShadowRanger


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)))
like image 41
Tim Roberts Avatar answered Oct 19 '22 23:10

Tim Roberts