# Group recursively adjacent tuples from a list in Python

If I understood correctly.

a = [(1, 1), (3, 1), (4, 5), (8, 8), (4, 4), (8, 9), (2, 1)]
a = sorted(a)
def Manhattan(tuple1, tuple2):
return abs(tuple1 - tuple2) + abs(tuple1 - tuple2)

result = [set()]
l = len(a)
for i, v in enumerate(a):
if not i+1 >= l:
if Manhattan(v, a[i+1]) ==1:
else:
result.append(set())
print(result)


Output:

[{(3, 1), (1, 1), (2, 1)}, {(4, 5), (4, 4)}, {(8, 9), (8, 8)}]


A completely different, maybe less efficient but certainly interesting approach, would be with a graph theoretic formulation. You can view this problem as finding all connected components of a graph where two vertices are connected whenever the Manhattan distance is one. Crudely written, you could do :

import networkx as nx

G = nx.Graph()
a = [(1, 1), (3, 1), (4, 5), (8, 8), (4, 4), (8, 9), (2, 1)]
n = len(a)

# Generate edges
for i in range(n):
for j in range(i+1,n):
if Manhattan(a[i],a[j]) == 1:

# Find components
components = nx.connected_components(G)
for x in components:
print(x)


which spits out

{(3, 1), (1, 1), (2, 1)}
{(4, 5), (4, 4)}
{(8, 9), (8, 8)}


a somewhat UnionFind approach, iterating all 1-distanced pairs and "Unifying" their groups:

from itertools import groupby, product

def Manhattan(tuple1, tuple2):
return abs(tuple1 - tuple2) + abs(tuple1 - tuple2)

a = [(1, 1), (3, 1), (4, 5), (8, 8), (4, 4), (8, 9), (2, 1)]

tuple_pairs_with_distance_1 = [sorted(pair) for pair in product(a, repeat=2) if Manhattan(*pair) == 1]

result_dict = {t: {t} for t in a}
for t1, t2 in tuple_pairs_with_distance_1:
# "Unify" these tuple's groups
result_dict[t1] |= result_dict[t2]
result_dict[t2] = result_dict[t1]

result = [[*next(g)] for k, g in groupby(sorted(result_dict.values(), key=id), id)]
print(result)