Skip to content

Commit 1976048

Browse files
shivaparihar6119cclausspre-commit-ci[bot]
authored
Concatenates both check bipatrite graphs(bfs&dfs) (TheAlgorithms#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 <[email protected]> Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com>
1 parent 82fc24c commit 1976048

File tree

4 files changed

+179
-157
lines changed

4 files changed

+179
-157
lines changed

DIRECTORY.md

-10
Original file line numberDiff line numberDiff line change
@@ -65,9 +65,7 @@
6565

6666
## Boolean Algebra
6767
* [And Gate](boolean_algebra/and_gate.py)
68-
* [Imply Gate](boolean_algebra/imply_gate.py)
6968
* [Nand Gate](boolean_algebra/nand_gate.py)
70-
* [Nimply Gate](boolean_algebra/nimply_gate.py)
7169
* [Nor Gate](boolean_algebra/nor_gate.py)
7270
* [Not Gate](boolean_algebra/not_gate.py)
7371
* [Or Gate](boolean_algebra/or_gate.py)
@@ -180,9 +178,7 @@
180178
## Data Structures
181179
* Arrays
182180
* [Equilibrium Index In Array](data_structures/arrays/equilibrium_index_in_array.py)
183-
* [Find Triplets With 0 Sum](data_structures/arrays/find_triplets_with_0_sum.py)
184181
* [Median Two Array](data_structures/arrays/median_two_array.py)
185-
* [Pairs With Given Sum](data_structures/arrays/pairs_with_given_sum.py)
186182
* [Permutations](data_structures/arrays/permutations.py)
187183
* [Prefix Sum](data_structures/arrays/prefix_sum.py)
188184
* [Product Sum](data_structures/arrays/product_sum.py)
@@ -402,7 +398,6 @@
402398

403399
## Financial
404400
* [Equated Monthly Installments](financial/equated_monthly_installments.py)
405-
* [Exponential Moving Average](financial/exponential_moving_average.py)
406401
* [Interest](financial/interest.py)
407402
* [Present Value](financial/present_value.py)
408403
* [Price Plus Tax](financial/price_plus_tax.py)
@@ -711,7 +706,6 @@
711706
* [Sin](maths/sin.py)
712707
* [Sock Merchant](maths/sock_merchant.py)
713708
* [Softmax](maths/softmax.py)
714-
* [Solovay Strassen Primality Test](maths/solovay_strassen_primality_test.py)
715709
* [Square Root](maths/square_root.py)
716710
* [Sum Of Arithmetic Series](maths/sum_of_arithmetic_series.py)
717711
* [Sum Of Digits](maths/sum_of_digits.py)
@@ -753,7 +747,6 @@
753747
* [Spiral Print](matrix/spiral_print.py)
754748
* Tests
755749
* [Test Matrix Operation](matrix/tests/test_matrix_operation.py)
756-
* [Validate Sudoku Board](matrix/validate_sudoku_board.py)
757750

758751
## Networking Flow
759752
* [Ford Fulkerson](networking_flow/ford_fulkerson.py)
@@ -829,7 +822,6 @@
829822
* [Rms Speed Of Molecule](physics/rms_speed_of_molecule.py)
830823
* [Shear Stress](physics/shear_stress.py)
831824
* [Speed Of Sound](physics/speed_of_sound.py)
832-
* [Speeds Of Gas Molecules](physics/speeds_of_gas_molecules.py)
833825

834826
## Project Euler
835827
* Problem 001
@@ -1220,7 +1212,6 @@
12201212
* [Capitalize](strings/capitalize.py)
12211213
* [Check Anagrams](strings/check_anagrams.py)
12221214
* [Credit Card Validator](strings/credit_card_validator.py)
1223-
* [Damerau Levenshtein Distance](strings/damerau_levenshtein_distance.py)
12241215
* [Detecting English Programmatically](strings/detecting_english_programmatically.py)
12251216
* [Dna](strings/dna.py)
12261217
* [Edit Distance](strings/edit_distance.py)
@@ -1255,7 +1246,6 @@
12551246
* [String Switch Case](strings/string_switch_case.py)
12561247
* [Strip](strings/strip.py)
12571248
* [Text Justification](strings/text_justification.py)
1258-
* [Title](strings/title.py)
12591249
* [Top K Frequent Words](strings/top_k_frequent_words.py)
12601250
* [Upper](strings/upper.py)
12611251
* [Wave](strings/wave.py)

graphs/check_bipartite_graph_bfs.py

-92
This file was deleted.

graphs/check_bipartite_graph_dfs.py

-55
This file was deleted.

graphs/check_bipatrite.py

+179
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,179 @@
1+
from collections import defaultdict, deque
2+
3+
4+
def is_bipartite_dfs(graph: defaultdict[int, list[int]]) -> bool:
5+
"""
6+
Check if a graph is bipartite using depth-first search (DFS).
7+
8+
Args:
9+
graph: Adjacency list representing the graph.
10+
11+
Returns:
12+
True if bipartite, False otherwise.
13+
14+
Checks if the graph can be divided into two sets of vertices, such that no two
15+
vertices within the same set are connected by an edge.
16+
17+
Examples:
18+
# FIXME: This test should pass.
19+
>>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]}))
20+
Traceback (most recent call last):
21+
...
22+
RuntimeError: dictionary changed size during iteration
23+
>>> is_bipartite_dfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 1]}))
24+
False
25+
>>> is_bipartite_dfs({})
26+
True
27+
>>> is_bipartite_dfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})
28+
True
29+
>>> is_bipartite_dfs({0: [1, 2, 3], 1: [0, 2], 2: [0, 1, 3], 3: [0, 2]})
30+
False
31+
>>> is_bipartite_dfs({0: [4], 1: [], 2: [4], 3: [4], 4: [0, 2, 3]})
32+
True
33+
>>> is_bipartite_dfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
34+
False
35+
>>> is_bipartite_dfs({7: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
36+
Traceback (most recent call last):
37+
...
38+
KeyError: 0
39+
40+
# FIXME: This test should fails with KeyError: 4.
41+
>>> is_bipartite_dfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 9: [0]})
42+
False
43+
>>> is_bipartite_dfs({0: [-1, 3], 1: [0, -2]})
44+
Traceback (most recent call last):
45+
...
46+
KeyError: -1
47+
>>> is_bipartite_dfs({-1: [0, 2], 0: [-1, 1], 1: [0, 2], 2: [-1, 1]})
48+
True
49+
>>> is_bipartite_dfs({0.9: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})
50+
Traceback (most recent call last):
51+
...
52+
KeyError: 0
53+
54+
# FIXME: This test should fails with TypeError: list indices must be integers or...
55+
>>> is_bipartite_dfs({0: [1.0, 3.0], 1.0: [0, 2.0], 2.0: [1.0, 3.0], 3.0: [0, 2.0]})
56+
True
57+
>>> is_bipartite_dfs({"a": [1, 3], "b": [0, 2], "c": [1, 3], "d": [0, 2]})
58+
Traceback (most recent call last):
59+
...
60+
KeyError: 1
61+
>>> is_bipartite_dfs({0: ["b", "d"], 1: ["a", "c"], 2: ["b", "d"], 3: ["a", "c"]})
62+
Traceback (most recent call last):
63+
...
64+
KeyError: 'b'
65+
"""
66+
67+
def depth_first_search(node: int, color: int) -> bool:
68+
"""
69+
Perform Depth-First Search (DFS) on the graph starting from a node.
70+
71+
Args:
72+
node: The current node being visited.
73+
color: The color assigned to the current node.
74+
75+
Returns:
76+
True if the graph is bipartite starting from the current node,
77+
False otherwise.
78+
"""
79+
if visited[node] == -1:
80+
visited[node] = color
81+
for neighbor in graph[node]:
82+
if not depth_first_search(neighbor, 1 - color):
83+
return False
84+
return visited[node] == color
85+
86+
visited: defaultdict[int, int] = defaultdict(lambda: -1)
87+
for node in graph:
88+
if visited[node] == -1 and not depth_first_search(node, 0):
89+
return False
90+
return True
91+
92+
93+
def is_bipartite_bfs(graph: defaultdict[int, list[int]]) -> bool:
94+
"""
95+
Check if a graph is bipartite using a breadth-first search (BFS).
96+
97+
Args:
98+
graph: Adjacency list representing the graph.
99+
100+
Returns:
101+
True if bipartite, False otherwise.
102+
103+
Check if the graph can be divided into two sets of vertices, such that no two
104+
vertices within the same set are connected by an edge.
105+
106+
Examples:
107+
# FIXME: This test should pass.
108+
>>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 3], 2: [0, 4]}))
109+
Traceback (most recent call last):
110+
...
111+
RuntimeError: dictionary changed size during iteration
112+
>>> is_bipartite_bfs(defaultdict(list, {0: [1, 2], 1: [0, 2], 2: [0, 1]}))
113+
False
114+
>>> is_bipartite_bfs({})
115+
True
116+
>>> is_bipartite_bfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})
117+
True
118+
>>> is_bipartite_bfs({0: [1, 2, 3], 1: [0, 2], 2: [0, 1, 3], 3: [0, 2]})
119+
False
120+
>>> is_bipartite_bfs({0: [4], 1: [], 2: [4], 3: [4], 4: [0, 2, 3]})
121+
True
122+
>>> is_bipartite_bfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
123+
False
124+
>>> is_bipartite_bfs({7: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 4: [0]})
125+
Traceback (most recent call last):
126+
...
127+
KeyError: 0
128+
129+
# FIXME: This test should fails with KeyError: 4.
130+
>>> is_bipartite_bfs({0: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2], 9: [0]})
131+
False
132+
>>> is_bipartite_bfs({0: [-1, 3], 1: [0, -2]})
133+
Traceback (most recent call last):
134+
...
135+
KeyError: -1
136+
>>> is_bipartite_bfs({-1: [0, 2], 0: [-1, 1], 1: [0, 2], 2: [-1, 1]})
137+
True
138+
>>> is_bipartite_bfs({0.9: [1, 3], 1: [0, 2], 2: [1, 3], 3: [0, 2]})
139+
Traceback (most recent call last):
140+
...
141+
KeyError: 0
142+
143+
# FIXME: This test should fails with TypeError: list indices must be integers or...
144+
>>> is_bipartite_bfs({0: [1.0, 3.0], 1.0: [0, 2.0], 2.0: [1.0, 3.0], 3.0: [0, 2.0]})
145+
True
146+
>>> is_bipartite_bfs({"a": [1, 3], "b": [0, 2], "c": [1, 3], "d": [0, 2]})
147+
Traceback (most recent call last):
148+
...
149+
KeyError: 1
150+
>>> is_bipartite_bfs({0: ["b", "d"], 1: ["a", "c"], 2: ["b", "d"], 3: ["a", "c"]})
151+
Traceback (most recent call last):
152+
...
153+
KeyError: 'b'
154+
"""
155+
visited: defaultdict[int, int] = defaultdict(lambda: -1)
156+
for node in graph:
157+
if visited[node] == -1:
158+
queue: deque[int] = deque()
159+
queue.append(node)
160+
visited[node] = 0
161+
while queue:
162+
curr_node = queue.popleft()
163+
for neighbor in graph[curr_node]:
164+
if visited[neighbor] == -1:
165+
visited[neighbor] = 1 - visited[curr_node]
166+
queue.append(neighbor)
167+
elif visited[neighbor] == visited[curr_node]:
168+
return False
169+
return True
170+
171+
172+
if __name__ == "__main":
173+
import doctest
174+
175+
result = doctest.testmod()
176+
if result.failed:
177+
print(f"{result.failed} test(s) failed.")
178+
else:
179+
print("All tests passed!")

0 commit comments

Comments
 (0)