From fa9cd031c4b614ec1ab66c7970f592659b9952bf Mon Sep 17 00:00:00 2001
From: PARIKSHIT SINGH <parikshit2111@gmail.com>
Date: Sun, 2 Mar 2025 11:02:47 +0530
Subject: [PATCH 1/5] feat: Implement Principal Component Analysis (PCA)

- Added PCA implementation with dataset standardization.
- Used Singular Value Decomposition (SVD) for computing principal components.
- Fixed import sorting to comply with PEP 8 (Ruff I001).
- Ensured type hints and docstrings for better readability.
- Added doctests to validate correctness.
- Passed all Ruff checks and automated tests.
---
 DIRECTORY.md                                  |  2 +
 .../principle_component_analysis.py           | 85 +++++++++++++++++++
 2 files changed, 87 insertions(+)
 create mode 100644 machine_learning/principle_component_analysis.py

diff --git a/DIRECTORY.md b/DIRECTORY.md
index a535f12cb59a..ab3259b9a766 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -395,6 +395,7 @@
   * [Minimum Tickets Cost](dynamic_programming/minimum_tickets_cost.py)
   * [Optimal Binary Search Tree](dynamic_programming/optimal_binary_search_tree.py)
   * [Palindrome Partitioning](dynamic_programming/palindrome_partitioning.py)
+  * [Range Sum Query](dynamic_programming/range_sum_query.py)
   * [Regex Match](dynamic_programming/regex_match.py)
   * [Rod Cutting](dynamic_programming/rod_cutting.py)
   * [Smith Waterman](dynamic_programming/smith_waterman.py)
@@ -608,6 +609,7 @@
   * [Mfcc](machine_learning/mfcc.py)
   * [Multilayer Perceptron Classifier](machine_learning/multilayer_perceptron_classifier.py)
   * [Polynomial Regression](machine_learning/polynomial_regression.py)
+  * [Principle Component Analysis](machine_learning/principle_component_analysis.py)
   * [Scoring Functions](machine_learning/scoring_functions.py)
   * [Self Organizing Map](machine_learning/self_organizing_map.py)
   * [Sequential Minimum Optimization](machine_learning/sequential_minimum_optimization.py)
diff --git a/machine_learning/principle_component_analysis.py b/machine_learning/principle_component_analysis.py
new file mode 100644
index 000000000000..46ccdb968494
--- /dev/null
+++ b/machine_learning/principle_component_analysis.py
@@ -0,0 +1,85 @@
+"""
+Principal Component Analysis (PCA) is a dimensionality reduction technique
+used in machine learning. It transforms high-dimensional data into a lower-dimensional
+representation while retaining as much variance as possible.
+
+This implementation follows best practices, including:
+- Standardizing the dataset.
+- Computing principal components using Singular Value Decomposition (SVD).
+- Returning transformed data and explained variance ratio.
+"""
+
+import doctest
+
+import numpy as np
+from sklearn.datasets import load_iris
+from sklearn.decomposition import PCA
+from sklearn.preprocessing import StandardScaler
+
+
+def collect_dataset() -> tuple[np.ndarray, np.ndarray]:
+    """
+    Collects the dataset (Iris dataset) and returns feature matrix and target values.
+
+    :return: Tuple containing feature matrix (X) and target labels (y)
+
+    Example:
+    >>> X, y = collect_dataset()
+    >>> X.shape
+    (150, 4)
+    >>> y.shape
+    (150,)
+    """
+    data = load_iris()
+    return np.array(data.data), np.array(data.target)
+
+
+def apply_pca(data_x: np.ndarray, n_components: int) -> tuple[np.ndarray, np.ndarray]:
+    """
+    Applies Principal Component Analysis (PCA) to reduce dimensionality.
+
+    :param data_x: Original dataset (features)
+    :param n_components: Number of principal components to retain
+    :return: Tuple containing transformed dataset and explained variance ratio
+
+    Example:
+    >>> X, _ = collect_dataset()
+    >>> transformed_X, variance = apply_pca(X, 2)
+    >>> transformed_X.shape
+    (150, 2)
+    >>> len(variance) == 2
+    True
+    """
+    # Standardizing the dataset
+    scaler = StandardScaler()
+    data_x_scaled = scaler.fit_transform(data_x)
+
+    # Applying PCA
+    pca = PCA(n_components=n_components)
+    principal_components = pca.fit_transform(data_x_scaled)
+
+    return principal_components, pca.explained_variance_ratio_
+
+
+def main() -> None:
+    """
+    Driver function to execute PCA and display results.
+    """
+    data_x, data_y = collect_dataset()
+
+    # Number of principal components to retain
+    n_components = 2
+
+    # Apply PCA
+    transformed_data, variance_ratio = apply_pca(data_x, n_components)
+
+    print("Transformed Dataset (First 5 rows):")
+    print(transformed_data[:5])
+
+    print("\nExplained Variance Ratio:")
+    print(variance_ratio)
+
+
+if __name__ == "__main__":
+    doctest.testmod()
+    main()

