From 7b17be5898b11e313e7e325197455f814e620d60 Mon Sep 17 00:00:00 2001 From: Kyra Patton Date: Thu, 22 Sep 2022 14:33:30 -0700 Subject: [PATCH 1/4] Update README description --- README.md | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/README.md b/README.md index b777198..17c3cd5 100644 --- a/README.md +++ b/README.md @@ -11,13 +11,13 @@ 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. +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 From fee1c64ddae33dca69893049eb0f17ccba1c489f Mon Sep 17 00:00:00 2001 From: Kyra Patton Date: Thu, 22 Sep 2022 14:54:03 -0700 Subject: [PATCH 2/4] Update examples to use dictionaries --- README.md | 72 +++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index 17c3cd5..d056e01 100644 --- a/README.md +++ b/README.md @@ -17,51 +17,51 @@ Some dogs have a history of fighting with specific other dogs and shouldn't be p 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. Otherwise, return `False` +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 From db38388ffa66c9d0e2c0f55bd9bf9efd633b8caf Mon Sep 17 00:00:00 2001 From: char Date: Thu, 22 Sep 2022 15:32:47 -0700 Subject: [PATCH 3/4] update test cases --- tests/test_possible_bipartition.py | 158 ++++++++++++++++++++--------- 1 file changed, 112 insertions(+), 46 deletions(-) diff --git a/tests/test_possible_bipartition.py b/tests/test_possible_bipartition.py index 88ba735..7dfbdd8 100644 --- a/tests/test_possible_bipartition.py +++ b/tests/test_possible_bipartition.py @@ -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) @@ -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) @@ -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) @@ -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) @@ -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) @@ -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 \ No newline at end of file From b808b87cad26fff6b3e6b9870ca1432a727a170f Mon Sep 17 00:00:00 2001 From: Bahareh Date: Sun, 22 Jan 2023 15:13:42 -0500 Subject: [PATCH 4/4] passed all tests --- graphs/possible_bipartition.py | 40 ++++++++++++++++++++++++++++------ 1 file changed, 33 insertions(+), 7 deletions(-) diff --git a/graphs/possible_bipartition.py b/graphs/possible_bipartition.py index ca55677..a1e3b72 100644 --- a/graphs/possible_bipartition.py +++ b/graphs/possible_bipartition.py @@ -2,11 +2,37 @@ from collections import deque 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: ? - """ - pass + + # Can be used for BFS + from collections import deque + + + + if len(dislikes) == 0: + return True + + checked = set() + + for each_dog in dislikes.keys(): + + colored_dogs = {each_dog: 'red'} # visited + queue = [each_dog] + + while queue: + + dog = queue.pop(0) # current dog + checked.add(dog) + + color = 'red' if colored_dogs[dog] == 'blue' else 'blue' + + for neighbor in dislikes[dog]: + if neighbor not in colored_dogs: + colored_dogs[neighbor] = color + queue.append(neighbor) + elif colored_dogs[neighbor] != color: + return False + + return True + +