Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Gaby Webb c17 whales #6

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
76 changes: 38 additions & 38 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,57 +11,57 @@ In this exercise you should be able to:

## Description

Given a set of N puppies (numbered 0, 1, 2, ..., N - 1), we would like to split them into two groups of any size to use two play areas.
Given a set of N puppies, we would like to split them into two groups of any size to use two play areas.

Some dogs have a history of fighting with specific other dogs and shouldn't be put into the same play area.

Formally, if dislikes[i] = [a, b], it means dog i is not allowed to put in the same group as dog a or dog b.
Formally, if `dislikes[i] = [a, b]`, it means dog `i` is not allowed to put in the same group as dog `a` or dog `b`.

Return true if and only if it is possible to split the dogs into two groups where no fighting will occur.
Dislike is mutual. If dog `a` that dislikes dog `b`, dog `b` also dislikes dog `a`.

### Example 1
Return `True` if and only if it is possible to split the dogs into two groups where no fighting will occur. Otherwise, return `False`.

### Example 1
*Input*:
``` python
dislikes = {
"Fido": [],
"Nala": ["Cooper", "Spot"],
"Cooper": ["Nala", "Bruno"],
"Spot": ["Nala"],
"Bruno": ["Cooper"]
}
```
Input: dislikes = [ [],
[2, 3],
[1, 4],
[1],
[2]
]
Output: true
```

Explanation: group1 [0, 1, 4], group2 [2, 3]
*Output*: `True`
Explanation: group1: `["Fido", "Nala", "Bruno"]`, group2: `["Cooper", "Spot"]`

### Example 2

```
Input: dislikes = [ [],
[2, 3],
[1, 3],
[1, 2]
]
Output: false
*Input*:
```python
dislikes = {
"Fido": [],
"Nala": ["Cooper", "Spot"],
"Coooper": ["Nala", "Spot"],
"Spot": ["Nala", "Cooper"]
}
```

Explanation: All the nodes 1-3 are interconnected and so there is no way to split them up.
*Output*: `False`
Explanation: The nodes `Nala`, `Cooper`, and `Spot` are interconnected and so there is no way to split them up.

### Example 3

