From 868f619d32c69790889cca3d943c2bf4dfc448f0 Mon Sep 17 00:00:00 2001
From: MaximSmolskiy <mithridatus@mail.ru>
Date: Mon, 1 Apr 2024 23:58:54 +0300
Subject: [PATCH 1/4] Enable ruff SIM102 rule

---
 data_structures/arrays/sudoku_solver.py        |  5 ++---
 data_structures/stacks/balanced_parentheses.py |  5 ++---
 graphs/a_star.py                               | 13 ++++++-------
 graphs/bi_directional_dijkstra.py              |  5 ++---
 other/davis_putnam_logemann_loveland.py        |  7 +++----
 project_euler/problem_033/sol1.py              |  5 ++---
 project_euler/problem_037/sol1.py              |  3 +--
 project_euler/problem_107/sol1.py              |  7 +++----
 project_euler/problem_207/sol1.py              |  5 ++---
 pyproject.toml                                 |  1 -
 scheduling/shortest_job_first.py               |  9 ++++-----
 scripts/validate_solutions.py                  |  7 +++----
 web_programming/emails_from_url.py             | 10 ++++------
 13 files changed, 34 insertions(+), 48 deletions(-)

diff --git a/data_structures/arrays/sudoku_solver.py b/data_structures/arrays/sudoku_solver.py
index c9dffcde2379..09e51bf165e4 100644
--- a/data_structures/arrays/sudoku_solver.py
+++ b/data_structures/arrays/sudoku_solver.py
@@ -92,9 +92,8 @@ def eliminate(values, s, d):
         dplaces = [s for s in u if d in values[s]]
         if len(dplaces) == 0:
             return False  ## Contradiction: no place for this value
-        elif len(dplaces) == 1:
-            # d can only be in one place in unit; assign it there
-            if not assign(values, dplaces[0], d):
+        # d can only be in one place in unit; assign it there
+        elif len(dplaces) == 1 and not assign(values, dplaces[0], d):
                 return False
     return values
 
diff --git a/data_structures/stacks/balanced_parentheses.py b/data_structures/stacks/balanced_parentheses.py
index 3c036c220e5c..9bb61894fe4d 100644
--- a/data_structures/stacks/balanced_parentheses.py
+++ b/data_structures/stacks/balanced_parentheses.py
@@ -19,9 +19,8 @@ def balanced_parentheses(parentheses: str) -> bool:
     for bracket in parentheses:
         if bracket in bracket_pairs:
             stack.push(bracket)
-        elif bracket in (")", "]", "}"):
-            if stack.is_empty() or bracket_pairs[stack.pop()] != bracket:
-                return False
+        elif bracket in (")", "]", "}") and stack.is_empty() or bracket_pairs[stack.pop()] != bracket:
+            return False
     return stack.is_empty()
 
 