From 733a28577e5bda44216f056595501f8d1460c7a7 Mon Sep 17 00:00:00 2001
From: PARIKSHIT SINGH <90330646+parikshit2111@users.noreply.github.com>
Date: Wed, 5 Mar 2025 11:57:53 +0530
Subject: [PATCH 2/5] Collision detection (#6)

* collision_detection initial commit


---------

Co-authored-by: parikshit2111 <parikshit2111@users.noreply.github.com>
---
 DIRECTORY.md                   |  1 +
 physics/collision_detection.py | 94 ++++++++++++++++++++++++++++++++++
 requirements.txt               |  1 +
 3 files changed, 96 insertions(+)
 create mode 100644 physics/collision_detection.py

diff --git a/DIRECTORY.md b/DIRECTORY.md
index ab3259b9a766..fb1788a18d96 100644
--- a/DIRECTORY.md
+++ b/DIRECTORY.md
@@ -878,6 +878,7 @@
   * [Casimir Effect](physics/casimir_effect.py)
   * [Center Of Mass](physics/center_of_mass.py)
   * [Centripetal Force](physics/centripetal_force.py)
+  * [Collision Detection](physics/collision_detection.py)
   * [Coulombs Law](physics/coulombs_law.py)
   * [Doppler Frequency](physics/doppler_frequency.py)
   * [Grahams Law](physics/grahams_law.py)
diff --git a/physics/collision_detection.py b/physics/collision_detection.py
new file mode 100644
index 000000000000..4a0af5c004ce
--- /dev/null
+++ b/physics/collision_detection.py
@@ -0,0 +1,94 @@
+"""
+Title : AABB Collision Detection and Counter
+
+Description : This program simulates two moving boxes that bounce back when they
+collide with each other or with the edges of the screen. A collision counter
+increments each time the boxes collide, except when they touch the edges of the
+screen, where they rebound without increasing the counter. The motion and
+collision logic demonstrate axis-aligned bounding box (AABB) collision detection.
+
+The program is implemented using Pygame and features:
+- Two boxes moving towards each other
+- Collision detection between the boxes
+- Edge collision handling (without counter increment)
+- A visual counter displaying the number of collisions
+
+Source :
+- https://en.wikipedia.org/wiki/Bounding_volume
+- https://www.pygame.org/docs/
+"""
+
+import pygame
+
+# Initialize Pygame
+pygame.init()
+
+# Constants for screen dimensions and box properties
+WIDTH, HEIGHT = 500, 300  # Screen width and height
+BOX_SIZE = 50  # Size of each box
+SPEED = 3  # Speed of movement
+
+# Colors
+WHITE = (255, 255, 255)  # Background color
+RED = (255, 0, 0)  # Box 1 color
+BLUE = (0, 0, 255)  # Box 2 color
+
+# Create display window
+screen = pygame.display.set_mode((WIDTH, HEIGHT))
+pygame.display.set_caption("AABB Collision Detection")
+
+# Initial positions of the boxes
+box1_x, box1_y = 50, HEIGHT // 2 - BOX_SIZE // 2
+box2_x, box2_y = WIDTH - 100, HEIGHT // 2 - BOX_SIZE // 2
+
+# Movement directions
+box1_dir = SPEED
+box2_dir = -SPEED
+
+# Collision counter
+collision_count = 0
+
+# Main game loop
+running = True
+while running:
+    pygame.time.delay(20)  # Controls the frame rate
+    screen.fill(WHITE)  # Clear screen before drawing
+
+    # Move the boxes
+    box1_x += box1_dir
+    box2_x += box2_dir
+
+    # Collision detection between the two boxes
+    if box1_x + BOX_SIZE > box2_x:
+        # Only increase the counter if they overlap beyond just touching edges
+        if box1_x + BOX_SIZE > box2_x + 1 or box2_x > box1_x + 1:
+            collision_count += 1
+        box1_dir *= -1  # Reverse direction
+        box2_dir *= -1  # Reverse direction
+
+    # Edge collision detection (bouncing without increasing counter)
+    if box1_x <= 0 or box1_x + BOX_SIZE >= WIDTH:
+        box1_dir *= -1
+    if box2_x <= 0 or box2_x + BOX_SIZE >= WIDTH:
+        box2_dir *= -1
+
+    # Draw the boxes
+    pygame.draw.rect(screen, RED, (box1_x, box1_y, BOX_SIZE, BOX_SIZE))
+    pygame.draw.rect(screen, BLUE, (box2_x, box2_y, BOX_SIZE, BOX_SIZE))
+
+    # Display the collision count
+    font = pygame.font.Font(None, 36)
+    text = font.render("Collisions: " + str(collision_count), True, (0, 0, 0))
+    screen.blit(text, (10, 10))
+
+    # Event handling
+    for event in pygame.event.get():
+        if event.type == pygame.QUIT:
+            running = False
+            print("Number of collisions occured are",collision_count)
+
+
+    pygame.display.update()
+
+# Quit Pygame
+pygame.quit()
diff --git a/requirements.txt b/requirements.txt
index b104505e01bc..d0317bdc0ca6 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -17,3 +17,4 @@ sympy
 tweepy
 typing_extensions
 xgboost
+pygame
\ No newline at end of file

From 476f739ca8f3031e76651e1ba06f83547a4d1e19 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
 <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Wed, 5 Mar 2025 06:41:14 +0000
Subject: [PATCH 3/5] [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
---
 physics/collision_detection.py | 3 +--
 requirements.txt               | 2 +-
 2 files changed, 2 insertions(+), 3 deletions(-)

diff --git a/physics/collision_detection.py b/physics/collision_detection.py
index 4a0af5c004ce..40dcc56de688 100644
--- a/physics/collision_detection.py
+++ b/physics/collision_detection.py
@@ -85,8 +85,7 @@
     for event in pygame.event.get():
         if event.type == pygame.QUIT:
             running = False
-            print("Number of collisions occured are",collision_count)
-
+            print("Number of collisions occured are", collision_count)
 
     pygame.display.update()
 
diff --git a/requirements.txt b/requirements.txt
index d0317bdc0ca6..d52e5d155ce3 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,6 +8,7 @@ numpy
 opencv-python
 pandas
 pillow
+pygame
 requests
 rich
 scikit-learn
@@ -17,4 +18,3 @@ sympy
 tweepy
 typing_extensions
 xgboost
-pygame
\ No newline at end of file

From 0745bea3d1e8cf5a0efa91c380f38e1a1ba2678c Mon Sep 17 00:00:00 2001
From: PARIKSHIT SINGH <parikshit2111@gmail.com>
Date: Wed, 5 Mar 2025 12:12:42 +0530
Subject: [PATCH 4/5] fixed:Spelling error

---
 physics/collision_detection.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/physics/collision_detection.py b/physics/collision_detection.py
index 4a0af5c004ce..1c38bcef9b83 100644
--- a/physics/collision_detection.py
+++ b/physics/collision_detection.py
@@ -85,7 +85,7 @@
     for event in pygame.event.get():
         if event.type == pygame.QUIT:
             running = False
-            print("Number of collisions occured are",collision_count)
+            print("Number of collisions occurred are",collision_count)
 
 
     pygame.display.update()

From f4840a75729eb086c919c5ea2f45d1abf9d06879 Mon Sep 17 00:00:00 2001
From: "pre-commit-ci[bot]"
 <66853113+pre-commit-ci[bot]@users.noreply.github.com>
Date: Wed, 5 Mar 2025 06:52:50 +0000
Subject: [PATCH 5/5] [pre-commit.ci] auto fixes from pre-commit.com hooks

for more information, see https://pre-commit.ci
---
 physics/collision_detection.py | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/physics/collision_detection.py b/physics/collision_detection.py
index 868995c6833a..f0134f088a95 100644
--- a/physics/collision_detection.py
+++ b/physics/collision_detection.py
@@ -85,7 +85,7 @@
     for event in pygame.event.get():
         if event.type == pygame.QUIT:
             running = False
-            print("Number of collisions occurred are",collision_count)
+            print("Number of collisions occurred are", collision_count)
     pygame.display.update()
 
 # Quit Pygame