```
Input: dislikes = [ [],
[2, 5],
[1, 3],
[2, 4],
[3, 5],
[1, 4]
]
Output: false
*Input*:
```Python
dislikes = {
"Fido": [],
"Nala": ["Cooper", "Cali"],
"Cooper": ["Nala", "Spot"],
"Spot": ["Cooper", "Bruno"],
"Bruno": ["Spot", "Cali"],
"Cali": ["Nala", "Bruno"]
}
```

### Note

The graph is undirected, so if dog 1 dislikes dog 2, then dog 2 also dislikes dog 1.
*Output*: `False`
Explanation: There is no way to split `Nala`, `Cooper`, `Spot`, `Bruno`, and `Cali` up into two groups such that they are all separated from the dogs they dislike.

## Source

Expand Down
33 changes: 30 additions & 3 deletions graphs/possible_bipartition.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,35 @@ def possible_bipartition(dislikes):
""" Will return True or False if the given graph
can be bipartitioned without neighboring nodes put
into the same partition.
Time Complexity: ?
Space Complexity: ?
Time Complexity: O(N + E) where N is the number of nodes & E is the number of edges
Space Complexity: O(N) where N is the number of nodes
"""
pass

if len(dislikes) == 0:
return True

groups = {}
for key in dislikes.keys():
groups[key] = 0

first_pup = list(dislikes.keys())[0]
groups[first_pup] = 1
queue = [first_pup]
visited = set()

for pup in dislikes:
while queue:
current = queue.pop(0)
visited.add(current)

if dislikes[current]:
for dog in dislikes[current]:
if groups[dog] == 0:
groups[dog] = groups[current] + 1
queue.append(dog)
elif groups[dog] == groups[current]:
return False
if pup not in visited:
queue.append(pup)
return True

158 changes: 112 additions & 46 deletions tests/test_possible_bipartition.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,12 +3,13 @@

def test_example_1():
# Arrange
dislikes = [ [],
[2, 3],
[1, 4],
[1],
[2]
]
dislikes = {
"Fido": [],
"Rufus": ["James", "Alfie"],
"James": ["Rufus", "T-Bone"],
"Alfie": ["Rufus"],
"T-Bone": ["James"]
}

# Act
answer = possible_bipartition(dislikes)
Expand All @@ -17,12 +18,12 @@ def test_example_1():
assert answer

def test_example_2():
# Arrange
dislikes = [ [],
[2, 3],
[1, 3],
[1, 2]
]
dislikes = {
"Fido": [],
"Rufus": ["James", "Alfie"],
"James": ["Rufus", "Alfie"],
"Alfie": ["Rufus", "James"]
}

# Act
answer = possible_bipartition(dislikes)
Expand All @@ -32,13 +33,14 @@ def test_example_2():

def test_example_r():
# Arrange
dislikes = [ [],
[2, 5],
[1, 3],
[2, 4],
[3, 5],
[1, 4]
]
dislikes = {
"Fido": [],
"Rufus": ["James", "Scruffy"],
"James": ["Rufus", "Alfie"],
"Alfie": ["Rufus", "T-Bone"],
"T-Bone": ["Alfie", "Scruffy"],
"Scruffy": ["Rufus", "T-Bone"]
}

# Act
answer = possible_bipartition(dislikes)
Expand All @@ -48,14 +50,15 @@ def test_example_r():

def test_will_return_true_for_a_graph_which_can_be_bipartitioned():
# Arrange
dislikes = [ [3, 6],
[2, 5],
[1, 3],
[0, 2],
[5],
[1, 4],
[0]
]
dislikes = {
"Fido": ["Alfie", "Bruno"],
"Rufus": ["James", "Scruffy"],
"James": ["Rufus", "Alfie"],
"Alfie": ["Fido", "James"],
"T-Bone": ["Scruffy"],
"Scruffy": ["Rufus", "T-Bone"],
"Bruno": ["Fido"]
}

# Act
answer = possible_bipartition(dislikes)
Expand All @@ -65,14 +68,15 @@ def test_will_return_true_for_a_graph_which_can_be_bipartitioned():

def test_will_return_false_for_graph_which_cannot_be_bipartitioned():
# Arrange
dislikes = [ [3, 6],
[2, 5],
[1, 3],
[0, 2, 4],
[3, 5],
[1, 4],
[0]
]
dislikes = {
"Fido": ["Alfie", "Bruno"],
"Rufus": ["James", "Scruffy"],
"James": ["Rufus", "Alfie"],
"Alfie": ["Fido", "James", "T-Bone"],
"T-Bone": ["Alfie", "Scruffy"],
"Scruffy": ["Rufus", "T-Bone"],
"Bruno": ["Fido"]
}

# Act
answer = possible_bipartition(dislikes)
Expand All @@ -82,23 +86,85 @@ def test_will_return_false_for_graph_which_cannot_be_bipartitioned():


def test_will_return_true_for_empty_graph():
assert possible_bipartition([])
assert possible_bipartition({})

def test_will_return_false_for_another_graph_which_cannot_be_bipartitioned():
# Arrange
dislikes = [ [3, 6],
[2, 5],
[1, 3],
[0, 2, 4],
[3, 5],
[1, 4],
[0],
[8],
[7]
]
dislikes = {
"Fido": ["Alfie", "Bruno"],
"Rufus": ["James", "Scruffy"],
"James": ["Rufus", "Alfie"],
"Alfie": ["Fido", "James", "T-Bone"],
"T-Bone": ["Alfie", "Scruffy"],
"Scruffy": ["Rufus", "T-Bone"],
"Bruno": ["Fido"],
"Spot": ["Nala"],
"Nala": ["Spot"]
}

# Act
answer = possible_bipartition(dislikes)

# Assert
assert not answer

def test_multiple_dogs_at_beginning_dont_dislike_any_others():
# Arrange
dislikes = {
"Fido": [],
"Rufus": [],
"James": [],
"Alfie": ["T-Bone"],
"T-Bone": ["Alfie", "Scruffy"],
"Scruffy": ["T-Bone"],
"Bruno": ["Nala"],
"Spot": ["Nala"],
"Nala": ["Bruno", "Spot"]
}

# Act
answer = possible_bipartition(dislikes)

# Assert
assert answer


def test_multiple_dogs_in_middle_dont_dislike_any_others():
# Arrange
dislikes = {
"Fido": ["Alfie"],
"Rufus": ["James", "Scruffy"],
"James": ["Rufus", "Alfie"],
"Alfie": ["Fido", "James"],
"T-Bone": [],
"Scruffy": ["Rufus"],
"Bruno": [],
"Spot": ["Nala"],
"Nala": ["Spot"]
}

# Act
answer = possible_bipartition(dislikes)

# Assert
assert answer

def test_will_return_false_for_disconnected_graph_which_cannot_be_bipartitioned():
# Arrange
dislikes = {
"Ralph": ["Tony"],
"Tony": ["Ralph"],
"Fido": ["Alfie", "Bruno"],
"Rufus": ["James", "Scruffy"],
"James": ["Rufus", "Alfie"],
"Alfie": ["Fido", "James", "T-Bone"],
"T-Bone": ["Alfie", "Scruffy"],
"Scruffy": ["Rufus", "T-Bone"],
"Bruno": ["Fido"]
}

# Act
answer = possible_bipartition(dislikes)

# Assert
assert not answer