I created a solution using set
and for...else
... Yes, that for...else
may seem very strange but when you understand what it’s for it can be very useful, as is the case...
Steps to solving the problem:
- Create a list of social groups;
- Scroll through all received relationships as argument;
Test if any of the students in each relationship are already in some group
If at least one of the students is already in a group, add both in the group (as we are working with set
there will be no duplicate students in the group);
If both students are not in any group, create a new group with both students.
Return the resulting group list
Code:
def redes(relacionamentos):
grupos = []
for rel in relacionamentos:
rel = set(rel)
for grupo in grupos:
if grupo & rel:
grupo |= rel
break
else:
grupos.append(rel)
return grupos
PS: I purposely ignored the number of students proposed in the exercise because it makes no difference in the algorithm, except perhaps the validation of the received tuples.
Explanation
If you check the documentation you will find the following:
Loop statements may have an Else clause; it is executed when the loop Terminates through exhaustion of the iterable (with for) or when the condition Becomes false (with while), but not when the loop is terminated by a break statement.
Free translation:
Repeat loops may have a clause else
; this will be executed when the loop ends by the exhaustion of the eternal (with for
) or when the condition becomes false (with while
), but not when the loop is ending through a break
.
So what I did in my code is I went through all the social groups that exist up to that point, and if any of the students are part of some group, add both to the group and get out of the loop using break
, that way you won’t fall in else
.
However, if, after going through all the groups, students do not yet belong to any of the groups Python will run the block else
where I create a new group with students.
Examples:
for...else
:
If you iterate to the end, you enter else
:
for i in range(5):
print(i, end=" ")
else:
print("\n[O for executou até o fim sem interrupção]")
Exit
0 1 2 3 4
[O for executou até o fim sem interrupção]
If interrupted by a break
:
for i in range(5):
break
else:
print("[Nunca ocorrerá por causa do break]")
The above code does not print anything on the screen as it does not enter the else
.
while...else
:
If you iterate to the end, you enter else
:
i = 0
while i < 5:
print(i, end=" ")
i += 1
else:
print("\n[O while executou até o fim sem interrupção]")
Exit
0 1 2 3 4
[O while executou até o fim sem interrupção]
If interrupted by a break
:
i = 0
while i < 5:
break
else:
print("[Nunca ocorrerá por causa do break]")
The above code does not print anything on the screen as it does not enter the else
.
Code running on Repl.it
Full code with examples mentioned in the question
def redes(relacionamentos):
grupos = []
for rel in relacionamentos:
rel = set(rel) # transformo a tupla em set
for grupo in grupos:
if grupo & rel: # se um dos alunos está no grupo
grupo |= rel # adiciona os alunos ao grupo
break # sai do for
else:
grupos.append(rel)
return grupos
exemplos = [
[(0, 1), (1, 2), (3, 4)], # Primeiro exemplo da pergunta
[(0, 1), (3, 5), (3, 6)], # Exemplo com erro na pergunta
]
print(f">>> redes({exemplos[0]!r})")
resultado_1 = redes(exemplos[0])
for i, grupo in enumerate(resultado_1, start=1):
print(f"Grupo {i}: {grupo!r}")
print(f"\n>>> redes({exemplos[1]!r})")
resultado_1 = redes(exemplos[1])
for i, grupo in enumerate(resultado_1, start=1):
print(f"Grupo {i}: {grupo!r}")
Code running on Repl.it
Exit:
>>> redes([(0, 1), (1, 2), (3, 4)])
Grupo 1: {0, 1, 2}
Grupo 2: {3, 4}
>>> redes([(0, 1), (3, 5), (3, 6)])
Grupo 1: {0, 1}
Grupo 2: {3, 5, 6}
If one of the answers below solved your problem and there was no doubt left, choose the one you liked the most and mark it as correct/accepted by clicking on the " " that is next to it, which also marks your question as solved. If you still have any questions or would like further clarification, feel free to comment.
– Lucas