From 7b17be5898b11e313e7e325197455f814e620d60 Mon Sep 17 00:00:00 2001 From: Kyra Patton Date: Thu, 22 Sep 2022 14:33:30 -0700 Subject: [PATCH 1/5] 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/5] 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/5] 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 01c4b869298be41c5209a2cdf7a6c3543745af19 Mon Sep 17 00:00:00 2001 From: Gabriela Webb Date: Mon, 7 Nov 2022 00:54:36 -0500 Subject: [PATCH 4/5] passes 7/10 tests --- graphs/possible_bipartition.py | 54 +++++++++++++++++++++++++++++++++- 1 file changed, 53 insertions(+), 1 deletion(-) diff --git a/graphs/possible_bipartition.py b/graphs/possible_bipartition.py index ca55677..820573f 100644 --- a/graphs/possible_bipartition.py +++ b/graphs/possible_bipartition.py @@ -8,5 +8,57 @@ def possible_bipartition(dislikes): Time Complexity: ? Space Complexity: ? """ - pass + if len(dislikes) == 0: + return True + + all_puppies = list(dislikes.keys()) + first_pup = all_puppies[0] + # if len(dislikes) == 1: + # return [first_pup] + + queue = [first_pup] + visited = set() + groups = { + first_pup: "A" + } + + + # i = 0 + for pup in all_puppies: + while queue: + # while i < len(queue): + current = queue.pop(0) + opposite_group = "B" if groups[current] == "A" else "A" + # i += 1 + visited.add(current) + + # for pup in dislikes[current]: + if dislikes[current]: + for pup in dislikes[current]: + # print(f"current:{current}") + # print(f"pup:{pup}") + if pup not in visited: + queue.append(pup) + # visited.add(pup) + groups[pup] = opposite_group + elif groups[current] == groups[pup]: + return False + + return True + # return visited + +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"] +} + + +print (possible_bipartition(dislikes)) From b2ae037d2e5d3d45f0476215c980558433e0e660 Mon Sep 17 00:00:00 2001 From: Gabriela Webb Date: Mon, 21 Nov 2022 00:10:22 -0500 Subject: [PATCH 5/5] passes all tests --- graphs/possible_bipartition.py | 63 ++++++++++------------------------ 1 file changed, 19 insertions(+), 44 deletions(-) diff --git a/graphs/possible_bipartition.py b/graphs/possible_bipartition.py index 820573f..4d96804 100644 --- a/graphs/possible_bipartition.py +++ b/graphs/possible_bipartition.py @@ -5,60 +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 """ if len(dislikes) == 0: return True - - all_puppies = list(dislikes.keys()) - first_pup = all_puppies[0] - # if len(dislikes) == 1: - # return [first_pup] - + + groups = {} + for key in dislikes.keys(): + groups[key] = 0 + + first_pup = list(dislikes.keys())[0] + groups[first_pup] = 1 queue = [first_pup] visited = set() - groups = { - first_pup: "A" - } - - # i = 0 - for pup in all_puppies: + for pup in dislikes: while queue: - # while i < len(queue): current = queue.pop(0) - opposite_group = "B" if groups[current] == "A" else "A" - # i += 1 visited.add(current) - - # for pup in dislikes[current]: + if dislikes[current]: - for pup in dislikes[current]: - # print(f"current:{current}") - # print(f"pup:{pup}") - if pup not in visited: - queue.append(pup) - # visited.add(pup) - groups[pup] = opposite_group - elif groups[current] == groups[pup]: + 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 - # return visited - -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"] -} - - -print (possible_bipartition(dislikes)) + \ No newline at end of file