Concatenates both check bipatrite graphs(bfs&dfs) (#10708)

* sync

* fixes#8098

* deleted:    graphs/check_bipartite_graph_all.py
	new file:   graphs/check_bipatrite,py

* renamed:    graphs/check_bipatrite,py -> graphs/check_bipatrite.py

* [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci

* Add the new tests

---------

Co-authored-by: Christian Clauss <cclauss@me.com>
Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
This commit is contained in:
shivaparihar6119 2023-10-20 11:39:58 +05:30 committed by GitHub
parent 82fc24ce96
commit 197604898b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 179 additions and 157 deletions

View File

@ -65,9 +65,7 @@
## Boolean Algebra ## Boolean Algebra
* [And Gate](boolean_algebra/and_gate.py) * [And Gate](boolean_algebra/and_gate.py)
* [Imply Gate](boolean_algebra/imply_gate.py)
* [Nand Gate](boolean_algebra/nand_gate.py) * [Nand Gate](boolean_algebra/nand_gate.py)
* [Nimply Gate](boolean_algebra/nimply_gate.py)
* [Nor Gate](boolean_algebra/nor_gate.py) * [Nor Gate](boolean_algebra/nor_gate.py)
* [Not Gate](boolean_algebra/not_gate.py) * [Not Gate](boolean_algebra/not_gate.py)
* [Or Gate](boolean_algebra/or_gate.py) * [Or Gate](boolean_algebra/or_gate.py)
@ -180,9 +178,7 @@
## Data Structures ## Data Structures
* Arrays * Arrays
* [Equilibrium Index In Array](data_structures/arrays/equilibrium_index_in_array.py) * [Equilibrium Index In Array](data_structures/arrays/equilibrium_index_in_array.py)
* [Find Triplets With 0 Sum](data_structures/arrays/find_triplets_with_0_sum.py)
* [Median Two Array](data_structures/arrays/median_two_array.py) * [Median Two Array](data_structures/arrays/median_two_array.py)
* [Pairs With Given Sum](data_structures/arrays/pairs_with_given_sum.py)
* [Permutations](data_structures/arrays/permutations.py) * [Permutations](data_structures/arrays/permutations.py)
* [Prefix Sum](data_structures/arrays/prefix_sum.py) * [Prefix Sum](data_structures/arrays/prefix_sum.py)
* [Product Sum](data_structures/arrays/product_sum.py) * [Product Sum](data_structures/arrays/product_sum.py)
@ -402,7 +398,6 @@
## Financial ## Financial
* [Equated Monthly Installments](financial/equated_monthly_installments.py) * [Equated Monthly Installments](financial/equated_monthly_installments.py)
* [Exponential Moving Average](financial/exponential_moving_average.py)
* [Interest](financial/interest.py) * [Interest](financial/interest.py)
* [Present Value](financial/present_value.py) * [Present Value](financial/present_value.py)
* [Price Plus Tax](financial/price_plus_tax.py) * [Price Plus Tax](financial/price_plus_tax.py)
@ -711,7 +706,6 @@
* [Sin](maths/sin.py) * [Sin](maths/sin.py)
* [Sock Merchant](maths/sock_merchant.py) * [Sock Merchant](maths/sock_merchant.py)
* [Softmax](maths/softmax.py) * [Softmax](maths/softmax.py)
* [Solovay Strassen Primality Test](maths/solovay_strassen_primality_test.py)
* [Square Root](maths/square_root.py) * [Square Root](maths/square_root.py)
* [Sum Of Arithmetic Series](maths/sum_of_arithmetic_series.py) * [Sum Of Arithmetic Series](maths/sum_of_arithmetic_series.py)
* [Sum Of Digits](maths/sum_of_digits.py) * [Sum Of Digits](maths/sum_of_digits.py)
@ -753,7 +747,6 @@
* [Spiral Print](matrix/spiral_print.py) * [Spiral Print](matrix/spiral_print.py)
* Tests * Tests
* [Test Matrix Operation](matrix/tests/test_matrix_operation.py) * [Test Matrix Operation](matrix/tests/test_matrix_operation.py)
* [Validate Sudoku Board](matrix/validate_sudoku_board.py)
## Networking Flow ## Networking Flow
* [Ford Fulkerson](networking_flow/ford_fulkerson.py) * [Ford Fulkerson](networking_flow/ford_fulkerson.py)
@ -829,7 +822,6 @@
* [Rms Speed Of Molecule](physics/rms_speed_of_molecule.py) * [Rms Speed Of Molecule](physics/rms_speed_of_molecule.py)
* [Shear Stress](physics/shear_stress.py) * [Shear Stress](physics/shear_stress.py)
* [Speed Of Sound](physics/speed_of_sound.py) * [Speed Of Sound](physics/speed_of_sound.py)
* [Speeds Of Gas Molecules](physics/speeds_of_gas_molecules.py)
## Project Euler ## Project Euler
* Problem 001 * Problem 001
@ -1220,7 +1212,6 @@
* [Capitalize](strings/capitalize.py) * [Capitalize](strings/capitalize.py)
* [Check Anagrams](strings/check_anagrams.py) * [Check Anagrams](strings/check_anagrams.py)
* [Credit Card Validator](strings/credit_card_validator.py) * [Credit Card Validator](strings/credit_card_validator.py)
* [Damerau Levenshtein Distance](strings/damerau_levenshtein_distance.py)
* [Detecting English Programmatically](strings/detecting_english_programmatically.py) * [Detecting English Programmatically](strings/detecting_english_programmatically.py)
* [Dna](strings/dna.py) * [Dna](strings/dna.py)
* [Edit Distance](strings/edit_distance.py) * [Edit Distance](strings/edit_distance.py)
@ -1255,7 +1246,6 @@
* [String Switch Case](strings/string_switch_case.py) * [String Switch Case](strings/string_switch_case.py)
* [Strip](strings/strip.py) * [Strip](strings/strip.py)
* [Text Justification](strings/text_justification.py) * [Text Justification](strings/text_justification.py)
* [Title](strings/title.py)
* [Top K Frequent Words](strings/top_k_frequent_words.py) * [Top K Frequent Words](strings/top_k_frequent_words.py)
* [Upper](strings/upper.py) * [Upper](strings/upper.py)
* [Wave](strings/wave.py) * [Wave](strings/wave.py)

View File

@ -1,92 +0,0 @@
# Check whether Graph is Bipartite or Not using BFS
# A Bipartite Graph is a graph whose vertices can be divided into two independent sets,
# U and V such that every edge (u, v) either connects a vertex from U to V or a vertex
# from V to U. In other words, for every edge (u, v), either u belongs to U and v to V,
# or u belongs to V and v to U. We can also say that there is no edge that connects
# vertices of same set.
from queue import Queue
def check_bipartite(graph):
"""
>>> check_bipartite({})
True
>>> check_bipartite({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})
True
>>> check_bipartite({0: [1, 2, 3], 1: [0, 2], 2: [0, 1, 3], 3: [0, 2]})
False
>>> check_bipartite({0: [4], 1: [], 2: [4], 3: [4], 4: [0, 2, 3]})
True
>>> check_bipartite({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
False
>>> check_bipartite({7: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
Traceback (most recent call last):
...
KeyError: 0
>>> check_bipartite({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 9: [0]})
Traceback (most recent call last):
...
KeyError: 4
>>> check_bipartite({0: [-1, 3], 1: [0, -2]})
Traceback (most recent call last):
...
IndexError: list index out of range
>>> check_bipartite({-1: [0, 2], 0: [-1, 1], 1: [0, 2], 2: [-1, 1]})
True
>>> check_bipartite({0.9: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})
Traceback (most recent call last):
...
KeyError: 0
>>> check_bipartite({0: [1.0, 3.0], 1.0: [0, 2.0], 2.0: [1.0, 3.0], 3.0: [0, 2.0]})
Traceback (most recent call last):
...
TypeError: list indices must be integers or slices, not float
>>> check_bipartite({"a": [1, 3], "b": [0, 2], "c": [1, 3], "d": [0, 2]})
Traceback (most recent call last):
...
KeyError: 0
>>> check_bipartite({0: ["b", "d"], 1: ["a", "c"], 2: ["b", "d"], 3: ["a", "c"]})
Traceback (most recent call last):
...
TypeError: list indices must be integers or slices, not str
"""
queue = Queue()
visited = [False] * len(graph)
color = [-1] * len(graph)
def bfs():
while not queue.empty():
u = queue.get()
visited[u] = True
for neighbour in graph[u]:
if neighbour == u:
return False
if color[neighbour] == -1:
color[neighbour] = 1 - color[u]
queue.put(neighbour)
elif color[neighbour] == color[u]:
return False
return True
for i in range(len(graph)):
if not visited[i]:
queue.put(i)
color[i] = 0
if bfs() is False:
return False
return True
if __name__ == "__main__":
# Adjacency List of graph
print(check_bipartite({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]}))
import doctest
doctest.testmod()

View File

@ -1,55 +0,0 @@
from collections import defaultdict
def is_bipartite(graph: defaultdict[int, list[int]]) -> bool:
"""
Check whether a graph is Bipartite or not using Depth-First Search (DFS).
A Bipartite Graph is a graph whose vertices can be divided into two independent
sets, U and V such that every edge (u, v) either connects a vertex from
U to V or a vertex from V to U. In other words, for every edge (u, v),
either u belongs to U and v to V, or u belongs to V and v to U. There is
no edge that connects vertices of the same set.
Args:
graph: An adjacency list representing the graph.
Returns:
True if there's no edge that connects vertices of the same set, False otherwise.
Examples:
>>> is_bipartite(
... defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4], 3: [1], 4: [2]})
... )
False
>>> is_bipartite(defaultdict(list, {0: [1, 2], 1: [0, 2], 2: [0, 1]}))
True
"""
def depth_first_search(node: int, color: int) -> bool:
visited[node] = color
return any(
visited[neighbour] == color
or (
visited[neighbour] == -1
and not depth_first_search(neighbour, 1 - color)
)
for neighbour in graph[node]
)
visited: defaultdict[int, int] = defaultdict(lambda: -1)
return all(
not (visited[node] == -1 and not depth_first_search(node, 0)) for node in graph
)
if __name__ == "__main__":
import doctest
result = doctest.testmod()
if result.failed:
print(f"{result.failed} test(s) failed.")
else:
print("All tests passed!")

179
graphs/check_bipatrite.py Normal file
View File

@ -0,0 +1,179 @@
from collections import defaultdict, deque
def is_bipartite_dfs(graph: defaultdict[int, list[int]]) -> bool:
"""
Check if a graph is bipartite using depth-first search (DFS).
Args:
graph: Adjacency list representing the graph.
Returns:
True if bipartite, False otherwise.
Checks if the graph can be divided into two sets of vertices, such that no two
vertices within the same set are connected by an edge.
Examples:
# FIXME: This test should pass.
>>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]}))
Traceback (most recent call last):
...
RuntimeError: dictionary changed size during iteration
>>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 1]}))
False
>>> is_bipartite_dfs({})
True
>>> is_bipartite_dfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})
True
>>> is_bipartite_dfs({0: [1, 2, 3], 1: [0, 2], 2: [0, 1, 3], 3: [0, 2]})
False
>>> is_bipartite_dfs({0: [4], 1: [], 2: [4], 3: [4], 4: [0, 2, 3]})
True
>>> is_bipartite_dfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
False
>>> is_bipartite_dfs({7: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
Traceback (most recent call last):
...
KeyError: 0
# FIXME: This test should fails with KeyError: 4.
>>> is_bipartite_dfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 9: [0]})
False
>>> is_bipartite_dfs({0: [-1, 3], 1: [0, -2]})
Traceback (most recent call last):
...
KeyError: -1
>>> is_bipartite_dfs({-1: [0, 2], 0: [-1, 1], 1: [0, 2], 2: [-1, 1]})
True
>>> is_bipartite_dfs({0.9: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})
Traceback (most recent call last):
...
KeyError: 0
# FIXME: This test should fails with TypeError: list indices must be integers or...
>>> is_bipartite_dfs({0: [1.0, 3.0], 1.0: [0, 2.0], 2.0: [1.0, 3.0], 3.0: [0, 2.0]})
True
>>> is_bipartite_dfs({"a": [1, 3], "b": [0, 2], "c": [1, 3], "d": [0, 2]})
Traceback (most recent call last):
...
KeyError: 1
>>> is_bipartite_dfs({0: ["b", "d"], 1: ["a", "c"], 2: ["b", "d"], 3: ["a", "c"]})
Traceback (most recent call last):
...
KeyError: 'b'
"""
def depth_first_search(node: int, color: int) -> bool:
"""
Perform Depth-First Search (DFS) on the graph starting from a node.
Args:
node: The current node being visited.
color: The color assigned to the current node.
Returns:
True if the graph is bipartite starting from the current node,
False otherwise.
"""
if visited[node] == -1:
visited[node] = color
for neighbor in graph[node]:
if not depth_first_search(neighbor, 1 - color):
return False
return visited[node] == color
visited: defaultdict[int, int] = defaultdict(lambda: -1)
for node in graph:
if visited[node] == -1 and not depth_first_search(node, 0):
return False
return True
def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool:
"""
Check if a graph is bipartite using a breadth-first search (BFS).
Args:
graph: Adjacency list representing the graph.
Returns:
True if bipartite, False otherwise.
Check if the graph can be divided into two sets of vertices, such that no two
vertices within the same set are connected by an edge.
Examples:
# FIXME: This test should pass.
>>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]}))
Traceback (most recent call last):
...
RuntimeError: dictionary changed size during iteration
>>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 2], 2: [0, 1]}))
False
>>> is_bipartite_bfs({})
True
>>> is_bipartite_bfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})
True
>>> is_bipartite_bfs({0: [1, 2, 3], 1: [0, 2], 2: [0, 1, 3], 3: [0, 2]})
False
>>> is_bipartite_bfs({0: [4], 1: [], 2: [4], 3: [4], 4: [0, 2, 3]})
True
>>> is_bipartite_bfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
False
>>> is_bipartite_bfs({7: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
Traceback (most recent call last):
...
KeyError: 0
# FIXME: This test should fails with KeyError: 4.
>>> is_bipartite_bfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 9: [0]})
False
>>> is_bipartite_bfs({0: [-1, 3], 1: [0, -2]})
Traceback (most recent call last):
...
KeyError: -1
>>> is_bipartite_bfs({-1: [0, 2], 0: [-1, 1], 1: [0, 2], 2: [-1, 1]})
True
>>> is_bipartite_bfs({0.9: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})
Traceback (most recent call last):
...
KeyError: 0
# FIXME: This test should fails with TypeError: list indices must be integers or...
>>> is_bipartite_bfs({0: [1.0, 3.0], 1.0: [0, 2.0], 2.0: [1.0, 3.0], 3.0: [0, 2.0]})
True
>>> is_bipartite_bfs({"a": [1, 3], "b": [0, 2], "c": [1, 3], "d": [0, 2]})
Traceback (most recent call last):
...
KeyError: 1
>>> is_bipartite_bfs({0: ["b", "d"], 1: ["a", "c"], 2: ["b", "d"], 3: ["a", "c"]})
Traceback (most recent call last):
...
KeyError: 'b'
"""
visited: defaultdict[int, int] = defaultdict(lambda: -1)
for node in graph:
if visited[node] == -1:
queue: deque[int] = deque()
queue.append(node)
visited[node] = 0
while queue:
curr_node = queue.popleft()
for neighbor in graph[curr_node]:
if visited[neighbor] == -1:
visited[neighbor] = 1 - visited[curr_node]
queue.append(neighbor)
elif visited[neighbor] == visited[curr_node]:
return False
return True
if __name__ == "__main":
import doctest
result = doctest.testmod()
if result.failed:
print(f"{result.failed} test(s) failed.")
else:
print("All tests passed!")