From 314263024d12c40aa1f36fdc9da8535502066208 Mon Sep 17 00:00:00 2001 From: Aminpatra Date: Tue, 17 Mar 2026 15:33:10 +0400 Subject: [PATCH] Add vector projection linear algebra problem --- .../189_vector_projection/description.md | 16 ++ questions/189_vector_projection/example.json | 5 + questions/189_vector_projection/learn.md | 159 ++++++++++++++++++ questions/189_vector_projection/meta.json | 15 ++ questions/189_vector_projection/solution.py | 23 +++ .../189_vector_projection/starter_code.py | 12 ++ questions/189_vector_projection/tests.json | 22 +++ 7 files changed, 252 insertions(+) create mode 100644 questions/189_vector_projection/description.md create mode 100644 questions/189_vector_projection/example.json create mode 100644 questions/189_vector_projection/learn.md create mode 100644 questions/189_vector_projection/meta.json create mode 100644 questions/189_vector_projection/solution.py create mode 100644 questions/189_vector_projection/starter_code.py create mode 100644 questions/189_vector_projection/tests.json diff --git a/questions/189_vector_projection/description.md b/questions/189_vector_projection/description.md new file mode 100644 index 00000000..282a0dd5 --- /dev/null +++ b/questions/189_vector_projection/description.md @@ -0,0 +1,16 @@ +Given two vectors `a` and `b` of the same length, compute the projection of `a` onto `b`. + +The projection is defined as: + +`proj_b(a) = (dot(a, b) / dot(b, b)) * b` + +## Input +- `a`: a list of numbers +- `b`: a list of numbers of the same length + +## Output +- a list representing the projection of `a` onto `b` + +## Notes +- If `b` is the zero vector, raise an error. +- If the vectors do not have the same length, raise an error. \ No newline at end of file diff --git a/questions/189_vector_projection/example.json b/questions/189_vector_projection/example.json new file mode 100644 index 00000000..ef1a9090 --- /dev/null +++ b/questions/189_vector_projection/example.json @@ -0,0 +1,5 @@ +{ + "input": "a = [3, 4]\nb = [1, 0]\nresult = project_vector(a, b)\nprint(result)", + "output": "[3.0, 0.0]", + "reasoning": "The vector [1, 0] points entirely along the x-axis, so projecting [3, 4] onto it keeps only the x-component. Using proj_b(a) = (dot(a, b) / dot(b, b)) * b gives [3.0, 0.0]." +} \ No newline at end of file diff --git a/questions/189_vector_projection/learn.md b/questions/189_vector_projection/learn.md new file mode 100644 index 00000000..83fa33fc --- /dev/null +++ b/questions/189_vector_projection/learn.md @@ -0,0 +1,159 @@ +## Solution Explanation + +To project a vector `a` onto another vector `b`, we want to keep only the part of `a` that points in the direction of `b`. + +In geometry, a vector can often be split into two components: + +- one component parallel to `b` +- one component perpendicular to `b` + +The projection is the parallel component. + +### Intuition + +Suppose `a` represents some movement or force, and `b` is the direction we care about. + +Projecting `a` onto `b` answers this question: + +**How much of vector `a` lies in the direction of vector `b`?** + +If `a` points strongly in the same direction as `b`, the projection will be large. +If `a` is perpendicular to `b`, the projection will be the zero vector. + +--- + +### Mathematical Formula + +The projection of `a` onto `b` is: + +`proj_b(a) = (dot(a, b) / dot(b, b)) * b` + +where: + +- `dot(a, b)` is the dot product of `a` and `b` +- `dot(b, b)` is the dot product of `b` with itself + +The term + +`dot(a, b) / dot(b, b)` + +is a scalar that tells us how much of vector `b` we need. + +Then we multiply that scalar by `b` to get the projection vector. + +--- + +### Why does this work? + +The dot product `dot(a, b)` measures how aligned the two vectors are. + +- If the vectors point in similar directions, the dot product is positive. +- If they are perpendicular, the dot product is zero. +- If they point in opposite directions, the dot product is negative. + +Dividing by `dot(b, b)` normalizes by the size of `b`, so the formula gives the correct amount of `b` needed for the projection. + +--- + +### Step-by-Step Example + +Let: + +`a = [3, 4]`, `b = [1, 0]` + +#### Step 1: Compute the dot product + +`dot(a, b) = (3)(1) + (4)(0) = 3` + +#### Step 2: Compute `dot(b, b)` + +`dot(b, b) = (1)(1) + (0)(0) = 1` + +#### Step 3: Compute the scalar factor + +`dot(a, b) / dot(b, b) = 3 / 1 = 3` + +#### Step 4: Multiply by `b` + +`3 * [1, 0] = [3, 0]` + +So the projection of `[3, 4]` onto `[1, 0]` is: + +`[3, 0]` + +This makes sense because `[1, 0]` points along the x-axis, so we keep only the x-component of `a`. + +--- + +### Another Example + +Let: + +`a = [2, 2]`, `b = [1, 1]` + +#### Step 1: Compute the dot product + +`dot(a, b) = (2)(1) + (2)(1) = 4` + +#### Step 2: Compute `dot(b, b)` + +`dot(b, b) = (1)(1) + (1)(1) = 2` + +#### Step 3: Compute the scalar factor + +`4 / 2 = 2` + +#### Step 4: Multiply by `b` + +`2 * [1, 1] = [2, 2]` + +So the projection is: + +`[2, 2]` + +This happens because `a` is already in the same direction as `b`. + +--- + +### Special Cases + +#### 1. Orthogonal vectors + +If `a` and `b` are perpendicular, then: + +`dot(a, b) = 0` + +So the projection becomes the zero vector. + +Example: + +`a = [1, 0]`, `b = [0, 1]` + +Then: + +`dot(a, b) = 0` + +So the projection is the zero vector. + +#### 2. Zero vector for `b` + +If `b` is the zero vector, then: + +`dot(b, b) = 0` + +This causes division by zero, which is undefined. + +So projection onto the zero vector is not allowed, and the function should raise an error. + +--- + +### Algorithm + +To compute the projection of `a` onto `b`: + +1. Check that both vectors have the same length. +2. Compute the dot product `dot(a, b)`. +3. Compute the dot product `dot(b, b)`. +4. If `dot(b, b) = 0`, raise an error. +5. Compute the scalar factor `dot(a, b) / dot(b, b)`. +6. Multiply every element of `b` by that scalar. \ No newline at end of file diff --git a/questions/189_vector_projection/meta.json b/questions/189_vector_projection/meta.json new file mode 100644 index 00000000..6a6af5b0 --- /dev/null +++ b/questions/189_vector_projection/meta.json @@ -0,0 +1,15 @@ +{ + "id": "189", + "title": "Project a Vector onto Another Vector", + "difficulty": "easy", + "category": "Linear Algebra", + "video": "", + "likes": "0", + "dislikes": "0", + "contributor": [ + { + "profile_link": "https://github.com/Aminpatra", + "name": "Amin Mohamed" + } + ] +} diff --git a/questions/189_vector_projection/solution.py b/questions/189_vector_projection/solution.py new file mode 100644 index 00000000..9f52cfcd --- /dev/null +++ b/questions/189_vector_projection/solution.py @@ -0,0 +1,23 @@ +def project_vector(a, b): + """ + Compute the projection of vector a onto vector b. + + Args: + a (list): A list of numbers representing the first vector. + b (list): A list of numbers representing the vector onto which a is projected. + + Returns: + list: The projection of a onto b. + + Raises: + ValueError: If the vectors do not have the same length. + ValueError: If b is the zero vector. + """ + dot_ab = sum(x * y for x, y in zip(a, b)) + dot_bb = sum(y * y for y in b) + + if dot_bb == 0: + raise ValueError("Cannot project onto the zero vector") + + scale = dot_ab / dot_bb + return [scale * y for y in b] \ No newline at end of file diff --git a/questions/189_vector_projection/starter_code.py b/questions/189_vector_projection/starter_code.py new file mode 100644 index 00000000..2fa8d323 --- /dev/null +++ b/questions/189_vector_projection/starter_code.py @@ -0,0 +1,12 @@ +def project_vector(a, b): + """ + Compute the projection of vector a onto vector b. + + Args: + a (list): A list of numbers representing the first vector. + b (list): A list of numbers representing the vector onto which a is projected. + + Returns: + list: The projection of a onto b. + """ + pass \ No newline at end of file diff --git a/questions/189_vector_projection/tests.json b/questions/189_vector_projection/tests.json new file mode 100644 index 00000000..1d80b96f --- /dev/null +++ b/questions/189_vector_projection/tests.json @@ -0,0 +1,22 @@ +[ + { + "test": "a = [3, 4]\nb = [1, 0]\nresult = project_vector(a, b)\nprint(result)", + "expected_output": "[3.0, 0.0]" + }, + { + "test": "a = [2, 2]\nb = [1, 1]\nresult = project_vector(a, b)\nprint(result)", + "expected_output": "[2.0, 2.0]" + }, + { + "test": "a = [1, 0]\nb = [0, 1]\nresult = project_vector(a, b)\nprint(result)", + "expected_output": "[0.0, 0.0]" + }, + { + "test": "a = [2, 3]\nb = [4, 0]\nresult = project_vector(a, b)\nprint(result)", + "expected_output": "[2.0, 0.0]" + }, + { + "test": "a = [1.5, 2.5]\nb = [1.0, 0.0]\nresult = project_vector(a, b)\nprint(result)", + "expected_output": "[1.5, 0.0]" + } +] \ No newline at end of file