diff --git a/graphs/a_star.py b/graphs/a_star.py
index 06da3b5cd863..bade22231a45 100644
--- a/graphs/a_star.py
+++ b/graphs/a_star.py
@@ -75,13 +75,12 @@ def search(
                 for i in range(len(DIRECTIONS)):  # to try out different valid actions
                     x2 = x + DIRECTIONS[i][0]
                     y2 = y + DIRECTIONS[i][1]
-                    if x2 >= 0 and x2 < len(grid) and y2 >= 0 and y2 < len(grid[0]):
-                        if closed[x2][y2] == 0 and grid[x2][y2] == 0:
-                            g2 = g + cost
-                            f2 = g2 + heuristic[x2][y2]
-                            cell.append([f2, g2, x2, y2])
-                            closed[x2][y2] = 1
-                            action[x2][y2] = i
+                    if x2 >= 0 and x2 < len(grid) and y2 >= 0 and y2 < len(grid[0]) and closed[x2][y2] == 0 and grid[x2][y2] == 0:
+                        g2 = g + cost
+                        f2 = g2 + heuristic[x2][y2]
+                        cell.append([f2, g2, x2, y2])
+                        closed[x2][y2] = 1
+                        action[x2][y2] = i
     invpath = []
     x = goal[0]
     y = goal[1]
diff --git a/graphs/bi_directional_dijkstra.py b/graphs/bi_directional_dijkstra.py
index 7b9eac6c8587..8d2506cce87a 100644
--- a/graphs/bi_directional_dijkstra.py
+++ b/graphs/bi_directional_dijkstra.py
@@ -36,9 +36,8 @@ def pass_and_relaxation(
             queue.put((new_cost_f, nxt))
             cst_fwd[nxt] = new_cost_f
             parent[nxt] = v
-        if nxt in visited_backward:
-            if cst_fwd[v] + d + cst_bwd[nxt] < shortest_distance:
-                shortest_distance = cst_fwd[v] + d + cst_bwd[nxt]
+        if nxt in visited_backward and cst_fwd[v] + d + cst_bwd[nxt] < shortest_distance:
+            shortest_distance = cst_fwd[v] + d + cst_bwd[nxt]
     return shortest_distance
 
 
diff --git a/other/davis_putnam_logemann_loveland.py b/other/davis_putnam_logemann_loveland.py
index 5c6e2d9ffd5e..3a76f3dfef08 100644
--- a/other/davis_putnam_logemann_loveland.py
+++ b/other/davis_putnam_logemann_loveland.py
@@ -64,10 +64,9 @@ def assign(self, model: dict[str, bool | None]) -> None:
                 value = model[symbol]
             else:
                 continue
-            if value is not None:
-                # Complement assignment if literal is in complemented form
-                if literal.endswith("'"):
-                    value = not value
+            # Complement assignment if literal is in complemented form
+            if value is not None and literal.endswith("'"):
+                value = not value
             self.literals[literal] = value
 
     def evaluate(self, model: dict[str, bool | None]) -> bool | None:
diff --git a/project_euler/problem_033/sol1.py b/project_euler/problem_033/sol1.py
index 187fd61bde6c..ce4af76605be 100644
--- a/project_euler/problem_033/sol1.py
+++ b/project_euler/problem_033/sol1.py
@@ -44,9 +44,8 @@ def fraction_list(digit_len: int) -> list[str]:
     last_digit = int("1" + "0" * digit_len)
     for num in range(den, last_digit):
         while den <= 99:
-            if (num != den) and (num % 10 == den // 10) and (den % 10 != 0):
-                if is_digit_cancelling(num, den):
-                    solutions.append(f"{num}/{den}")
+            if (num != den) and (num % 10 == den // 10) and (den % 10 != 0) and is_digit_cancelling(num, den):
+                solutions.append(f"{num}/{den}")
             den += 1
         num += 1
         den = 10
diff --git a/project_euler/problem_037/sol1.py b/project_euler/problem_037/sol1.py
index ef7686cbcb96..a3bf7ed151d0 100644
--- a/project_euler/problem_037/sol1.py
+++ b/project_euler/problem_037/sol1.py
@@ -85,8 +85,7 @@ def validate(n: int) -> bool:
     >>> validate(3797)
     True
     """
-    if len(str(n)) > 3:
-        if not is_prime(int(str(n)[-3:])) or not is_prime(int(str(n)[:3])):
+    if len(str(n)) > 3 and (not is_prime(int(str(n)[-3:])) or not is_prime(int(str(n)[:3]))):
             return False
     return True
 
diff --git a/project_euler/problem_107/sol1.py b/project_euler/problem_107/sol1.py
index 3fe75909e2ea..cd020b5af64e 100644
--- a/project_euler/problem_107/sol1.py
+++ b/project_euler/problem_107/sol1.py
@@ -81,10 +81,9 @@ def prims_algorithm(self) -> Graph:
         while len(subgraph.vertices) < len(self.vertices):
             min_weight = max(self.edges.values()) + 1
             for edge, weight in self.edges.items():
-                if (edge[0] in subgraph.vertices) ^ (edge[1] in subgraph.vertices):
-                    if weight < min_weight:
-                        min_edge = edge
-                        min_weight = weight
+                if (edge[0] in subgraph.vertices) ^ (edge[1] in subgraph.vertices) and weight < min_weight:
+                    min_edge = edge
+                    min_weight = weight
 
             subgraph.add_edge(min_edge, min_weight)
 
diff --git a/project_euler/problem_207/sol1.py b/project_euler/problem_207/sol1.py
index 2b3591f51cfa..99d3e5f0276e 100644
--- a/project_euler/problem_207/sol1.py
+++ b/project_euler/problem_207/sol1.py
@@ -88,9 +88,8 @@ def solution(max_proportion: float = 1 / 12345) -> int:
             total_partitions += 1
             if check_partition_perfect(partition_candidate):
                 perfect_partitions += 1
-        if perfect_partitions > 0:
-            if perfect_partitions / total_partitions < max_proportion:
-                return int(partition_candidate)
+        if perfect_partitions > 0 and perfect_partitions / total_partitions < max_proportion:
+            return int(partition_candidate)
         integer += 1
 
 
diff --git a/pyproject.toml b/pyproject.toml
index 50cd38005f09..e3cf42c92c54 100644
--- a/pyproject.toml
+++ b/pyproject.toml
@@ -18,7 +18,6 @@ lint.ignore = [    # `ruff rule S101` for a description of that rule
   "S105",     # Possible hardcoded password: 'password'
   "S113",     # Probable use of requests call without timeout -- FIX ME
   "S311",     # Standard pseudo-random generators are not suitable for cryptographic purposes -- FIX ME
-  "SIM102",   # Use a single `if` statement instead of nested `if` statements -- FIX ME
   "SLF001",   # Private member accessed: `_Iterator` -- FIX ME
   "UP038",    # Use `X | Y` in `{}` call instead of `(X, Y)` -- DO NOT FIX
 ]
diff --git a/scheduling/shortest_job_first.py b/scheduling/shortest_job_first.py
index cfd0417ea62d..8118fbb4bf55 100644
--- a/scheduling/shortest_job_first.py
+++ b/scheduling/shortest_job_first.py
@@ -37,11 +37,10 @@ def calculate_waitingtime(
     # Process until all processes are completed
     while complete != no_of_processes:
         for j in range(no_of_processes):
-            if arrival_time[j] <= increment_time and remaining_time[j] > 0:
-                if remaining_time[j] < minm:
-                    minm = remaining_time[j]
-                    short = j
-                    check = True
+            if arrival_time[j] <= increment_time and remaining_time[j] > 0 and remaining_time[j] < minm:
+                minm = remaining_time[j]
+                short = j
+                check = True
 
         if not check:
             increment_time += 1
diff --git a/scripts/validate_solutions.py b/scripts/validate_solutions.py
index ca4af5261a8f..7e2bb886b144 100755
--- a/scripts/validate_solutions.py
+++ b/scripts/validate_solutions.py
@@ -71,10 +71,9 @@ def added_solution_file_path() -> list[pathlib.Path]:
 
 
 def collect_solution_file_paths() -> list[pathlib.Path]:
-    if os.environ.get("CI") and os.environ.get("GITHUB_EVENT_NAME") == "pull_request":
-        # Return only if there are any, otherwise default to all solutions
-        if filepaths := added_solution_file_path():
-            return filepaths
+    # Return only if there are any, otherwise default to all solutions
+    if os.environ.get("CI") and os.environ.get("GITHUB_EVENT_NAME") == "pull_request" and (filepaths := added_solution_file_path()):
+        return filepaths
     return all_solution_file_paths()
 
 
diff --git a/web_programming/emails_from_url.py b/web_programming/emails_from_url.py
index 6b4bacfe7d5a..17b504983b10 100644
--- a/web_programming/emails_from_url.py
+++ b/web_programming/emails_from_url.py
@@ -30,12 +30,10 @@ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None
         if tag == "a":
             # Check the list of defined attributes.
             for name, value in attrs:
-                # If href is defined, and not empty nor # print it.
-                if name == "href" and value != "#" and value != "":
-                    # If not already in urls.
-                    if value not in self.urls:
-                        url = parse.urljoin(self.domain, value)
-                        self.urls.append(url)
+                # If href is defined, not empty nor # print it and not already in urls.
+                if name == "href" and value != "#" and value != "" and value not in self.urls:
+                    url = parse.urljoin(self.domain, value)
+                    self.urls.append(url)
 
 
 # Get main domain name (example.com)

From 3e3075134326451e97a526f709aee139f5c94165 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
 <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Mon, 1 Apr 2024 20:59:49 +0000
Subject: [PATCH 2/4] [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
---
 data_structures/arrays/sudoku_solver.py        | 2 +-
 data_structures/stacks/balanced_parentheses.py | 6 +++++-
 graphs/a_star.py                               | 9 ++++++++-
 graphs/bi_directional_dijkstra.py              | 5 ++++-
 project_euler/problem_033/sol1.py              | 7 ++++++-
 project_euler/problem_037/sol1.py              | 6 ++++--
 project_euler/problem_107/sol1.py              | 4 +++-
 project_euler/problem_207/sol1.py              | 5 ++++-
 scheduling/shortest_job_first.py               | 6 +++++-
 scripts/validate_solutions.py                  | 6 +++++-
 web_programming/emails_from_url.py             | 7 ++++++-
 11 files changed, 51 insertions(+), 12 deletions(-)

diff --git a/data_structures/arrays/sudoku_solver.py b/data_structures/arrays/sudoku_solver.py
index 09e51bf165e4..5c1cff06f9d4 100644
--- a/data_structures/arrays/sudoku_solver.py
+++ b/data_structures/arrays/sudoku_solver.py
@@ -94,7 +94,7 @@ def eliminate(values, s, d):
             return False  ## Contradiction: no place for this value
         # d can only be in one place in unit; assign it there
         elif len(dplaces) == 1 and not assign(values, dplaces[0], d):
-                return False
+            return False
     return values
 
 
diff --git a/data_structures/stacks/balanced_parentheses.py b/data_structures/stacks/balanced_parentheses.py
index 9bb61894fe4d..2c19bc14e1b0 100644
--- a/data_structures/stacks/balanced_parentheses.py
+++ b/data_structures/stacks/balanced_parentheses.py
@@ -19,7 +19,11 @@ def balanced_parentheses(parentheses: str) -> bool:
     for bracket in parentheses:
         if bracket in bracket_pairs:
             stack.push(bracket)
-        elif bracket in (")", "]", "}") and stack.is_empty() or bracket_pairs[stack.pop()] != bracket:
+        elif (
+            bracket in (")", "]", "}")
+            and stack.is_empty()
+            or bracket_pairs[stack.pop()] != bracket
+        ):
             return False
     return stack.is_empty()
 
diff --git a/graphs/a_star.py b/graphs/a_star.py
index bade22231a45..1d7063ccc55a 100644
--- a/graphs/a_star.py
+++ b/graphs/a_star.py
@@ -75,7 +75,14 @@ def search(
                 for i in range(len(DIRECTIONS)):  # to try out different valid actions
                     x2 = x + DIRECTIONS[i][0]
                     y2 = y + DIRECTIONS[i][1]
-                    if x2 >= 0 and x2 < len(grid) and y2 >= 0 and y2 < len(grid[0]) and closed[x2][y2] == 0 and grid[x2][y2] == 0:
+                    if (
+                        x2 >= 0
+                        and x2 < len(grid)
+                        and y2 >= 0
+                        and y2 < len(grid[0])
+                        and closed[x2][y2] == 0
+                        and grid[x2][y2] == 0
+                    ):
                         g2 = g + cost
                         f2 = g2 + heuristic[x2][y2]
                         cell.append([f2, g2, x2, y2])
diff --git a/graphs/bi_directional_dijkstra.py b/graphs/bi_directional_dijkstra.py
index 8d2506cce87a..d2c4030b921b 100644
--- a/graphs/bi_directional_dijkstra.py
+++ b/graphs/bi_directional_dijkstra.py
@@ -36,7 +36,10 @@ def pass_and_relaxation(
             queue.put((new_cost_f, nxt))
             cst_fwd[nxt] = new_cost_f
             parent[nxt] = v
-        if nxt in visited_backward and cst_fwd[v] + d + cst_bwd[nxt] < shortest_distance:
+        if (
+            nxt in visited_backward
+            and cst_fwd[v] + d + cst_bwd[nxt] < shortest_distance
+        ):
             shortest_distance = cst_fwd[v] + d + cst_bwd[nxt]
     return shortest_distance
 
diff --git a/project_euler/problem_033/sol1.py b/project_euler/problem_033/sol1.py
index ce4af76605be..71790d34fbed 100644
--- a/project_euler/problem_033/sol1.py
+++ b/project_euler/problem_033/sol1.py
@@ -44,7 +44,12 @@ def fraction_list(digit_len: int) -> list[str]:
     last_digit = int("1" + "0" * digit_len)
     for num in range(den, last_digit):
         while den <= 99:
-            if (num != den) and (num % 10 == den // 10) and (den % 10 != 0) and is_digit_cancelling(num, den):
+            if (
+                (num != den)
+                and (num % 10 == den // 10)
+                and (den % 10 != 0)
+                and is_digit_cancelling(num, den)
+            ):
                 solutions.append(f"{num}/{den}")
             den += 1
         num += 1
diff --git a/project_euler/problem_037/sol1.py b/project_euler/problem_037/sol1.py
index a3bf7ed151d0..9c09065f4bd0 100644
--- a/project_euler/problem_037/sol1.py
+++ b/project_euler/problem_037/sol1.py
@@ -85,8 +85,10 @@ def validate(n: int) -> bool:
     >>> validate(3797)
     True
     """
-    if len(str(n)) > 3 and (not is_prime(int(str(n)[-3:])) or not is_prime(int(str(n)[:3]))):
-            return False
+    if len(str(n)) > 3 and (
+        not is_prime(int(str(n)[-3:])) or not is_prime(int(str(n)[:3]))
+    ):
+        return False
     return True
 
 
diff --git a/project_euler/problem_107/sol1.py b/project_euler/problem_107/sol1.py
index cd020b5af64e..79cdd937042e 100644
--- a/project_euler/problem_107/sol1.py
+++ b/project_euler/problem_107/sol1.py
@@ -81,7 +81,9 @@ def prims_algorithm(self) -> Graph:
         while len(subgraph.vertices) < len(self.vertices):
             min_weight = max(self.edges.values()) + 1
             for edge, weight in self.edges.items():
-                if (edge[0] in subgraph.vertices) ^ (edge[1] in subgraph.vertices) and weight < min_weight:
+                if (edge[0] in subgraph.vertices) ^ (
+                    edge[1] in subgraph.vertices
+                ) and weight < min_weight:
                     min_edge = edge
                     min_weight = weight
 
diff --git a/project_euler/problem_207/sol1.py b/project_euler/problem_207/sol1.py
index 99d3e5f0276e..c83dc1d4aaef 100644
--- a/project_euler/problem_207/sol1.py
+++ b/project_euler/problem_207/sol1.py
@@ -88,7 +88,10 @@ def solution(max_proportion: float = 1 / 12345) -> int:
             total_partitions += 1
             if check_partition_perfect(partition_candidate):
                 perfect_partitions += 1
-        if perfect_partitions > 0 and perfect_partitions / total_partitions < max_proportion:
+        if (
+            perfect_partitions > 0
+            and perfect_partitions / total_partitions < max_proportion
+        ):
             return int(partition_candidate)
         integer += 1
 
diff --git a/scheduling/shortest_job_first.py b/scheduling/shortest_job_first.py
index 8118fbb4bf55..6899ec87c591 100644
--- a/scheduling/shortest_job_first.py
+++ b/scheduling/shortest_job_first.py
@@ -37,7 +37,11 @@ def calculate_waitingtime(
     # Process until all processes are completed
     while complete != no_of_processes:
         for j in range(no_of_processes):
-            if arrival_time[j] <= increment_time and remaining_time[j] > 0 and remaining_time[j] < minm:
+            if (
+                arrival_time[j] <= increment_time
+                and remaining_time[j] > 0
+                and remaining_time[j] < minm
+            ):
                 minm = remaining_time[j]
                 short = j
                 check = True
diff --git a/scripts/validate_solutions.py b/scripts/validate_solutions.py
index 7e2bb886b144..0afbdde315c7 100755
--- a/scripts/validate_solutions.py
+++ b/scripts/validate_solutions.py
@@ -72,7 +72,11 @@ def added_solution_file_path() -> list[pathlib.Path]:
 
 def collect_solution_file_paths() -> list[pathlib.Path]:
     # Return only if there are any, otherwise default to all solutions
-    if os.environ.get("CI") and os.environ.get("GITHUB_EVENT_NAME") == "pull_request" and (filepaths := added_solution_file_path()):
+    if (
+        os.environ.get("CI")
+        and os.environ.get("GITHUB_EVENT_NAME") == "pull_request"
+        and (filepaths := added_solution_file_path())
+    ):
         return filepaths
     return all_solution_file_paths()
 
diff --git a/web_programming/emails_from_url.py b/web_programming/emails_from_url.py
index 17b504983b10..26c88e1b13a5 100644
--- a/web_programming/emails_from_url.py
+++ b/web_programming/emails_from_url.py
@@ -31,7 +31,12 @@ def handle_starttag(self, tag: str, attrs: list[tuple[str, str | None]]) -> None
             # Check the list of defined attributes.
             for name, value in attrs:
                 # If href is defined, not empty nor # print it and not already in urls.
-                if name == "href" and value != "#" and value != "" and value not in self.urls:
+                if (
+                    name == "href"
+                    and value != "#"
+                    and value != ""
+                    and value not in self.urls
+                ):
                     url = parse.urljoin(self.domain, value)
                     self.urls.append(url)
 

From a0f8b6fba7dc80be9f87ade6373fdb71c5522db0 Mon Sep 17 00:00:00 2001
From: MaximSmolskiy <mithridatus@mail.ru>
Date: Tue, 2 Apr 2024 00:09:10 +0300
Subject: [PATCH 3/4] Fix

---
 data_structures/stacks/balanced_parentheses.py | 6 +-----
 1 file changed, 1 insertion(+), 5 deletions(-)

diff --git a/data_structures/stacks/balanced_parentheses.py b/data_structures/stacks/balanced_parentheses.py
index 2c19bc14e1b0..6f9d92b55069 100644
--- a/data_structures/stacks/balanced_parentheses.py
+++ b/data_structures/stacks/balanced_parentheses.py
@@ -19,11 +19,7 @@ def balanced_parentheses(parentheses: str) -> bool:
     for bracket in parentheses:
         if bracket in bracket_pairs:
             stack.push(bracket)
-        elif (
-            bracket in (")", "]", "}")
-            and stack.is_empty()
-            or bracket_pairs[stack.pop()] != bracket
-        ):
+        elif bracket in (")", "]", "}") and (stack.is_empty() or bracket_pairs[stack.pop()] != bracket):
             return False
     return stack.is_empty()
 

From 1e0d57c710e7e0b008548b5708f01eff38511674 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
 <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Mon, 1 Apr 2024 21:09:33 +0000
Subject: [PATCH 4/4] [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
---
 data_structures/stacks/balanced_parentheses.py | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

diff --git a/data_structures/stacks/balanced_parentheses.py b/data_structures/stacks/balanced_parentheses.py
index 6f9d92b55069..928815bb2111 100644
--- a/data_structures/stacks/balanced_parentheses.py
+++ b/data_structures/stacks/balanced_parentheses.py
@@ -19,7 +19,9 @@ def balanced_parentheses(parentheses: str) -> bool:
     for bracket in parentheses:
         if bracket in bracket_pairs:
             stack.push(bracket)
-        elif bracket in (")", "]", "}") and (stack.is_empty() or bracket_pairs[stack.pop()] != bracket):
+        elif bracket in (")", "]", "}") and (
+            stack.is_empty() or bracket_pairs[stack.pop()] != bracket
+        ):
             return False
     return stack.is_empty()