1

I got into problem to solve matrix grouping problem based on its relation.

Problem

Consider a group of people giving books to each other. More formally, group is composed of all the people who know one another, whether directly to transitively.

Example

Consider a matrix of input M

Input

1100
1110
0110
0001

Output:

2

enter image description here

  • There are n = 4 people numbered related[0] through related[3].
  • There are 2 pairs who directly know each other: (related[0], related[1]) and (related[1], related[2]). Because a relation is transitive, the set of people {related[0], related[1], related[2]} is considered a single group.
  • The remaining person, related[3], does not know any other people and is a separate group: {related[3]}
  • There are a total of 2 groups.

Example

Input:

10000
01000
00100
00010
00001

Output:

5

No direct relationship are shown so there are 5 groups: {related [0], related[1], related[2], related[3], related[4]}

Example

Input

1100000
1110000
0110000
0001000
0000110
0000110
0000001

Output

4
  • There are 2 pairs who directly know each other: (related[0], related[1]) and (related[1], related[2]). Because a relation is transitive, the set of people {related[0], related[1], related[2]} is considered a single group.
  • There is 1 pair who directly know each other: (related[4], related[5]). So they are considered as single group {related[4], related[5]}
  • The remaining person, related[3], related[6] does not know any other people and is a separate group: {related[3]}, {related[6]}
  • There are total 4 group : {{related[0], related[1], related[2]}, {related[4], related[5]}, {related[3]}, {related[6]} }

I need help with how to approach with this kind of problems.

Code (I tried not completed)

def countGroup(matrix):
    people = set()
    group1 = set()
    for i in range(len(matrix)):
        people.add(i) 
        for j in range(len(matrix)):
            if i == j:
              # next
              continue
            if matrix[i][j]:
                group1.add((i,j))
                people.discard(i)
                people.discard(j)
                # group1.add(i)
                # group1.add(j)
    print(people, "people")
    print(group1, "group1")
    count = len(people)
    if group1:
        count += 1

    return count


Avanish Tiwari
  • 201
  • 1
  • 2
  • 10

2 Answers2

0

Your almost there, the issue is the if isn't quite right, and you need to make more use of sets. Haven't tested the code but should work with perhaps a few minor tweaks, my python is a bit rusty.

def countGroup(matrix):
    people = set()
    group1 = set()
    for i in range(len(matrix)):
        people.add(i) # Quick way to build a list of all the people
        for j in range(len(matrix)):
            if i == j: # Not useful, you should know yourself. 
              # Could avoid this by using itertools.combinations
              continue
            if matrix[i][j] == 1: # we just want to know
                group1.add(i)
                group1.add(j)
    group2 = people - group1 # Anyone not in group1 is in group2.

    return (group1, group2)
Avanish Tiwari
  • 201
  • 1
  • 2
  • 10
Nuclearman
  • 5,029
  • 1
  • 19
  • 35
  • This works for 2 group relation but what if I have a big matrix for 10 people as input and there are many grouping relation. Consider `matrix = [ [1,1,0,0,0,0,0], [1,1,1,0,0,0,0], [0,1,1,0,0,0,0], [0,0,0,1,0,0,0], [0,0,0,0,1,1,0], [0,0,0,0,1,1,0], [0,0,0,0,0,0,1] ]` it has group 4, related {[0,1,2], [4,5], [3], [6]}. How can it get this your algorithm please help – Avanish Tiwari Oct 19 '20 at 08:40
  • Please update your question with that information and explain what you are really looking for in terms of group. You may want to look into adjacency lists as a way to store graphs instead. I was going to give an example of building an adjacency list then having everyone in the adjacency list being part of group 1 while everyone not in being part of group 2. But it was excessively complicated for this purpose and the above algorithm works better. Here is a graph utility I usually use for building them (but it's ruby not python) https://gist.github.com/MyklClason/fe603a6005a1dedc6ec65fda7ff47f68 – Nuclearman Oct 20 '20 at 02:31
  • Yup just use adjacency lists. That will let you know that this person knows these people. From there you can use a breadth first search to get the list of all people that each other knows. What you are looking for is known as `Connected Components`. https://en.wikipedia.org/wiki/Component_(graph_theory) – Nuclearman Oct 20 '20 at 09:06
0

You need something like this pseudo code:

relationship_groups = []
for i, relationship in enumerate(relationships):
  for j, related in enumerate(relationship):
    if related == 1:
       # for all sets in relationship_groups
           # check if i or j exists in those sets
           # if j, break, if i add j
       # if you don't find any relationship
           # create a new group (set) for i and j and add them
           # to relationship groups
# return the length of relationship groups.

That should get you most of the way there.

Will Brown
  • 41
  • 1
  • 4