mirror of
https://github.com/TheAlgorithms/Python.git
synced 2024-11-23 21:11:08 +00:00
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:
parent
82fc24ce96
commit
197604898b
10
DIRECTORY.md
10
DIRECTORY.md
|
@ -65,9 +65,7 @@
|
|||
|
||||
## Boolean Algebra
|
||||
* [And Gate](boolean_algebra/and_gate.py)
|
||||
* [Imply Gate](boolean_algebra/imply_gate.py)
|
||||
* [Nand Gate](boolean_algebra/nand_gate.py)
|
||||
* [Nimply Gate](boolean_algebra/nimply_gate.py)
|
||||
* [Nor Gate](boolean_algebra/nor_gate.py)
|
||||
* [Not Gate](boolean_algebra/not_gate.py)
|
||||
* [Or Gate](boolean_algebra/or_gate.py)
|
||||
|
@ -180,9 +178,7 @@
|
|||
## Data Structures
|
||||
* Arrays
|
||||
* [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)
|
||||
* [Pairs With Given Sum](data_structures/arrays/pairs_with_given_sum.py)
|
||||
* [Permutations](data_structures/arrays/permutations.py)
|
||||
* [Prefix Sum](data_structures/arrays/prefix_sum.py)
|
||||
* [Product Sum](data_structures/arrays/product_sum.py)
|
||||
|
@ -402,7 +398,6 @@
|
|||
|
||||
## Financial
|
||||
* [Equated Monthly Installments](financial/equated_monthly_installments.py)
|
||||
* [Exponential Moving Average](financial/exponential_moving_average.py)
|
||||
* [Interest](financial/interest.py)
|
||||
* [Present Value](financial/present_value.py)
|
||||
* [Price Plus Tax](financial/price_plus_tax.py)
|
||||
|
@ -711,7 +706,6 @@
|
|||
* [Sin](maths/sin.py)
|
||||
* [Sock Merchant](maths/sock_merchant.py)
|
||||
* [Softmax](maths/softmax.py)
|
||||
* [Solovay Strassen Primality Test](maths/solovay_strassen_primality_test.py)
|
||||
* [Square Root](maths/square_root.py)
|
||||
* [Sum Of Arithmetic Series](maths/sum_of_arithmetic_series.py)
|
||||
* [Sum Of Digits](maths/sum_of_digits.py)
|
||||
|
@ -753,7 +747,6 @@
|
|||
* [Spiral Print](matrix/spiral_print.py)
|
||||
* Tests
|
||||
* [Test Matrix Operation](matrix/tests/test_matrix_operation.py)
|
||||
* [Validate Sudoku Board](matrix/validate_sudoku_board.py)
|
||||
|
||||
## Networking Flow
|
||||
* [Ford Fulkerson](networking_flow/ford_fulkerson.py)
|
||||
|
@ -829,7 +822,6 @@
|
|||
* [Rms Speed Of Molecule](physics/rms_speed_of_molecule.py)
|
||||
* [Shear Stress](physics/shear_stress.py)
|
||||
* [Speed Of Sound](physics/speed_of_sound.py)
|
||||
* [Speeds Of Gas Molecules](physics/speeds_of_gas_molecules.py)
|
||||
|
||||
## Project Euler
|
||||
* Problem 001
|
||||
|
@ -1220,7 +1212,6 @@
|
|||
* [Capitalize](strings/capitalize.py)
|
||||
* [Check Anagrams](strings/check_anagrams.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)
|
||||
* [Dna](strings/dna.py)
|
||||
* [Edit Distance](strings/edit_distance.py)
|
||||
|
@ -1255,7 +1246,6 @@
|
|||
* [String Switch Case](strings/string_switch_case.py)
|
||||
* [Strip](strings/strip.py)
|
||||
* [Text Justification](strings/text_justification.py)
|
||||
* [Title](strings/title.py)
|
||||
* [Top K Frequent Words](strings/top_k_frequent_words.py)
|
||||
* [Upper](strings/upper.py)
|
||||
* [Wave](strings/wave.py)
|
||||
|
|
|
@ -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()
|
|
@ -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
179
graphs/check_bipatrite.py
Normal 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!")
|
Loading…
Reference in New Issue
Block a user