How to get graphically connected array items in Python?
Question:
Alright… Here’s a fun question.
I want to make a program that counts how many patches are connected in a string.
To make this a little easier to grasp, here is how the input/outputs should go:
Input:
.....%%%%%..%
%%%...%%...%%
%.....%%%..%%
...%%.....%%%
....%%.....%%
.....%%%..%%%
%%%%....%%%..
Output:
4 patches.
One block of paint is a "%" sign and a empty space is a ".".
How would I go about finding the number of patches?
For instance, a connected patch would be a few % signs connected like this:
%%%%%
%%...
%....
Answers:
Here’s one way you could do it by using a bit of hackery to create a NetworkX Graph
and then just using NetworkX
algorithm number_connected_components
.
$ ipython
Python 3.10.6 (main, Aug 2 2022, 00:00:00) [GCC 11.3.1 20220421 (Red Hat 11.3.1-2)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: raster='''.....%%%%%..%
...: %%%...%%...%%
...: %.....%%%..%%
...: ...%%.....%%%
...: ....%%.....%%
...: .....%%%..%%%
...: %%%%....%%%..'''
In [2]: import networkx as nx
In [3]: vertices = [(row, column) for row,line in enumerate(raster.splitlines()) for column,char in
...: enumerate(line) if char=='%']
In [4]: G = nx.Graph()
In [5]: G.add_nodes_from(vertices)
In [6]: for node in G:
...: for x in range(node[0]-1,node[0]+2):
...: for y in range (node[1]-1,node[1]+2):
...: if (x,y) in G:
...: G.add_edge(node, (x,y))
...:
In [7]: nx.number_connected_components(G)
Out[7]: 4
If for some unfortunate reason, nice libraries/packages (like NetworkX
) can’t be used, here’s another way to do it.
$ ipython
Python 3.10.6 (main, Aug 2 2022, 00:00:00) [GCC 11.3.1 20220421 (Red Hat 11.3.1-2)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: raster='''.....%%%%%..%
...: %%%...%%...%%
...: %.....%%%..%%
...: ...%%.....%%%
...: ....%%.....%%
...: .....%%%..%%%
...: %%%%....%%%..'''
In [2]: vertices = [(row, column) for row,line in enumerate(raster.splitlines()) for column,char in
...: enumerate(line) if char=='%']
In [3]: vertex_edges = dict()
In [4]: for vertex in vertices:
...: vertex_edges[vertex] = set()
...: for x in range(vertex[0]-1, vertex[0]+2):
...: for y in range (vertex[1]-1, vertex[1]+2):
...: if ((x,y) != vertex) and ((x,y) in vertices):
...: vertex_edges[vertex].add((x,y))
...:
In [5]: num_connected_components = 0
In [6]: removed_vertices = set()
In [7]: while len(vertex_edges) > 0:
...: num_connected_components += 1
...: vertex, vertex_set = vertex_edges.popitem()
...: removed_vertices.add(vertex)
...: while len(vertex_set) > 0:
...: vertex = vertex_set.pop()
...: if vertex in vertex_edges:
...: removed_vertices.add(vertex)
...: vertex_set = vertex_set.union(vertex_edges[vertex] - removed_vertices)
...: _ = vertex_edges.pop(vertex)
...:
In [8]: num_connected_components
Out[8]: 4
Alright… Here’s a fun question.
I want to make a program that counts how many patches are connected in a string.
To make this a little easier to grasp, here is how the input/outputs should go:
Input:
.....%%%%%..%
%%%...%%...%%
%.....%%%..%%
...%%.....%%%
....%%.....%%
.....%%%..%%%
%%%%....%%%..
Output:
4 patches.
One block of paint is a "%" sign and a empty space is a ".".
How would I go about finding the number of patches?
For instance, a connected patch would be a few % signs connected like this:
%%%%%
%%...
%....
Here’s one way you could do it by using a bit of hackery to create a NetworkX Graph
and then just using NetworkX
algorithm number_connected_components
.
$ ipython
Python 3.10.6 (main, Aug 2 2022, 00:00:00) [GCC 11.3.1 20220421 (Red Hat 11.3.1-2)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: raster='''.....%%%%%..%
...: %%%...%%...%%
...: %.....%%%..%%
...: ...%%.....%%%
...: ....%%.....%%
...: .....%%%..%%%
...: %%%%....%%%..'''
In [2]: import networkx as nx
In [3]: vertices = [(row, column) for row,line in enumerate(raster.splitlines()) for column,char in
...: enumerate(line) if char=='%']
In [4]: G = nx.Graph()
In [5]: G.add_nodes_from(vertices)
In [6]: for node in G:
...: for x in range(node[0]-1,node[0]+2):
...: for y in range (node[1]-1,node[1]+2):
...: if (x,y) in G:
...: G.add_edge(node, (x,y))
...:
In [7]: nx.number_connected_components(G)
Out[7]: 4
If for some unfortunate reason, nice libraries/packages (like NetworkX
) can’t be used, here’s another way to do it.
$ ipython
Python 3.10.6 (main, Aug 2 2022, 00:00:00) [GCC 11.3.1 20220421 (Red Hat 11.3.1-2)]
Type 'copyright', 'credits' or 'license' for more information
IPython 8.4.0 -- An enhanced Interactive Python. Type '?' for help.
In [1]: raster='''.....%%%%%..%
...: %%%...%%...%%
...: %.....%%%..%%
...: ...%%.....%%%
...: ....%%.....%%
...: .....%%%..%%%
...: %%%%....%%%..'''
In [2]: vertices = [(row, column) for row,line in enumerate(raster.splitlines()) for column,char in
...: enumerate(line) if char=='%']
In [3]: vertex_edges = dict()
In [4]: for vertex in vertices:
...: vertex_edges[vertex] = set()
...: for x in range(vertex[0]-1, vertex[0]+2):
...: for y in range (vertex[1]-1, vertex[1]+2):
...: if ((x,y) != vertex) and ((x,y) in vertices):
...: vertex_edges[vertex].add((x,y))
...:
In [5]: num_connected_components = 0
In [6]: removed_vertices = set()
In [7]: while len(vertex_edges) > 0:
...: num_connected_components += 1
...: vertex, vertex_set = vertex_edges.popitem()
...: removed_vertices.add(vertex)
...: while len(vertex_set) > 0:
...: vertex = vertex_set.pop()
...: if vertex in vertex_edges:
...: removed_vertices.add(vertex)
...: vertex_set = vertex_set.union(vertex_edges[vertex] - removed_vertices)
...: _ = vertex_edges.pop(vertex)
...:
In [8]: num_connected_components
Out[8]: 4