+
+Within the `Vector` class, create an `__init__` method and give it three parameters, `self`, `x`, and `y`.
+
+# --hints--
+
+You should define an `__init__` method inside the `Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").has_function("__init__")`)) })
+```
+
+Your `__init__` method should take three parameters: `self`, `x`, and `y`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").find_function("__init__").has_args("self, x, y")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ pass
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
new file mode 100644
index 00000000000..62ab349a8db
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
@@ -0,0 +1,38 @@
+---
+id: 65f055b9190fc41ca35549b8
+title: Step 3
+challengeType: 20
+dashedName: step-3
+---
+
+# --description--
+
+Python offers various methods that include both a leading and trailing double underscore in their names. You may already be familiar with some, such as `__init__` and `__str__`. These methods, which follow the `__
+
+So far, you created a 2-dimensional vector. You want to be able to represent vectors with a different number of dimensions without rewriting the necessary code for each specific case. For that, you will use inheritance.
+
+Start by renaming the `Vector` class into `R2Vector` to specify that this class is going to deal with 2-dimensional vectors. Remember to modify the instantiation of `v1`, too.
+
+# --hints--
+
+You should rename the `Vector` class into `R2Vector`. Remember to modify the instantiation of `v1`, too.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+v1 = Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
new file mode 100644
index 00000000000..e26a20b0730
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
@@ -0,0 +1,70 @@
+---
+id: 65f40051d6b09a139f253e8e
+title: Step 12
+challengeType: 20
+dashedName: step-12
+---
+
+# --description--
+
+Inheritance enables you to define a class from an existing one. The new class, called child, inherits all the methods and properties of the existing class, called parent.
+
+```py
+class Tree:
+ def sprout(self):
+ print('Making new leaves!')
+
+class Oak(Tree):
+ pass
+
+Oak().sprout() # Output: Making new leaves!
+```
+
+In the example above, the child class `Oak` inherits from `Tree` and inherits the `sprout` method from the parent class `Tree`.
+
+Create a new class named `R3Vector` and follow the example above to make it inherit from the `R2Vector` class.
+
+# --hints--
+
+You should define a new class `R3Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R3Vector")
+ `))
+})
+```
+
+Your new class `R3Vector` should inherit from `R2Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").inherits_from("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
new file mode 100644
index 00000000000..c50cbefeb4a
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
@@ -0,0 +1,56 @@
+---
+id: 65f40401e6ef53173c04e27d
+title: Step 13
+challengeType: 20
+dashedName: step-13
+---
+
+# --description--
+
+Within your new class, declare an `__init__` method. Give it `self`, `x`, `y`, and `z` as the parameters.
+
+# --hints--
+
+You should define an `__init__` method inside your `R3Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").has_function("__init__")
+ `))
+})
+```
+
+Your `__init__` method should have four parameters `self`, `x`, `y`, and `z`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, x, y, z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
new file mode 100644
index 00000000000..cb7a33c0eb1
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
@@ -0,0 +1,49 @@
+---
+id: 65f407ea37ad6e181b90462e
+title: Step 14
+challengeType: 20
+dashedName: step-14
+---
+
+# --description--
+
+You could assign each `i` parameter to `self.i` as you did before. Although in this case you have few lines to repeat, one way to avoid this repetition is using the `super()` function. `super()` enables you to refer implicitly to the parent class: `super().__init__(x, y)` calls the `__init__` method of the parent class.
+
+Add a `super().__init__(x, y)` call to your `__init__` method.
+
+# --hints--
+
+You should have a `super().__init__(x, y)` call in your `__init__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_stmt("super().__init__(x, y)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
new file mode 100644
index 00000000000..caf708394fc
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
@@ -0,0 +1,47 @@
+---
+id: 65f40f8af784751c613d638a
+title: Step 15
+challengeType: 20
+dashedName: step-15
+---
+
+# --description--
+
+Now, you need to assign `z` to the `z` attribute of your `R3Vector` object.
+
+# --hints--
+
+You should assign `z` to `self.z` after the `super` call.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").is_ordered("super().__init__(x, y)", "self.z = z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
new file mode 100644
index 00000000000..68340ee6c11
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
@@ -0,0 +1,47 @@
+---
+id: 65f40fdb3579aa1ced28b2eb
+title: Step 16
+challengeType: 20
+dashedName: step-16
+---
+
+# --description--
+
+Create an `R3Vector` instance with `2`, `2`, and `3` as the values of `x`, `y`, and `z`, respectively. Assign the new instance to `v2`.
+
+# --hints--
+
+You should declare a variable `v2` and assign it `R3Vector(2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(2, 2, 3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
new file mode 100644
index 00000000000..06b727e3b29
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
@@ -0,0 +1,72 @@
+---
+id: 65f412c208c3791fee305acf
+title: Step 17
+challengeType: 20
+dashedName: step-17
+---
+
+# --description--
+
+In Python, you can enforce the use of keyword-only arguments by adding a `*` as an additional argument to the function or method signature. Modify both `__init__` methods by adding a `*` as the second parameter (after `self`). Every parameter placed after that will require the use of a keyword argument in the function/method call.
+
+This means that you need to modify the `super().__init__(x, y)` call, too. Do it by giving `x` the value `x`, and `y` the value `y`.
+
+Finally, modify the instantiation of `v1` and `v2` by using keyword arguments.
+
+# --hints--
+
+You should enforce keyword arguments by adding a `*` as the second parameter in both your `__init__` methods.
+
+```js
+({ test: () => {
+ assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__init__").has_args("self, *, x, y")`));
+ assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, *, x, y, z")`));
+} })
+```
+
+You should modify your `super.__init__(x, y)` call to use keyword arguments.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").find_body().is_equivalent("super().__init__(x=x, y=y)\\nself.z = z")`)) })
+```
+
+You should modify the assignment of `v1` to be `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R2Vector(x=2, y=3)")`)) })
+```
+
+You should modify the assignment of `v2` to be `R3Vector(x=2, y=2, z=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=2, y=2, z=3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+v2 = R3Vector(2, 2, 3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
new file mode 100644
index 00000000000..ef31cdd6194
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
@@ -0,0 +1,64 @@
+---
+id: 65f4148dea0f802040225e0c
+title: Step 18
+challengeType: 20
+dashedName: step-18
+---
+
+# --description--
+
+Remove the existing `print` calls. Then, as you did before for `v1`, print `v2` and the value returned by `v2.norm()`.
+
+# --hints--
+
+You should not have `print(v1)` and `print(v1.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1.norm())")`));
+ }
+})
+```
+
+You should print `v2` and `v2.norm()`.
+
+```js
+({
+ test: () => {
+ assert(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+print(v1.norm())
+print(v1)
+
+v2 = R3Vector(x=2, y=2, z=3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
new file mode 100644
index 00000000000..1a83f17e994
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
@@ -0,0 +1,64 @@
+---
+id: 65f4520e363e2642f8112e33
+title: Step 19
+challengeType: 20
+dashedName: step-19
+---
+
+# --description--
+
+As you can see, something is not quite right. The `norm` and `__str__` methods inherited from `R2Vector` cannot adapt to a 3-dimensional vector. Their implementation has to be more flexible.
+
+Every object in Python has a special attribute named `__dict__`, which is a dictionary that stores the object attributes.
+
+Remove the existing `print` calls. Then, print the `__dict__` attribute of your `v1` and `v2` vectors to see what they look like.
+
+# --hints--
+
+You should not have `print(v2)` and `print(v2.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+You should print the `__dict__` attribute of `v1` and `v2`.
+
+```js
+({ test: () => assert(runPython(`
+(_Node(_code).has_call("print(v1.__dict__)") and _Node(_code).has_call("print(v2.__dict__)")) or _Node(_code).has_call("print(v1.__dict__, v2.__dict__)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v2.norm())
+print(v2)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
new file mode 100644
index 00000000000..2a2c8f28376
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
@@ -0,0 +1,49 @@
+---
+id: 65f4535bbdb28d436ff3ddc9
+title: Step 20
+challengeType: 20
+dashedName: step-20
+---
+
+# --description--
+
+As you can see from the output, `__dict__` contains the values of your instance attributes. Instead of explicitly adding the squares of `self.x` and `self.y`, you are going to iterate over the values stored in `__dict__` to calculate the value of the norm.
+
+Within the `norm` method body, replace the content of the parentheses with a generator expression that elevates each value `val` in `self.__dict__.values()` to the power of `2`. Also, pass that generator expression as the argument to the `sum` function, so that all the squares are added together before calculating the square root.
+
+# --hints--
+
+You should return `sum(val**2 for val in self.__dict__.values())**0.5` from `norm()` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in self.__dict__.values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
new file mode 100644
index 00000000000..bbb82436c52
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
@@ -0,0 +1,53 @@
+---
+id: 65f870003444fb1a2ad171f2
+title: Step 21
+challengeType: 20
+dashedName: step-21
+---
+
+# --description--
+
+Modify the two `print` calls to print the norm of your vectors and verify that the `norm()` method works fine.
+
+# --hints--
+
+You should print `v1.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1.norm())")`)) })
+```
+
+You should print `v2.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v2.norm())")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
new file mode 100644
index 00000000000..22e3cab792e
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
@@ -0,0 +1,61 @@
+---
+id: 65f8709620b2ce1a62608f5a
+title: Step 23
+challengeType: 20
+dashedName: step-23
+---
+
+# --description--
+
+When you need to dynamically access some attributes starting from a string input, the built-in `getattr()` function is what you need. It takes an object as its first argument, and a string containing the attribute name as its second attribute.
+
+Start to fix the `__str__` method by replacing the string returned by `__str__()` with a generator expression that iterates through the object attributes and calls `getattr()` for each attribute `i`.
+
+# --hints--
+
+You should return a generator expression that iterates over `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_iters()[0].is_equivalent("vars(self)")`)) })
+```
+
+You should return a generator expression that uses `i` as the iteration variable.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_targets()[0].is_equivalent("i")`)) })
+```
+
+You should return a generator expression that calls `getattr(self, i)` for each item `i` in `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_expr().is_equivalent("getattr(self, i)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
new file mode 100644
index 00000000000..668bd89de56
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
@@ -0,0 +1,47 @@
+---
+id: 65f8720685ec351abef26740
+title: Step 24
+challengeType: 20
+dashedName: step-24
+---
+
+# --description--
+
+To obtain a proper string representation, call the `tuple()` constructor and pass it the generator expression you wrote in the previous step as the argument.
+
+# --hints--
+
+You should pass the expression returned by the `__str__` method to the `tuple()` constructor.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("tuple(getattr(self, i) for i in vars(self))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return (getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
new file mode 100644
index 00000000000..789f37ee6fe
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
@@ -0,0 +1,47 @@
+---
+id: 65f872a0fe6aa21b456ad4fe
+title: Step 25
+challengeType: 20
+dashedName: step-25
+---
+
+# --description--
+
+Finally, pass the `tuple()` call as the argument to the `str()` function.
+
+# --hints--
+
+You should pass the `tuple()` call you are currently returning from the `__str__` method to the `str()` function.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("str(tuple(getattr(self, i) for i in vars(self)))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return tuple(getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
new file mode 100644
index 00000000000..6a2c44baef5
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
@@ -0,0 +1,56 @@
+---
+id: 65f8749b13774b1d2e4a7fba
+title: Step 27
+challengeType: 20
+dashedName: step-27
+---
+
+# --description--
+
+While the `__str__` method returns a human-readable string representation of an object, the `__repr__` method is supposed to return the string needed to instantiate the object.
+
+Add a `__repr__` method with a `self` parameter within the `R2Vector` class.
+
+# --hints--
+
+Your `R2Vector` class should have a `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__repr__")`)) })
+```
+
+Your `__repr__` method should have a `self` parameter.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_args("self")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
new file mode 100644
index 00000000000..7f5a3e0f9c9
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
@@ -0,0 +1,74 @@
+---
+id: 65f876d17832001e8e1abb05
+title: Step 28
+challengeType: 20
+dashedName: step-28
+---
+
+# --description--
+
+Declare a variable `arg_list`. Give it the value of a list comprehension that iterates over `key` and `val` for each key-value pair in `vars(self).items()` and computes the f-string `f'{key}={val}'` at each iteration.
+
+# --hints--
+
+You should declare a variable `arg_list`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_variable("arg_list")`)) })
+```
+
+You should assign a list comprehension that iterates over `vars(self).items()` to `arg_list`.
+
+```js
+({ test: () => runPython(`
+import ast
+var = _Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list")
+assert isinstance(var.tree.value, ast.ListComp), "Expected arg_list to be a list comprehension"
+assert (actual := var.find_comp_iters()[0].is_equivalent("vars(self).items()")), f"Expected vars(self).items(), got {actual}"
+`) })
+```
+
+The list comprehension assigned to `arg_list` should use `key` and `val` to iterate over `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_targets()[0].is_equivalent("key, val")
+`)) })
+```
+
+The list comprehension assigned to `arg_list` should compute the string `f'{key}={val}'` for each key-value pair in `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_expr().is_equivalent("f'{key}={val}'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
new file mode 100644
index 00000000000..0c56316394e
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
@@ -0,0 +1,50 @@
+---
+id: 65f93acbb514857003510e79
+title: Step 29
+challengeType: 20
+dashedName: step-29
+---
+
+# --description--
+
+Declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+# --hints--
+
+You should declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("args").is_equivalent("args = ', '.join(arg_list)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
new file mode 100644
index 00000000000..e826611fa57
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
@@ -0,0 +1,52 @@
+---
+id: 65f93b67169a9c703264458a
+title: Step 30
+challengeType: 20
+dashedName: step-30
+---
+
+# --description--
+
+Since the method should return the string to instantiate the object for `R2Vector` as well as `R3Vector` when inherited, you cannot build the string specifying the class name.
+
+You can access the name of a class with `__class__.__name__`. Add a `return` statement to the `__repr__` method and return the string necessary to instantiate the object.
+
+# --hints--
+
+You should use `__class__.__name__` to build the f-string needed to instantiate a vector object and return it from the `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_return("f'{self.__class__.__name__}({args})'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
new file mode 100644
index 00000000000..13682539c2c
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
@@ -0,0 +1,57 @@
+---
+id: 65f93d4647ce2670dc6f095c
+title: Step 31
+challengeType: 20
+dashedName: step-31
+---
+
+# --description--
+
+The `__repr__` method is called under the hood by the `repr` function. Verify that `__repr__` works properly by adding `f'\nrepr = {repr(v1)}'` and `f'\nrepr = {repr(v2)}'` as the second argument to your first and second `print` calls, respectively.
+
+# --hints--
+
+You should add `f'\nrepr = {repr(v1)}'` as the second argument to your `print(f'v1 = {v1}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}', f'\\\\nrepr = {repr(v1)}')")`)) })
+```
+
+You should add `f'\nrepr = {repr(v2)}'` as the second argument to your `print(f'v2 = {v2}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}', f'\\\\nrepr = {repr(v2)}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
new file mode 100644
index 00000000000..a25da243ba9
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
@@ -0,0 +1,56 @@
+---
+id: 65f93e54a9121571dcdd3e79
+title: Step 32
+challengeType: 20
+dashedName: step-32
+---
+
+# --description--
+
+The output is correct, `repr` is giving you the string required to instantiate the objects.
+
+Now comment out both your `print` calls.
+
+# --hints--
+
+You should comment out both your `print()` calls.
+
+```js
+({ test: () => {
+ assert.match(code, /#\s*print\s*\(\s*f('|")v1 = \{\s*v1\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v1\s*\)\s*\}\2\s*\)/);
+ assert.match(code, /#\s*print\s*\(\s*f('|")v2 = \{\s*v2\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v2\s*\)\s*\}\2\s*\)/);
+} })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
new file mode 100644
index 00000000000..127f701ba31
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
@@ -0,0 +1,62 @@
+---
+id: 65f9b17a638f0d0dcce8c354
+title: Step 38
+challengeType: 20
+dashedName: step-38
+---
+
+# --description--
+
+To create a vector space, you need to define how vectors should behave in several cases. Vectors can be added, forming a new vector.
+
+The special method `__add__` can be implemented to override what happens by default when two objects are added together using the `+` operator.
+
+Right now, trying to add two instances of `R2Vector` or `R3Vector` would raise an exception. Create an empty `__add__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define an `__add__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__add__")`)) })
+```
+
+Your `__add__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
new file mode 100644
index 00000000000..f90c14fe57b
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b486989cb90ff3e77ac8
+title: Step 39
+challengeType: 20
+dashedName: step-39
+---
+
+# --description--
+
+The `other` parameter of your `__add__` method represents the operand placed at the right side of the `+` operator in an addition operation.
+
+You want to verify that the right-hand operand is not an object of the same class as the left-hand operand (i.e. `self`). Create an `if` statement that verifies that by checking the type of the operands.
+
+# --hints--
+
+You should create an `if` statement that checks if `type(self)` and `type(other)` are different.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
new file mode 100644
index 00000000000..1fa83e0f9aa
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b9710cca621244d3bde1
+title: Step 40
+challengeType: 20
+dashedName: step-40
+---
+
+# --description--
+
+In Python, `NotImplemented` is a special value used to indicate that an operation is not implemented for a specific case.
+
+`NotImplemented` does not raise an exception immediately. Instead, it signals to ask to the other operand how to perform the operation. If the request cannot be satisfied, a `TypeError` is returned by default.
+
+Because you want to be able to sum two vectors only if they belong to the same class, return `NotImplemented` from the `if` statement you created in the previous step.
+
+# --hints--
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
new file mode 100644
index 00000000000..9df77e46895
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
@@ -0,0 +1,58 @@
+---
+id: 65f9bb7c0d524612b2a88a4b
+title: Step 41
+challengeType: 20
+dashedName: step-41
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_stmt("kwargs = {}")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
new file mode 100644
index 00000000000..f5d28e43bd6
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
@@ -0,0 +1,92 @@
+---
+id: 65f9bc10a9fb1612e066e9e8
+title: Step 42
+challengeType: 20
+dashedName: step-42
+---
+
+# --description--
+
+When adding two vectors, each component of one vector is added to the same component of the other vector. For example, adding `(1, 2)` and `(2, 4)` generates a third vector `(3, 6)`, where `3` is the sum of `1` and `2` and `6` is the sum of `2` and `4`.
+
+The `kwargs` dictionary will contain the key-value pairs needed to instantiate a new vector of the same class of the two vectors added together.
+
+Turn the empty dictionary into a dictionary comprehension that iterates through `vars(self)` and for each key (`i`) creates a key-value pair, where the key is the same key of the current iteration and its value is the sum of the values of the `i` attributes of the two operands.
+
+# --hints--
+
+You should turn the empty dictionary assigned to `kwargs` into a dictionary comprehension that iterates over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_iters()[0].is_equivalent("vars(self)")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_key().is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the sum of the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i` in `vars(self)`. Use the `getattr()` function for that.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) + getattr(other, i)") or node.is_equivalent("getattr(other, i) + getattr(self, i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
new file mode 100644
index 00000000000..d1cd1755778
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
@@ -0,0 +1,70 @@
+---
+id: 65f9c2c2006feb1428ad2d4c
+title: Step 43
+challengeType: 20
+dashedName: step-43
+---
+
+# --description--
+
+You can unpack a dictionary into keyword arguments by using the `**` operator:
+
+```py
+def spam(a, b):
+ return a + b
+
+my_dict = {a: 11, b: 4}
+
+spam(**my_dict) # 15
+```
+
+Return an instance of the current class by using `__class__` and passing `**kwargs` as the argument.
+
+# --hints--
+
+You should return `self.__class__(**kwargs)` from the `__add__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
new file mode 100644
index 00000000000..689ab778fe5
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
@@ -0,0 +1,90 @@
+---
+id: 65f9cb678070ca1668898c70
+title: Step 44
+challengeType: 20
+dashedName: step-44
+---
+
+# --description--
+
+In the same way `__add__` is called under the hood when two objects are added together, the `__sub__` method is called implicitly in case of subtraction.
+
+Now, define an empty `__sub__` method and give two parameters: `self`, and `other`. Inside your new method, create an if statement to check if `self` and `other` do not belong to the same class and return `NotImplemented`, as you did previously.
+
+# --hints--
+
+You should define a `__sub__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__sub__")
+ `))
+})
+```
+
+Your `__sub__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_args("self, other")
+ `))
+})
+```
+
+You should create an `if` statement that checks if `self` and `other` does not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+ `))
+})
+```
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
new file mode 100644
index 00000000000..2d452d2413e
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
@@ -0,0 +1,89 @@
+---
+id: 65f9dd6e5a08af19c196c2df
+title: Step 45
+challengeType: 20
+dashedName: step-45
+---
+
+# --description--
+
+The vector resulting from the subtraction of one vector from another is obtained by calculating the difference of each of their components. For example, subtracting `(2, 4)` from `(7, 3)` generates a third vector `(5, -1)`, where `5` is the difference between `7` and `2` and `-1` is the difference between `3` and `4`.
+
+As you did before inside the `__add__` method, declare a `kwargs` variable after the `if` statement. Assign it a dictionary comprehension that iterates through the object attributes and creates a key-value pair for each key `i`, where the key is the same key as the current iteration and its value is the difference between the values of the `i` attributes of two operands.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it a dictionary comprehension that iterates over the object attributes.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_iters()[0]
+node.is_equivalent("vars(self)") or node.is_equivalent("self.__dict__")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over the object attributes.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_key().is_equivalent("i")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the difference between the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i`.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) - getattr(other, i)") or node.is_equivalent("self.__getattribute__(i) - other.__getattribute__(i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
new file mode 100644
index 00000000000..095bce27c7c
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
@@ -0,0 +1,65 @@
+---
+id: 65f9dfd2e75e291a38695f13
+title: Step 46
+challengeType: 20
+dashedName: step-46
+---
+
+# --description--
+
+Finally, return a new vector object. Use `__class__` and unpack `kwargs` to instantiate the new vector.
+
+# --hints--
+
+You should return a new vector using `__class__` and unpacking `kwargs` from the `__sub__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
new file mode 100644
index 00000000000..c5cb7742541
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
@@ -0,0 +1,67 @@
+---
+id: 65f9e0a578b22c1a736f3d82
+title: Step 47
+challengeType: 20
+dashedName: step-47
+---
+
+# --description--
+
+Modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+# --hints--
+
+You should modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v2 = R2Vector(x=0.5, y=1.25)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
new file mode 100644
index 00000000000..1d277671da4
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
@@ -0,0 +1,67 @@
+---
+id: 65fa8d5cf0ef3b141010f5d8
+title: Step 48
+challengeType: 20
+dashedName: step-48
+---
+
+# --description--
+
+It's time to verify that the addition and subtraction operations work as expected. Declare another variable `v3` and assign it the sum of `v1` plus `v2`.
+
+# --hints--
+
+You should declare a variable `v3` and assign it the sum of `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v3 = v1 + v2") or _Node(_code).has_stmt("v3 = v2 + v1")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
new file mode 100644
index 00000000000..87ddac5ea5f
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
@@ -0,0 +1,64 @@
+---
+id: 65fa8df56a0e2c149b4d24fe
+title: Step 49
+challengeType: 20
+dashedName: step-49
+---
+
+# --description--
+
+Next, check the new vector by printing the following f-string `f'v1 + v2 = {v3}'`.
+
+# --hints--
+
+You should print `f'v1 + v2 = {v3}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 + v2 = {v3}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
new file mode 100644
index 00000000000..e526a9cd4cc
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
@@ -0,0 +1,77 @@
+---
+id: 65fa9402d1fb5516aa42159d
+title: Step 50
+challengeType: 20
+dashedName: step-50
+---
+
+# --description--
+
+Feel free to modify `v3` so that it sums an `R2Vector` instance with an object of a different type, such as an integer or a string. You will be able to see a `TypeError` message printed on the console.
+
+Then, restore the original line and create a new variable `v4`. Assign the difference between `v1` and `v2` to your new variable and print the result following the same structure as the previous f-string.
+
+# --hints--
+
+You should declare a variable `v4` and assign it the difference between `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v4 = v1 - v2")
+ `))
+})
+```
+
+You should print `f'v1 - v2 = {v4}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 - v2 = {v4}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
new file mode 100644
index 00000000000..d2df1c3038d
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
@@ -0,0 +1,85 @@
+---
+id: 65fa9e1b6c6db919385359ec
+title: Step 51
+challengeType: 20
+dashedName: step-51
+---
+
+# --description--
+
+The special method `__mul__` can be implemented to specify what should happen when the current instance is multiplied by another object.
+
+Create an empty `__mul__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `__mul__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__mul__")
+ `))
+})
+```
+
+Your `__mul__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__mul__").has_args("self, other")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
new file mode 100644
index 00000000000..0a18b8b69d1
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
@@ -0,0 +1,94 @@
+---
+id: 65faaed8f7a9772f023ea816
+title: Step 52
+challengeType: 20
+dashedName: step-52
+---
+
+# --description--
+
+Vectors can be multiplied by a *scalar*, i.e. a number that multiplies each single component. The result of scalar multiplication is a vector with the same orientation as the original vector but a different magnitude.
+
+Implement the scalar multiplication by checking if `other` is either an `int` or a `float`. If it is, return a new instance of the current class that has each component of the starting vector multiplied by `other`. This will be the vector resulting from the scalar multiplication.
+
+Make sure the methods can be applied to compute the scalar multiplication of vectors with any number of dimensions.
+
+# --hints--
+
+Your method should return a new instance of the current class only when the type of `other` is either `int` or `float`.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=0, y=0)
+v2 = R3Vector(x=0, y=0, z=0)
+types = ["", True, [], {}]
+assert all((v1 * i) is None for i in types)
+types = [1, 1.0]
+assert all(type(v1 * i) is type(v1) for i in types)
+assert all(type(v2 * i) is type(v2) for i in types)
+`) })
+```
+
+The vector resulting from the scalar multiplication should have each component of the starting vector multiplied by the scalar.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=1, y=1.5)
+v2 = R3Vector(x=2.2, y=3, z=-1)
+assert vars(v1 * 3) == vars(R2Vector(x=3, y=4.5))
+assert vars(v2 * (-2.0)) == vars(R3Vector(x=-4.4, y=-6.0, z=2.0))
+`) })
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
new file mode 100644
index 00000000000..bcf1d3d0b55
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
@@ -0,0 +1,79 @@
+---
+id: 65fc87e19930a503e5f05500
+title: Step 53
+challengeType: 20
+dashedName: step-53
+---
+
+# --description--
+
+A vector can be multiplied by another vector, too. This operation is called *dot product*, or *scalar product*.
+
+Create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+You are going to implement the dot product inside this block during the next step.
+
+# --hints--
+
+You should create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__mul__").find_ifs()[0].find_conditions()[1]
+node.is_equivalent("type(self) == type(other)") or node.is_equivalent("type(other) == type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
new file mode 100644
index 00000000000..c5edc6d9b45
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
@@ -0,0 +1,87 @@
+---
+id: 65fc899d77495504d6deeccc
+title: Step 54
+challengeType: 20
+dashedName: step-54
+---
+
+# --description--
+
+The scalar product between two vectors $\mathbf{a}$ and $\mathbf{b}$ is indicated as:
+
+\\( \mathbf{a} \cdot \mathbf{b} = a_1 \cdot b_1 + a_2 \cdot b_2 + \ldots + a_n \cdot b_n = \sum_{i=1}^{n} a_i \cdot b_i \\)
+
+Where each component of $\mathbf{a}$ is multiplied by the correspondent component of $\mathbf{b}$, and all the products are summed together, resulting in a number.
+
+Within the `elif` clause, implement the above formula to compute the result of a scalar product and return the result. Remember that your implementation must be valid for any vector, independently from the number of components, when the method is inherited.
+
+# --hints--
+
+You should implement the scalar product calculation and return the result inside the `elif` body of your `__mul__` method.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+v3 = R3Vector(x=2, y=3, z=1.5)
+v4 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1*v2 == 4.75 and v3*v4 == 7.0
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
new file mode 100644
index 00000000000..36b78391926
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
@@ -0,0 +1,78 @@
+---
+id: 65fc8e7c766ab1070213aadb
+title: Step 55
+challengeType: 20
+dashedName: step-55
+---
+
+# --description--
+
+In case `other` is not an integer, a floating point number, or another instance of the current class, no product can be computed.
+
+After the `elif` clause, return `NotImplemented`.
+
+# --hints--
+
+You should return `NotImplemented` after the `elif` clause.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__mul__").has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
new file mode 100644
index 00000000000..bf365bd4903
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
@@ -0,0 +1,82 @@
+---
+id: 65fc8fa7e7860407ab479bf0
+title: Step 56
+challengeType: 20
+dashedName: step-56
+---
+
+# --description--
+
+It's time to test the multiplication. Declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`. Then, call the `print` function and pass it the following f-string: `f'v1 * 3 = {v5}'`.
+
+# --hints--
+
+You should declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * 3")`)) })
+```
+
+You should print the f-string `f'v1 * 3 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * 3 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
new file mode 100644
index 00000000000..034109b8c53
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
@@ -0,0 +1,87 @@
+---
+id: 65fd681b20b7e45f55def415
+title: Step 57
+challengeType: 20
+dashedName: step-57
+---
+
+# --description--
+
+The scalar multiplication works fine. Now, modify the assignment of `v5` to be the dot product `v1 * v2`. Also, update the `print` call.
+
+Before doing that, feel free to experiment and multiply `v1` by an object of invalid type to see the error message printed on the console.
+
+
+# --hints--
+
+You should update the assignment of `v5` assigning it the scalar product `v1 * v2`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * v2")`)) })
+```
+
+You should update your `print` call to print the f-string `f'v1 * v2 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * v2 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * 3
+print(f'v1 * 3 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
new file mode 100644
index 00000000000..f6184775ca4
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9250db0d6b8198cf29ef
+title: Step 58
+challengeType: 20
+dashedName: step-58
+---
+
+# --description--
+
+The `__eq__` method can be implemented to specify what should happen in case the comparison operator (`==`) is used to compare an object with something else.
+
+Within the `R2Vector` class, create an `__eq__` method and give it two parameters: `self` and `other`.
+
+# --hints--
+
+You should define a `__eq__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__eq__")`)) })
+```
+
+Your `__eq__` method should take two parameters: `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
new file mode 100644
index 00000000000..5d2d8cfc678
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
@@ -0,0 +1,88 @@
+---
+id: 65fd95c23beef982af29004c
+title: Step 59
+challengeType: 20
+dashedName: step-59
+---
+
+# --description--
+
+You want to compare two vectors, only when they belong to the same class. For that create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented` in that case.
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
new file mode 100644
index 00000000000..c3bea995dc8
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
@@ -0,0 +1,91 @@
+---
+id: 65fd97f3c1b4c4839bdeb8d2
+title: Step 60
+challengeType: 20
+dashedName: step-60
+---
+
+# --description--
+
+To compare two vectors, you are going to check that each component of the first vector is equal to the same component of the second vector.
+
+After the `if` statement you created in the previous step, return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+# --hints--
+
+The `__eq__` method should return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1 == v2 and not v1 == v3 and v4 == v5 and not v5 == v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
new file mode 100644
index 00000000000..a7f5d701215
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
@@ -0,0 +1,102 @@
+---
+id: 65fd9aa649f6cc84631882a9
+title: Step 61
+challengeType: 20
+dashedName: step-61
+---
+
+# --description--
+
+The `__ne__` method is called under the hood when the `!=` operator is used. Define a `__ne__` method with two parameters `self` and `other`. From your new method, return the opposite of `self == other`.
+
+# --hints--
+
+You should define a `__ne__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ne__")`)) })
+```
+
+Your `__ne__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ne__").has_args("self, other")`)) })
+```
+
+The `__ne__` method should return `False` if each attribute of the current instance is equal to the same attribute of `other` and `True` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+not v1 != v2 and v1 != v3 and not v4 != v5 and v5 != v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
new file mode 100644
index 00000000000..c151f678d86
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
@@ -0,0 +1,86 @@
+---
+id: 65fd9c6e49d7cd8513ab1005
+title: Step 62
+challengeType: 20
+dashedName: step-62
+---
+
+# --description--
+
+At the end of your code, use the equality operator to compare `v1` and `R2Vector(x=2, y=3)` and print the result.
+
+# --hints--
+
+You should print the result of comparing `v1` and `R2Vector(x=2, y=3)` using the equality operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 == R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) == v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
new file mode 100644
index 00000000000..804d4947304
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9d6203afea85931094c9
+title: Step 63
+challengeType: 20
+dashedName: step-63
+---
+
+# --description--
+
+The comparison returns `True`, since the two vectors have the same components. Now, modify the argument of the `print` call you added in the previous step to use the inequality operator.
+
+# --hints--
+
+You should modify the `print` call you added in the previous step using the inequality operator to compare `v1` and `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) != v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 == R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
new file mode 100644
index 00000000000..9255b41f2c6
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
@@ -0,0 +1,97 @@
+---
+id: 65fd9e2c56ff19862dfb8cbb
+title: Step 64
+challengeType: 20
+dashedName: step-64
+---
+
+# --description--
+
+The `__lt__` method is called under the hood when the `<` operator is used to compare an object with something else.
+
+Add an empty `__lt__` method and give it two parameters: `self`, `other`.
+
+# --hints--
+
+You should define a `__lt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__lt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
new file mode 100644
index 00000000000..ee258ff8a2a
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
@@ -0,0 +1,100 @@
+---
+id: 65fdc3c8478ee70fc7966151
+title: Step 65
+challengeType: 20
+dashedName: step-65
+---
+
+# --description--
+
+In the same way you did before for the `__eq__` method, create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
new file mode 100644
index 00000000000..390babbb01f
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
@@ -0,0 +1,91 @@
+---
+id: 65fdc496f4440e1055a2ac1b
+title: Step 66
+challengeType: 20
+dashedName: step-66
+---
+
+# --description--
+
+After the `if` statement, return the result of comparing the norm of the current instance with the norm of `other` using the less than operator.
+
+# --hints--
+
+The `__lt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the `<` operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_return("self.norm() < other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
new file mode 100644
index 00000000000..7193db8cba2
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
@@ -0,0 +1,122 @@
+---
+id: 6601918b44a11b4a8c986c6a
+title: Step 67
+challengeType: 20
+dashedName: step-67
+---
+
+# --description--
+
+The `__gt__` method is called under the hood when the `>` operator is used to compare an object with something else.
+
+After the `__lt__` method, in the same way you did for `__lt__`, implement the `__gt__` method. Pay attention to use the appropriate operator.
+
+# --hints--
+
+You should define a `__gt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__gt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_args("self, other")`)) })
+```
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+The `__gt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the greater than operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_return("self.norm() > other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
new file mode 100644
index 00000000000..fd051c7fca6
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
@@ -0,0 +1,111 @@
+---
+id: 66019258a7c71d4ae50da42e
+title: Step 68
+challengeType: 20
+dashedName: step-68
+---
+
+# --description--
+
+There are still two possible comparisons to implement. The `__le__` method is called when the `<=` operator is used to compare two objects.
+
+Define a `__le__` method with `self` and `other` as the parameters and make it return the opposite of `self > other`.
+
+# --hints--
+
+You should define a `__le__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__le__")`)) })
+```
+
+Your `__le__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_args("self, other")`)) })
+```
+
+Your `__le__` method return the opposite of `self > other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_return("not self > other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
new file mode 100644
index 00000000000..542035862a5
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
@@ -0,0 +1,116 @@
+---
+id: 66019319edb1cb4b57d3a793
+title: Step 69
+challengeType: 20
+dashedName: step-69
+---
+
+# --description--
+
+The last method you need is `__ge__`, which is called when the `>=` is used to compare two objects.
+
+Define a `__ge__` method with `self` and `other` as the parameters and make it return the opposite of `self < other`.
+
+# --hints--
+
+You should define a `__ge__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ge__")`)) })
+```
+
+Your `__ge__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_args("self, other")`)) })
+```
+
+Your `__ge__` method should return the opposite of `self < other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_return("not self < other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
new file mode 100644
index 00000000000..fe9c0cfa362
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
@@ -0,0 +1,104 @@
+---
+id: 660193a2a71faa4bd8f10970
+title: Step 70
+challengeType: 20
+dashedName: step-70
+---
+
+# --description--
+
+Feel free to play around with the new comparison operations you implemented. Then, remove your last `print` call.
+
+
+# --hints--
+
+You should not have `print(v1 != R2Vector(x=2, y=3))` in your code.
+
+```js
+({test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
new file mode 100644
index 00000000000..2157c6b8a3b
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
@@ -0,0 +1,111 @@
+---
+id: 66019977710caa516276c0a8
+title: Step 71
+challengeType: 20
+dashedName: step-71
+---
+
+# --description--
+
+The *cross product*, or *vector product*, is defined between 3-dimensional vectors and results in a third vector perpendicular to both of them.
+
+The `R3Vector` class inherits from `R2Vector`, meaning it has access to all the methods and properties defined in `R2Vector`. A child class can implement additional features. You already saw a way to change the implementation of a method. Now, you are going to give the child class `R3Vector` a new method instead.
+
+Within the `R3Vector` class, define a `cross` method and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `cross` method within the `R3Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").has_function("cross")`)) })
+```
+
+Your `cross` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
new file mode 100644
index 00000000000..b7948eb83c6
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
@@ -0,0 +1,114 @@
+---
+id: 6601a7eb860fb8546516674d
+title: Step 72
+challengeType: 20
+dashedName: step-72
+---
+
+# --description--
+
+Create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
new file mode 100644
index 00000000000..7a7cb7ef03c
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
@@ -0,0 +1,105 @@
+---
+id: 6601a88a6e2ccc550d7d7208
+title: Step 73
+challengeType: 20
+dashedName: step-73
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_variable("kwargs").is_equivalent("kwargs = {}")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
new file mode 100644
index 00000000000..c9e2224dad3
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
@@ -0,0 +1,116 @@
+---
+id: 6601a8fb2e993b55912f9e9f
+title: Step 74
+challengeType: 20
+dashedName: step-74
+---
+
+# --description--
+
+The dot product between two 3D vectors \\( \mathbf{a} \\) and \\( \mathbf{b} \\) can be computed as it follows:
+
+\\[ \mathbf{a} \times \mathbf{b} = \begin{pmatrix} a_yb_z - a_zb_y \\\ a_zb_x - a_xb_z \\\ a_xb_y - a_yb_x \end{pmatrix} \\]
+
+Where the resulting vector is represented as a column vector.
+
+Implement the formula above to compute the dot product between two 3-dimensional vectors and return the resulting vector from the `cross()` method.
+
+# --hints--
+
+The `cross()` method should return a new `R3Vector` instance resulting from the dot product computation.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+v1.cross(v2) == R3Vector(x=4.75, y=-3.5, z=1.0) and v2.cross(v1) == R3Vector(x=-4.75, y=3.5, z=-1.0) and v1.cross(v1) == R3Vector(x=0, y=0, z=0)
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
new file mode 100644
index 00000000000..c1435330d56
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
@@ -0,0 +1,119 @@
+---
+id: 6601ab2809898f57591f2f7f
+title: Step 75
+challengeType: 20
+dashedName: step-75
+---
+
+# --description--
+
+Now, modify the assignments of `v1` and `v2`. Turn them into `R3Vector` instances and pass `z=1` and `z=2` to `v1` and `v2`, respectively.
+
+# --hints--
+
+You should modify the assignment of `v1` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R3Vector(x=2, y=3, z=1)")`)) })
+```
+
+You should modify the assignment of `v2` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=0.5, y=1.25, z=2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+--fcc-editable-region--
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
new file mode 100644
index 00000000000..6904f99b5e1
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
@@ -0,0 +1,113 @@
+---
+id: 6601ac48a2ee6b59e6a5060d
+title: Step 76
+challengeType: 20
+dashedName: step-76
+---
+
+# --description--
+
+Call `cross()` on `v1` and pass `v2` as the argument. Assign this call to a new variable `v6`.
+
+# --hints--
+
+You should declare a variable named `v6` and assign it a call to the `cross()` method on `v1` passing it `v2` as the `argument`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v6").is_equivalent("v6 = v1.cross(v2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
new file mode 100644
index 00000000000..47d13a7bd4d
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
@@ -0,0 +1,210 @@
+---
+id: 6601ad0fe415985a5c83f3cc
+title: Step 77
+challengeType: 20
+dashedName: step-77
+---
+
+# --description--
+
+As a final step, call the `print` function and pass it the f-string `f'v1 x v2 = {v6}'` to see the output of the dot product.
+
+With that, you have completed the vector space project. Well done!
+
+# --hints--
+
+You should print `f'v1 x v2 = {v6}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 x v2 = {v6}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+print(f'v1 x v2 = {v6}')
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
new file mode 100644
index 00000000000..d25b1a4c723
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
@@ -0,0 +1,53 @@
+---
+id: 6659875502b6d7765498f324
+title: Step 26
+challengeType: 20
+dashedName: step-26
+---
+
+# --description--
+
+Use f-strings to modify your `print` calls so that they result in the output `v1 = (2, 3)` and `v2 = (2, 2, 3)`, respectively.
+
+# --hints--
+
+You should use an f-string to interpolate `v1` and generate the output `v1 = (2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}')")`)) })
+```
+
+You should use an f-string to interpolate `v2` and generate the output `v2 = (2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
new file mode 100644
index 00000000000..bc5ffa5f75d
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
@@ -0,0 +1,51 @@
+---
+id: 66680ddfd0f8c76782923cb0
+title: Step 22
+challengeType: 20
+dashedName: step-22
+---
+
+# --description--
+
+The `norm()` method is returning the correct values, but there's still something you can improve: readability.
+
+The `vars()` built-in function takes an object as its argument and returns the `__dict__` attribute of that object.
+
+Instead of directly accessing the `__dict__` attribute of `self`, modify the `norm` method to use the `vars()` function.
+
+# --hints--
+
+You should modify your `norm` method to use `vars(self)` instead of `self.__dict__`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in vars(self).values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
new file mode 100644
index 00000000000..e0f1c196265
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
@@ -0,0 +1,61 @@
+---
+id: 66682150151af29efec9727d
+title: Step 33
+challengeType: 20
+dashedName: step-33
+---
+
+# --description--
+
+The `__getattribute__` method is called under the hood any time you try to access an instance attribute. If the attribute is not found at the instance level, the method will search for it at the class level, and eventually in parent classes.
+
+Inside your class, define a `__getattribute__` method with two parameters, `self` and `attr`, and make it return the string `'calling __getattribute__'`. You'll override momentarily the default implementation just to see how the attribute access works.
+
+# --hints--
+
+You should define a method named `__getattribute__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_args("self, attr")`)) })
+```
+
+Your `__getattribute__` method should return the string `'calling __getattribute__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_return("'calling __getattribute__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
new file mode 100644
index 00000000000..948a541cb76
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
@@ -0,0 +1,61 @@
+---
+id: 666826f258fda1ab3396a509
+title: Step 34
+challengeType: 20
+dashedName: step-34
+---
+
+# --description--
+
+Now, print the result of accessing the `x` attribute of `v1` both with the dot operator and the `getattr()` built-in function.
+
+You will see that `__getattribute__` is called in both cases.
+
+# --hints--
+
+You should print the `x` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.x)") and n.has_call("print(getattr(v1, 'x'))")) or n.has_call("print(v1.x, getattr(v1, 'x'))") or n.has_call("print(getattr(v1, 'x'), v1.x)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
new file mode 100644
index 00000000000..8c3a650010b
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
@@ -0,0 +1,69 @@
+---
+id: 666827a6fd0dbaafe8330ea6
+title: Step 35
+challengeType: 20
+dashedName: step-35
+---
+
+# --description--
+
+`__getattr__` is another special method that plays a role in accessing attributes.
+
+The default implementation of `__getattribute__` is to raise an `AttributeError` when the requested attribute is not an instance attribute or it is not present in the class tree.
+
+In that case, `__getattr__` is called if defined by the class. You can consider it as a sort of fallback when the usual attribute accessing procedure fails.
+
+Turn the `__getattribute__` method into `__getattr__` and modify the string returned by the method into `'calling __getattr__'`.
+
+# --hints--
+
+You should define a method named `__getattr__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_args("self, attr")`)) })
+```
+
+Your `__getattr__` method should return the string `'calling __getattr__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_return("'calling __getattr__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+print(v1.x)
+print(getattr(v1, 'x'))
+
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
new file mode 100644
index 00000000000..598c9822428
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
@@ -0,0 +1,62 @@
+---
+id: 666832e427d70bc5219dc62a
+title: Step 36
+challengeType: 20
+dashedName: step-36
+---
+
+# --description--
+
+As you can see from the output, although you defined `__getattr__` in your class, this method is not called yet. This happens because the default attribute access occurs through `__getattribute__`. Therefore, you can see the attribute value printed on the terminal.
+
+Now modify the last two lines of code to access the `z` attribute of `v1` in both your `print()` calls. This time, you are going to access an attribute that `v1` does not have. As a result, `__getattribute__` will raise an error and `__getattr__` will be called.
+
+# --hints--
+
+You should modify your code to print the `z` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.z)") and n.has_call("print(getattr(v1, 'z'))")) or n.has_call("print(v1.z, getattr(v1, 'z'))") or n.has_call("print(getattr(v1, 'z'), v1.z)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+print(v1.x)
+print(getattr(v1, 'x'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
new file mode 100644
index 00000000000..3f18e7c657c
--- /dev/null
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
@@ -0,0 +1,75 @@
+---
+id: 6668374ed18b7fce10259cb3
+title: Step 37
+challengeType: 20
+dashedName: step-37
+---
+
+# --description--
+
+Now that you have an idea of how the attribute access work, remove the last two lines of your code together with the `__getattr__` method.
+
+Then, restore the `print()` calls you commented out before and delete the second argument from both of them.
+
+# --hints--
+
+You should not have a `__getattr__` method.
+
+```js
+({ test: () => assert.isFalse(runPython(`_Node(_code).find_class("R2Vector").has_function("__getattr__")`)) })
+```
+
+You should not have `print(v1.z)`and `print(getattr(v1, 'z'))` in your code.
+
+```js
+({ test: () => assert.isFalse(runPython(`
+n = _Node(_code)
+n.has_call("print(v1.z)") or n.has_call("print(getattr(v1, 'z'))")
+`)) })
+```
+
+You should restore the `print()` calls you commented out before and remove the second argument from both of them.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).has_call("print(f'v1 = {v1}')") and _Node(_code).has_call("print(f'v2 = {v2}')")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+print(v1.z)
+print(getattr(v1, 'z'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
index f84624b42de..e9870c4826a 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
@@ -1,6 +1,6 @@
---
id: 6553ed69ece88d29594748aa
-title: Step 50
+title: Step 52
challengeType: 20
dashedName: step-52
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
index bf46d6f32ca..36913664567 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
@@ -1,6 +1,6 @@
---
id: 6553efd6ada3f42aa2d75448
-title: Step 51
+title: Step 53
challengeType: 20
dashedName: step-53
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
index 2688363421c..bdc61a56deb 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
@@ -1,6 +1,6 @@
---
id: 6553f3fc92741c2bf8ded140
-title: Step 52
+title: Step 54
challengeType: 20
dashedName: step-54
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
index 16b2b7a8c78..c54923b4ea2 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
@@ -1,6 +1,6 @@
---
id: 6553f4f66099802c6ae94613
-title: Step 53
+title: Step 55
challengeType: 20
dashedName: step-55
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
index bcae9e4c2a5..92734e07289 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
@@ -1,6 +1,6 @@
---
id: 6553f6086add4b2cbb99fd78
-title: Step 54
+title: Step 56
challengeType: 20
dashedName: step-56
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
index 2f0fc79d3ff..1355edcf141 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
@@ -1,6 +1,6 @@
---
id: 6553f8c570f9982e013a8886
-title: Step 55
+title: Step 57
challengeType: 20
dashedName: step-57
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
index 51c7c51620d..5b984de7d3b 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
@@ -1,6 +1,6 @@
---
id: 655491bd5b98b813fa5bedca
-title: Step 56
+title: Step 58
challengeType: 20
dashedName: step-58
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
index 64bef622b35..b6a7f0aa9c6 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
@@ -1,6 +1,6 @@
---
id: 6554930320d70414e7b6acc6
-title: Step 57
+title: Step 59
challengeType: 20
dashedName: step-59
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
index c2b67a816d2..ab8d95e137d 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
@@ -1,6 +1,6 @@
---
id: 65549561463f0016876e852c
-title: Step 58
+title: Step 60
challengeType: 20
dashedName: step-60
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
index 5d4a37a2fe9..839352832e3 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
@@ -1,6 +1,6 @@
---
id: 65549f90cf78131c96ebcf28
-title: Step 59
+title: Step 61
challengeType: 20
dashedName: step-61
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
index 4c05b0584c4..01181c37df7 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
@@ -1,6 +1,6 @@
---
id: 6554a334a40edb1fb4eff827
-title: Step 60
+title: Step 62
challengeType: 20
dashedName: step-62
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
index 63e5be90540..921879d9acc 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
@@ -1,6 +1,6 @@
---
id: 6554a49a4f782f208abcc87e
-title: Step 61
+title: Step 63
challengeType: 20
dashedName: step-63
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
index c8c045af50c..139a3fea8db 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
@@ -1,6 +1,6 @@
---
id: 6554a57ec0a2c52106e7ee50
-title: Step 62
+title: Step 64
challengeType: 20
dashedName: step-64
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
index f8aec7c6f01..b1c21af09e5 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
@@ -1,6 +1,6 @@
---
id: 6554a88d5af937226f4a9121
-title: Step 63
+title: Step 65
challengeType: 20
dashedName: step-65
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
index 9f67d3e0905..2bff453ec4b 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
@@ -1,6 +1,6 @@
---
id: 6554ac937a49be2701af4f2f
-title: Step 64
+title: Step 66
challengeType: 20
dashedName: step-66
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
index d9b8dbfc283..4c7bb7ab462 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
@@ -1,6 +1,6 @@
---
id: 6554ad2463b8892748f8efdd
-title: Step 65
+title: Step 67
challengeType: 20
dashedName: step-67
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
index e2ed67b3ab6..1eeeb3697b1 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
@@ -1,6 +1,6 @@
---
id: 6554d0332949b133a0b35eaa
-title: Step 66
+title: Step 68
challengeType: 20
dashedName: step-68
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
index 863de41bbc0..5f093f3df2c 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
@@ -1,6 +1,6 @@
---
id: 6554d15c8acb5f34499ad789
-title: Step 67
+title: Step 69
challengeType: 20
dashedName: step-69
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
index c24fa10d6c6..65ac8f3f6c4 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
@@ -1,6 +1,6 @@
---
id: 6554d25dc5ceaa354307a77e
-title: Step 68
+title: Step 70
challengeType: 20
dashedName: step-70
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
index 076f1a41e91..2df3eb6fceb 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
@@ -1,6 +1,6 @@
---
id: 6554de295ade563a069936a1
-title: Step 69
+title: Step 71
challengeType: 20
dashedName: step-71
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
index 9793f1023c3..5e52b90279e 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
@@ -1,6 +1,6 @@
---
id: 6554dfce1683be3c0c9609a6
-title: Step 70
+title: Step 72
challengeType: 20
dashedName: step-72
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
index 9454a27cb5e..02e14d9019c 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
@@ -1,6 +1,6 @@
---
id: 6554e0adc7bb193cbfdb36d5
-title: Step 71
+title: Step 73
challengeType: 20
dashedName: step-73
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
index 182346eca82..7f91537aead 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
@@ -1,6 +1,6 @@
---
id: 6554e2ee23bfd93f2c83640f
-title: Step 72
+title: Step 74
challengeType: 20
dashedName: step-74
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
index 48ececac1ab..d5bdb7ff5d1 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
@@ -1,6 +1,6 @@
---
id: 6554e343caea913ffba7bec6
-title: Step 73
+title: Step 75
challengeType: 20
dashedName: step-75
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
index 368cf69b225..a80c318bd1d 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
@@ -1,6 +1,6 @@
---
id: 655516e410b8e30fb4fb64e8
-title: Step 74
+title: Step 76
challengeType: 20
dashedName: step-76
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
index 22de7de4fa0..82e1790a7d8 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
@@ -1,6 +1,6 @@
---
id: 65551a628bcb7e121e32d04b
-title: Step 77
+title: Step 79
challengeType: 20
dashedName: step-79
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
index 7f0ec8191b3..8603eb7e6d8 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
@@ -1,6 +1,6 @@
---
id: 6555201d9b7fc917399f9f0b
-title: Step 78
+title: Step 80
challengeType: 20
dashedName: step-80
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
index 01549558a4b..5c6c8181984 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
@@ -1,6 +1,6 @@
---
id: 655520c20cb1e6177b0641d6
-title: Step 79
+title: Step 81
challengeType: 20
dashedName: step-81
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
index cc4f4eacee1..db091c232cc 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
@@ -1,6 +1,6 @@
---
id: 655522883e66f618e03a9411
-title: Step 80
+title: Step 82
challengeType: 20
dashedName: step-82
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
index cd29fc36bb4..9588d739f44 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
@@ -1,6 +1,6 @@
---
id: 6555231eac4d9f19bd3d44b5
-title: Step 81
+title: Step 83
challengeType: 20
dashedName: step-83
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
index c02b037de64..b8c910a3aa5 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
@@ -1,6 +1,6 @@
---
id: 65552a111190e11f0963949e
-title: Step 82
+title: Step 84
challengeType: 20
dashedName: step-84
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
index eb0c5d14c63..28da95df2b0 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
@@ -1,6 +1,6 @@
---
id: 65552a9593755e1fb2f5ab50
-title: Step 83
+title: Step 85
challengeType: 20
dashedName: step-85
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
index aa1a050cf04..4fcaff7b89c 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
@@ -1,6 +1,6 @@
---
id: 65552b14e803731fe3c1e4ca
-title: Step 84
+title: Step 86
challengeType: 20
dashedName: step-86
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
index 3b6cc0579a3..f8ea2a67964 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
@@ -1,6 +1,6 @@
---
id: 65553159615a8123b190ee43
-title: Step 85
+title: Step 87
challengeType: 20
dashedName: step-87
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
index 1e3ad3dfb8a..6799724af14 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
@@ -1,6 +1,6 @@
---
id: 6555d6e12c95701172b55709
-title: Step 75
+title: Step 77
challengeType: 20
dashedName: step-77
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
index f3c3b93e0c6..97049b3b537 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
@@ -1,6 +1,6 @@
---
id: 6555d8b0b3d20b128bdadd37
-title: Step 76
+title: Step 78
challengeType: 20
dashedName: step-78
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
index 866b80d387b..d310105bfe1 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
@@ -1,6 +1,6 @@
---
id: 6555db4a7b788e15795674e5
-title: Step 87
+title: Step 89
challengeType: 20
dashedName: step-89
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
index 2cf86f2dd96..3a91139cf33 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
@@ -1,6 +1,6 @@
---
id: 6555df0c81300b175308557d
-title: Step 88
+title: Step 90
challengeType: 20
dashedName: step-90
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
index 959034b7875..bc5788b45f8 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
@@ -1,6 +1,6 @@
---
id: 6555e1bfcd374e18c6be8e58
-title: Step 89
+title: Step 91
challengeType: 20
dashedName: step-91
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
index 791d9bdbd6d..4d7848b4be9 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
@@ -1,6 +1,6 @@
---
id: 6555e3f387381a19d5e00333
-title: Step 90
+title: Step 92
challengeType: 20
dashedName: step-92
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
index 20f69b6bd24..e895a41b321 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
@@ -1,6 +1,6 @@
---
id: 6555e43e783ed31a0532b1b2
-title: Step 91
+title: Step 93
challengeType: 20
dashedName: step-93
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
index 9acf44cfdc2..f878bb6c12b 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
@@ -1,6 +1,6 @@
---
id: 6555e547c18a2b1a7b795bd8
-title: Step 93
+title: Step 95
challengeType: 20
dashedName: step-95
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
index 312d322e32f..9b3df4758a0 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
@@ -1,6 +1,6 @@
---
id: 6555e5991af57d1ae0e35f0a
-title: Step 94
+title: Step 96
challengeType: 20
dashedName: step-96
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
index 3493c823d5d..1bb2f8f1567 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
@@ -1,6 +1,6 @@
---
id: 65a450e8fb2c9d75c7378d28
-title: Step 86
+title: Step 88
challengeType: 20
dashedName: step-88
---
diff --git a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
index a15a486b7eb..29a960e8277 100644
--- a/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
+++ b/curriculum/challenges/arabic/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
@@ -1,6 +1,6 @@
---
id: 65a51c9e000b660122b8b29e
-title: Step 92
+title: Step 94
challengeType: 20
dashedName: step-94
---
diff --git a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md b/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
deleted file mode 100644
index 632abe728dd..00000000000
--- a/curriculum/challenges/arabic/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
+++ /dev/null
@@ -1,344 +0,0 @@
----
-id: 62aa1fed3d4e873366ff3131
-title: Step 150
-challengeType: 0
-dashedName: step-150
----
-
-# --description--
-
-In your `attack` function, below the `health` variable, create an `if` statement. Set the condition to call the `isMonsterHit` function.
-
-# --hints--
-
-You should add an `if` statement which calls `isMonsterHit` in the condition.
-
-```js
-assert.match(attack.toString(), /if\s*\(\s*isMonsterHit\s*\(\s*\)/)
-```
-
-# --seed--
-
-## --seed-contents--
-
-```html
-
-
-
-
-
-
+
+Within the `Vector` class, create an `__init__` method and give it three parameters, `self`, `x`, and `y`.
+
+# --hints--
+
+You should define an `__init__` method inside the `Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").has_function("__init__")`)) })
+```
+
+Your `__init__` method should take three parameters: `self`, `x`, and `y`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").find_function("__init__").has_args("self, x, y")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ pass
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
new file mode 100644
index 00000000000..62ab349a8db
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
@@ -0,0 +1,38 @@
+---
+id: 65f055b9190fc41ca35549b8
+title: Step 3
+challengeType: 20
+dashedName: step-3
+---
+
+# --description--
+
+Python offers various methods that include both a leading and trailing double underscore in their names. You may already be familiar with some, such as `__init__` and `__str__`. These methods, which follow the `__
+
+So far, you created a 2-dimensional vector. You want to be able to represent vectors with a different number of dimensions without rewriting the necessary code for each specific case. For that, you will use inheritance.
+
+Start by renaming the `Vector` class into `R2Vector` to specify that this class is going to deal with 2-dimensional vectors. Remember to modify the instantiation of `v1`, too.
+
+# --hints--
+
+You should rename the `Vector` class into `R2Vector`. Remember to modify the instantiation of `v1`, too.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+v1 = Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
new file mode 100644
index 00000000000..62b7794dba3
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
@@ -0,0 +1,70 @@
+---
+id: 65f40051d6b09a139f253e8e
+title: Step 12
+challengeType: 20
+dashedName: step-12
+---
+
+# --description--
+
+Inheritance enables you to define a class from an existing one. The new class, called child, inherits all the methods and properties of the existing class, called parent.
+
+```py
+class Tree:
+ def sprout(self):
+ print('Making new leaves!')
+
+class Oak(Tree):
+ pass
+
+Oak().sprout() # Output: Making new leaves!
+```
+
+In the example above, the child class `Oak` inherits from `Tree` and inherits the `sprout` method from the parent class `Tree`.
+
+Create a new class named `R3Vector` and follow the example above to make it inherit from the `R2Vector` class.
+
+# --hints--
+
+You should define a new class `R3Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R3Vector")
+ `))
+})
+```
+
+Your new class `R3Vector` should inherit from `R2Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").inherits_from("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
new file mode 100644
index 00000000000..dfdb08a15d3
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
@@ -0,0 +1,56 @@
+---
+id: 65f40401e6ef53173c04e27d
+title: Step 13
+challengeType: 20
+dashedName: step-13
+---
+
+# --description--
+
+Within your new class, declare an `__init__` method. Give it `self`, `x`, `y`, and `z` as the parameters.
+
+# --hints--
+
+You should define an `__init__` method inside your `R3Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").has_function("__init__")
+ `))
+})
+```
+
+Your `__init__` method should have four parameters `self`, `x`, `y`, and `z`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, x, y, z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
new file mode 100644
index 00000000000..f329157bd30
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
@@ -0,0 +1,49 @@
+---
+id: 65f407ea37ad6e181b90462e
+title: Step 14
+challengeType: 20
+dashedName: step-14
+---
+
+# --description--
+
+You could assign each `i` parameter to `self.i` as you did before. Although in this case you have few lines to repeat, one way to avoid this repetition is using the `super()` function. `super()` enables you to refer implicitly to the parent class: `super().__init__(x, y)` calls the `__init__` method of the parent class.
+
+Add a `super().__init__(x, y)` call to your `__init__` method.
+
+# --hints--
+
+You should have a `super().__init__(x, y)` call in your `__init__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_stmt("super().__init__(x, y)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
new file mode 100644
index 00000000000..ecf329fe7e7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
@@ -0,0 +1,47 @@
+---
+id: 65f40f8af784751c613d638a
+title: Step 15
+challengeType: 20
+dashedName: step-15
+---
+
+# --description--
+
+Now, you need to assign `z` to the `z` attribute of your `R3Vector` object.
+
+# --hints--
+
+You should assign `z` to `self.z` after the `super` call.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").is_ordered("super().__init__(x, y)", "self.z = z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
new file mode 100644
index 00000000000..5a13be02b39
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
@@ -0,0 +1,47 @@
+---
+id: 65f40fdb3579aa1ced28b2eb
+title: Step 16
+challengeType: 20
+dashedName: step-16
+---
+
+# --description--
+
+Create an `R3Vector` instance with `2`, `2`, and `3` as the values of `x`, `y`, and `z`, respectively. Assign the new instance to `v2`.
+
+# --hints--
+
+You should declare a variable `v2` and assign it `R3Vector(2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(2, 2, 3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
new file mode 100644
index 00000000000..c659dbc8460
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
@@ -0,0 +1,72 @@
+---
+id: 65f412c208c3791fee305acf
+title: Step 17
+challengeType: 20
+dashedName: step-17
+---
+
+# --description--
+
+In Python, you can enforce the use of keyword-only arguments by adding a `*` as an additional argument to the function or method signature. Modify both `__init__` methods by adding a `*` as the second parameter (after `self`). Every parameter placed after that will require the use of a keyword argument in the function/method call.
+
+This means that you need to modify the `super().__init__(x, y)` call, too. Do it by giving `x` the value `x`, and `y` the value `y`.
+
+Finally, modify the instantiation of `v1` and `v2` by using keyword arguments.
+
+# --hints--
+
+You should enforce keyword arguments by adding a `*` as the second parameter in both your `__init__` methods.
+
+```js
+({ test: () => {
+ assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__init__").has_args("self, *, x, y")`));
+ assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, *, x, y, z")`));
+} })
+```
+
+You should modify your `super.__init__(x, y)` call to use keyword arguments.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").find_body().is_equivalent("super().__init__(x=x, y=y)\\nself.z = z")`)) })
+```
+
+You should modify the assignment of `v1` to be `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R2Vector(x=2, y=3)")`)) })
+```
+
+You should modify the assignment of `v2` to be `R3Vector(x=2, y=2, z=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=2, y=2, z=3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+v2 = R3Vector(2, 2, 3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
new file mode 100644
index 00000000000..05cdf4f49a6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
@@ -0,0 +1,64 @@
+---
+id: 65f4148dea0f802040225e0c
+title: Step 18
+challengeType: 20
+dashedName: step-18
+---
+
+# --description--
+
+Remove the existing `print` calls. Then, as you did before for `v1`, print `v2` and the value returned by `v2.norm()`.
+
+# --hints--
+
+You should not have `print(v1)` and `print(v1.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1.norm())")`));
+ }
+})
+```
+
+You should print `v2` and `v2.norm()`.
+
+```js
+({
+ test: () => {
+ assert(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+print(v1.norm())
+print(v1)
+
+v2 = R3Vector(x=2, y=2, z=3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
new file mode 100644
index 00000000000..411bc02d955
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
@@ -0,0 +1,64 @@
+---
+id: 65f4520e363e2642f8112e33
+title: Step 19
+challengeType: 20
+dashedName: step-19
+---
+
+# --description--
+
+As you can see, something is not quite right. The `norm` and `__str__` methods inherited from `R2Vector` cannot adapt to a 3-dimensional vector. Their implementation has to be more flexible.
+
+Every object in Python has a special attribute named `__dict__`, which is a dictionary that stores the object attributes.
+
+Remove the existing `print` calls. Then, print the `__dict__` attribute of your `v1` and `v2` vectors to see what they look like.
+
+# --hints--
+
+You should not have `print(v2)` and `print(v2.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+You should print the `__dict__` attribute of `v1` and `v2`.
+
+```js
+({ test: () => assert(runPython(`
+(_Node(_code).has_call("print(v1.__dict__)") and _Node(_code).has_call("print(v2.__dict__)")) or _Node(_code).has_call("print(v1.__dict__, v2.__dict__)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v2.norm())
+print(v2)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
new file mode 100644
index 00000000000..2a2c8f28376
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
@@ -0,0 +1,49 @@
+---
+id: 65f4535bbdb28d436ff3ddc9
+title: Step 20
+challengeType: 20
+dashedName: step-20
+---
+
+# --description--
+
+As you can see from the output, `__dict__` contains the values of your instance attributes. Instead of explicitly adding the squares of `self.x` and `self.y`, you are going to iterate over the values stored in `__dict__` to calculate the value of the norm.
+
+Within the `norm` method body, replace the content of the parentheses with a generator expression that elevates each value `val` in `self.__dict__.values()` to the power of `2`. Also, pass that generator expression as the argument to the `sum` function, so that all the squares are added together before calculating the square root.
+
+# --hints--
+
+You should return `sum(val**2 for val in self.__dict__.values())**0.5` from `norm()` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in self.__dict__.values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
new file mode 100644
index 00000000000..bbb82436c52
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
@@ -0,0 +1,53 @@
+---
+id: 65f870003444fb1a2ad171f2
+title: Step 21
+challengeType: 20
+dashedName: step-21
+---
+
+# --description--
+
+Modify the two `print` calls to print the norm of your vectors and verify that the `norm()` method works fine.
+
+# --hints--
+
+You should print `v1.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1.norm())")`)) })
+```
+
+You should print `v2.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v2.norm())")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
new file mode 100644
index 00000000000..22e3cab792e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
@@ -0,0 +1,61 @@
+---
+id: 65f8709620b2ce1a62608f5a
+title: Step 23
+challengeType: 20
+dashedName: step-23
+---
+
+# --description--
+
+When you need to dynamically access some attributes starting from a string input, the built-in `getattr()` function is what you need. It takes an object as its first argument, and a string containing the attribute name as its second attribute.
+
+Start to fix the `__str__` method by replacing the string returned by `__str__()` with a generator expression that iterates through the object attributes and calls `getattr()` for each attribute `i`.
+
+# --hints--
+
+You should return a generator expression that iterates over `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_iters()[0].is_equivalent("vars(self)")`)) })
+```
+
+You should return a generator expression that uses `i` as the iteration variable.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_targets()[0].is_equivalent("i")`)) })
+```
+
+You should return a generator expression that calls `getattr(self, i)` for each item `i` in `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_expr().is_equivalent("getattr(self, i)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
new file mode 100644
index 00000000000..668bd89de56
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
@@ -0,0 +1,47 @@
+---
+id: 65f8720685ec351abef26740
+title: Step 24
+challengeType: 20
+dashedName: step-24
+---
+
+# --description--
+
+To obtain a proper string representation, call the `tuple()` constructor and pass it the generator expression you wrote in the previous step as the argument.
+
+# --hints--
+
+You should pass the expression returned by the `__str__` method to the `tuple()` constructor.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("tuple(getattr(self, i) for i in vars(self))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return (getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
new file mode 100644
index 00000000000..f687795519e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
@@ -0,0 +1,47 @@
+---
+id: 65f872a0fe6aa21b456ad4fe
+title: Step 25
+challengeType: 20
+dashedName: step-25
+---
+
+# --description--
+
+Finally, pass the `tuple()` call as the argument to the `str()` function.
+
+# --hints--
+
+You should pass the `tuple()` call you are currently returning from the `__str__` method to the `str()` function.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("str(tuple(getattr(self, i) for i in vars(self)))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return tuple(getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
new file mode 100644
index 00000000000..9f1d1e16d92
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
@@ -0,0 +1,56 @@
+---
+id: 65f8749b13774b1d2e4a7fba
+title: Step 27
+challengeType: 20
+dashedName: step-27
+---
+
+# --description--
+
+While the `__str__` method returns a human-readable string representation of an object, the `__repr__` method is supposed to return the string needed to instantiate the object.
+
+Add a `__repr__` method with a `self` parameter within the `R2Vector` class.
+
+# --hints--
+
+Your `R2Vector` class should have a `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__repr__")`)) })
+```
+
+Your `__repr__` method should have a `self` parameter.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_args("self")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
new file mode 100644
index 00000000000..7f5a3e0f9c9
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
@@ -0,0 +1,74 @@
+---
+id: 65f876d17832001e8e1abb05
+title: Step 28
+challengeType: 20
+dashedName: step-28
+---
+
+# --description--
+
+Declare a variable `arg_list`. Give it the value of a list comprehension that iterates over `key` and `val` for each key-value pair in `vars(self).items()` and computes the f-string `f'{key}={val}'` at each iteration.
+
+# --hints--
+
+You should declare a variable `arg_list`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_variable("arg_list")`)) })
+```
+
+You should assign a list comprehension that iterates over `vars(self).items()` to `arg_list`.
+
+```js
+({ test: () => runPython(`
+import ast
+var = _Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list")
+assert isinstance(var.tree.value, ast.ListComp), "Expected arg_list to be a list comprehension"
+assert (actual := var.find_comp_iters()[0].is_equivalent("vars(self).items()")), f"Expected vars(self).items(), got {actual}"
+`) })
+```
+
+The list comprehension assigned to `arg_list` should use `key` and `val` to iterate over `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_targets()[0].is_equivalent("key, val")
+`)) })
+```
+
+The list comprehension assigned to `arg_list` should compute the string `f'{key}={val}'` for each key-value pair in `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_expr().is_equivalent("f'{key}={val}'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
new file mode 100644
index 00000000000..0c56316394e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
@@ -0,0 +1,50 @@
+---
+id: 65f93acbb514857003510e79
+title: Step 29
+challengeType: 20
+dashedName: step-29
+---
+
+# --description--
+
+Declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+# --hints--
+
+You should declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("args").is_equivalent("args = ', '.join(arg_list)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
new file mode 100644
index 00000000000..e826611fa57
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
@@ -0,0 +1,52 @@
+---
+id: 65f93b67169a9c703264458a
+title: Step 30
+challengeType: 20
+dashedName: step-30
+---
+
+# --description--
+
+Since the method should return the string to instantiate the object for `R2Vector` as well as `R3Vector` when inherited, you cannot build the string specifying the class name.
+
+You can access the name of a class with `__class__.__name__`. Add a `return` statement to the `__repr__` method and return the string necessary to instantiate the object.
+
+# --hints--
+
+You should use `__class__.__name__` to build the f-string needed to instantiate a vector object and return it from the `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_return("f'{self.__class__.__name__}({args})'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
new file mode 100644
index 00000000000..13682539c2c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
@@ -0,0 +1,57 @@
+---
+id: 65f93d4647ce2670dc6f095c
+title: Step 31
+challengeType: 20
+dashedName: step-31
+---
+
+# --description--
+
+The `__repr__` method is called under the hood by the `repr` function. Verify that `__repr__` works properly by adding `f'\nrepr = {repr(v1)}'` and `f'\nrepr = {repr(v2)}'` as the second argument to your first and second `print` calls, respectively.
+
+# --hints--
+
+You should add `f'\nrepr = {repr(v1)}'` as the second argument to your `print(f'v1 = {v1}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}', f'\\\\nrepr = {repr(v1)}')")`)) })
+```
+
+You should add `f'\nrepr = {repr(v2)}'` as the second argument to your `print(f'v2 = {v2}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}', f'\\\\nrepr = {repr(v2)}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
new file mode 100644
index 00000000000..a25da243ba9
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
@@ -0,0 +1,56 @@
+---
+id: 65f93e54a9121571dcdd3e79
+title: Step 32
+challengeType: 20
+dashedName: step-32
+---
+
+# --description--
+
+The output is correct, `repr` is giving you the string required to instantiate the objects.
+
+Now comment out both your `print` calls.
+
+# --hints--
+
+You should comment out both your `print()` calls.
+
+```js
+({ test: () => {
+ assert.match(code, /#\s*print\s*\(\s*f('|")v1 = \{\s*v1\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v1\s*\)\s*\}\2\s*\)/);
+ assert.match(code, /#\s*print\s*\(\s*f('|")v2 = \{\s*v2\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v2\s*\)\s*\}\2\s*\)/);
+} })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
new file mode 100644
index 00000000000..86133f41f32
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
@@ -0,0 +1,62 @@
+---
+id: 65f9b17a638f0d0dcce8c354
+title: Step 38
+challengeType: 20
+dashedName: step-38
+---
+
+# --description--
+
+To create a vector space, you need to define how vectors should behave in several cases. Vectors can be added, forming a new vector.
+
+The special method `__add__` can be implemented to override what happens by default when two objects are added together using the `+` operator.
+
+Right now, trying to add two instances of `R2Vector` or `R3Vector` would raise an exception. Create an empty `__add__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define an `__add__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__add__")`)) })
+```
+
+Your `__add__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
new file mode 100644
index 00000000000..f90c14fe57b
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b486989cb90ff3e77ac8
+title: Step 39
+challengeType: 20
+dashedName: step-39
+---
+
+# --description--
+
+The `other` parameter of your `__add__` method represents the operand placed at the right side of the `+` operator in an addition operation.
+
+You want to verify that the right-hand operand is not an object of the same class as the left-hand operand (i.e. `self`). Create an `if` statement that verifies that by checking the type of the operands.
+
+# --hints--
+
+You should create an `if` statement that checks if `type(self)` and `type(other)` are different.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
new file mode 100644
index 00000000000..1fa83e0f9aa
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b9710cca621244d3bde1
+title: Step 40
+challengeType: 20
+dashedName: step-40
+---
+
+# --description--
+
+In Python, `NotImplemented` is a special value used to indicate that an operation is not implemented for a specific case.
+
+`NotImplemented` does not raise an exception immediately. Instead, it signals to ask to the other operand how to perform the operation. If the request cannot be satisfied, a `TypeError` is returned by default.
+
+Because you want to be able to sum two vectors only if they belong to the same class, return `NotImplemented` from the `if` statement you created in the previous step.
+
+# --hints--
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
new file mode 100644
index 00000000000..9df77e46895
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
@@ -0,0 +1,58 @@
+---
+id: 65f9bb7c0d524612b2a88a4b
+title: Step 41
+challengeType: 20
+dashedName: step-41
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_stmt("kwargs = {}")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
new file mode 100644
index 00000000000..f5d28e43bd6
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
@@ -0,0 +1,92 @@
+---
+id: 65f9bc10a9fb1612e066e9e8
+title: Step 42
+challengeType: 20
+dashedName: step-42
+---
+
+# --description--
+
+When adding two vectors, each component of one vector is added to the same component of the other vector. For example, adding `(1, 2)` and `(2, 4)` generates a third vector `(3, 6)`, where `3` is the sum of `1` and `2` and `6` is the sum of `2` and `4`.
+
+The `kwargs` dictionary will contain the key-value pairs needed to instantiate a new vector of the same class of the two vectors added together.
+
+Turn the empty dictionary into a dictionary comprehension that iterates through `vars(self)` and for each key (`i`) creates a key-value pair, where the key is the same key of the current iteration and its value is the sum of the values of the `i` attributes of the two operands.
+
+# --hints--
+
+You should turn the empty dictionary assigned to `kwargs` into a dictionary comprehension that iterates over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_iters()[0].is_equivalent("vars(self)")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_key().is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the sum of the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i` in `vars(self)`. Use the `getattr()` function for that.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) + getattr(other, i)") or node.is_equivalent("getattr(other, i) + getattr(self, i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
new file mode 100644
index 00000000000..d1cd1755778
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
@@ -0,0 +1,70 @@
+---
+id: 65f9c2c2006feb1428ad2d4c
+title: Step 43
+challengeType: 20
+dashedName: step-43
+---
+
+# --description--
+
+You can unpack a dictionary into keyword arguments by using the `**` operator:
+
+```py
+def spam(a, b):
+ return a + b
+
+my_dict = {a: 11, b: 4}
+
+spam(**my_dict) # 15
+```
+
+Return an instance of the current class by using `__class__` and passing `**kwargs` as the argument.
+
+# --hints--
+
+You should return `self.__class__(**kwargs)` from the `__add__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
new file mode 100644
index 00000000000..3a19c864a1d
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
@@ -0,0 +1,90 @@
+---
+id: 65f9cb678070ca1668898c70
+title: Step 44
+challengeType: 20
+dashedName: step-44
+---
+
+# --description--
+
+In the same way `__add__` is called under the hood when two objects are added together, the `__sub__` method is called implicitly in case of subtraction.
+
+Now, define an empty `__sub__` method and give two parameters: `self`, and `other`. Inside your new method, create an if statement to check if `self` and `other` do not belong to the same class and return `NotImplemented`, as you did previously.
+
+# --hints--
+
+You should define a `__sub__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__sub__")
+ `))
+})
+```
+
+Your `__sub__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_args("self, other")
+ `))
+})
+```
+
+You should create an `if` statement that checks if `self` and `other` does not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+ `))
+})
+```
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
new file mode 100644
index 00000000000..2d452d2413e
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
@@ -0,0 +1,89 @@
+---
+id: 65f9dd6e5a08af19c196c2df
+title: Step 45
+challengeType: 20
+dashedName: step-45
+---
+
+# --description--
+
+The vector resulting from the subtraction of one vector from another is obtained by calculating the difference of each of their components. For example, subtracting `(2, 4)` from `(7, 3)` generates a third vector `(5, -1)`, where `5` is the difference between `7` and `2` and `-1` is the difference between `3` and `4`.
+
+As you did before inside the `__add__` method, declare a `kwargs` variable after the `if` statement. Assign it a dictionary comprehension that iterates through the object attributes and creates a key-value pair for each key `i`, where the key is the same key as the current iteration and its value is the difference between the values of the `i` attributes of two operands.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it a dictionary comprehension that iterates over the object attributes.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_iters()[0]
+node.is_equivalent("vars(self)") or node.is_equivalent("self.__dict__")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over the object attributes.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_key().is_equivalent("i")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the difference between the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i`.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) - getattr(other, i)") or node.is_equivalent("self.__getattribute__(i) - other.__getattribute__(i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
new file mode 100644
index 00000000000..095bce27c7c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
@@ -0,0 +1,65 @@
+---
+id: 65f9dfd2e75e291a38695f13
+title: Step 46
+challengeType: 20
+dashedName: step-46
+---
+
+# --description--
+
+Finally, return a new vector object. Use `__class__` and unpack `kwargs` to instantiate the new vector.
+
+# --hints--
+
+You should return a new vector using `__class__` and unpacking `kwargs` from the `__sub__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
new file mode 100644
index 00000000000..c5cb7742541
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
@@ -0,0 +1,67 @@
+---
+id: 65f9e0a578b22c1a736f3d82
+title: Step 47
+challengeType: 20
+dashedName: step-47
+---
+
+# --description--
+
+Modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+# --hints--
+
+You should modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v2 = R2Vector(x=0.5, y=1.25)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
new file mode 100644
index 00000000000..1d277671da4
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
@@ -0,0 +1,67 @@
+---
+id: 65fa8d5cf0ef3b141010f5d8
+title: Step 48
+challengeType: 20
+dashedName: step-48
+---
+
+# --description--
+
+It's time to verify that the addition and subtraction operations work as expected. Declare another variable `v3` and assign it the sum of `v1` plus `v2`.
+
+# --hints--
+
+You should declare a variable `v3` and assign it the sum of `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v3 = v1 + v2") or _Node(_code).has_stmt("v3 = v2 + v1")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
new file mode 100644
index 00000000000..87ddac5ea5f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
@@ -0,0 +1,64 @@
+---
+id: 65fa8df56a0e2c149b4d24fe
+title: Step 49
+challengeType: 20
+dashedName: step-49
+---
+
+# --description--
+
+Next, check the new vector by printing the following f-string `f'v1 + v2 = {v3}'`.
+
+# --hints--
+
+You should print `f'v1 + v2 = {v3}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 + v2 = {v3}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
new file mode 100644
index 00000000000..e526a9cd4cc
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
@@ -0,0 +1,77 @@
+---
+id: 65fa9402d1fb5516aa42159d
+title: Step 50
+challengeType: 20
+dashedName: step-50
+---
+
+# --description--
+
+Feel free to modify `v3` so that it sums an `R2Vector` instance with an object of a different type, such as an integer or a string. You will be able to see a `TypeError` message printed on the console.
+
+Then, restore the original line and create a new variable `v4`. Assign the difference between `v1` and `v2` to your new variable and print the result following the same structure as the previous f-string.
+
+# --hints--
+
+You should declare a variable `v4` and assign it the difference between `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v4 = v1 - v2")
+ `))
+})
+```
+
+You should print `f'v1 - v2 = {v4}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 - v2 = {v4}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
new file mode 100644
index 00000000000..17afd8a185f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
@@ -0,0 +1,85 @@
+---
+id: 65fa9e1b6c6db919385359ec
+title: Step 51
+challengeType: 20
+dashedName: step-51
+---
+
+# --description--
+
+The special method `__mul__` can be implemented to specify what should happen when the current instance is multiplied by another object.
+
+Create an empty `__mul__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `__mul__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__mul__")
+ `))
+})
+```
+
+Your `__mul__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__mul__").has_args("self, other")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
new file mode 100644
index 00000000000..0a18b8b69d1
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
@@ -0,0 +1,94 @@
+---
+id: 65faaed8f7a9772f023ea816
+title: Step 52
+challengeType: 20
+dashedName: step-52
+---
+
+# --description--
+
+Vectors can be multiplied by a *scalar*, i.e. a number that multiplies each single component. The result of scalar multiplication is a vector with the same orientation as the original vector but a different magnitude.
+
+Implement the scalar multiplication by checking if `other` is either an `int` or a `float`. If it is, return a new instance of the current class that has each component of the starting vector multiplied by `other`. This will be the vector resulting from the scalar multiplication.
+
+Make sure the methods can be applied to compute the scalar multiplication of vectors with any number of dimensions.
+
+# --hints--
+
+Your method should return a new instance of the current class only when the type of `other` is either `int` or `float`.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=0, y=0)
+v2 = R3Vector(x=0, y=0, z=0)
+types = ["", True, [], {}]
+assert all((v1 * i) is None for i in types)
+types = [1, 1.0]
+assert all(type(v1 * i) is type(v1) for i in types)
+assert all(type(v2 * i) is type(v2) for i in types)
+`) })
+```
+
+The vector resulting from the scalar multiplication should have each component of the starting vector multiplied by the scalar.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=1, y=1.5)
+v2 = R3Vector(x=2.2, y=3, z=-1)
+assert vars(v1 * 3) == vars(R2Vector(x=3, y=4.5))
+assert vars(v2 * (-2.0)) == vars(R3Vector(x=-4.4, y=-6.0, z=2.0))
+`) })
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
new file mode 100644
index 00000000000..bcf1d3d0b55
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
@@ -0,0 +1,79 @@
+---
+id: 65fc87e19930a503e5f05500
+title: Step 53
+challengeType: 20
+dashedName: step-53
+---
+
+# --description--
+
+A vector can be multiplied by another vector, too. This operation is called *dot product*, or *scalar product*.
+
+Create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+You are going to implement the dot product inside this block during the next step.
+
+# --hints--
+
+You should create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__mul__").find_ifs()[0].find_conditions()[1]
+node.is_equivalent("type(self) == type(other)") or node.is_equivalent("type(other) == type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
new file mode 100644
index 00000000000..21e11cbc791
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
@@ -0,0 +1,87 @@
+---
+id: 65fc899d77495504d6deeccc
+title: Step 54
+challengeType: 20
+dashedName: step-54
+---
+
+# --description--
+
+The scalar product between two vectors $\mathbf{a}$ and $\mathbf{b}$ is indicated as:
+
+\\( \mathbf{a} \cdot \mathbf{b} = a_1 \cdot b_1 + a_2 \cdot b_2 + \ldots + a_n \cdot b_n = \sum_{i=1}^{n} a_i \cdot b_i \\)
+
+Where each component of $\mathbf{a}$ is multiplied by the correspondent component of $\mathbf{b}$, and all the products are summed together, resulting in a number.
+
+Within the `elif` clause, implement the above formula to compute the result of a scalar product and return the result. Remember that your implementation must be valid for any vector, independently from the number of components, when the method is inherited.
+
+# --hints--
+
+You should implement the scalar product calculation and return the result inside the `elif` body of your `__mul__` method.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+v3 = R3Vector(x=2, y=3, z=1.5)
+v4 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1*v2 == 4.75 and v3*v4 == 7.0
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
new file mode 100644
index 00000000000..7d818367bf8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
@@ -0,0 +1,78 @@
+---
+id: 65fc8e7c766ab1070213aadb
+title: Step 55
+challengeType: 20
+dashedName: step-55
+---
+
+# --description--
+
+In case `other` is not an integer, a floating point number, or another instance of the current class, no product can be computed.
+
+After the `elif` clause, return `NotImplemented`.
+
+# --hints--
+
+You should return `NotImplemented` after the `elif` clause.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__mul__").has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
new file mode 100644
index 00000000000..f0cc7d866b4
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
@@ -0,0 +1,83 @@
+---
+id: 65fc8fa7e7860407ab479bf0
+title: Step 56
+challengeType: 20
+dashedName: step-56
+---
+
+# --description--
+
+It's time to test the multiplication. Declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
+Then, call the `print` function and pass it the following f-string: `f'v1 * 3 = {v5}'`.
+
+# --hints--
+
+You should declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * 3")`)) })
+```
+
+You should print the f-string `f'v1 * 3 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * 3 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
new file mode 100644
index 00000000000..603375e34cc
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
@@ -0,0 +1,87 @@
+---
+id: 65fd681b20b7e45f55def415
+title: Step 57
+challengeType: 20
+dashedName: step-57
+---
+
+# --description--
+
+The scalar multiplication works fine. Now, modify the assignment of `v5` to be the dot product `v1 * v2`. Also, update the `print` call.
+
+Before doing that, feel free to experiment and multiply `v1` by an object of invalid type to see the error message printed on the console.
+
+
+# --hints--
+
+You should update the assignment of `v5` assigning it the scalar product `v1 * v2`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * v2")`)) })
+```
+
+You should update your `print` call to print the f-string `f'v1 * v2 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * v2 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * 3
+print(f'v1 * 3 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
new file mode 100644
index 00000000000..3773c95a395
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9250db0d6b8198cf29ef
+title: Step 58
+challengeType: 20
+dashedName: step-58
+---
+
+# --description--
+
+The `__eq__` method can be implemented to specify what should happen in case the comparison operator (`==`) is used to compare an object with something else.
+
+Within the `R2Vector` class, create an `__eq__` method and give it two parameters: `self` and `other`.
+
+# --hints--
+
+You should define a `__eq__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__eq__")`)) })
+```
+
+Your `__eq__` method should take two parameters: `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
new file mode 100644
index 00000000000..5d2d8cfc678
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
@@ -0,0 +1,88 @@
+---
+id: 65fd95c23beef982af29004c
+title: Step 59
+challengeType: 20
+dashedName: step-59
+---
+
+# --description--
+
+You want to compare two vectors, only when they belong to the same class. For that create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented` in that case.
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
new file mode 100644
index 00000000000..c3bea995dc8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
@@ -0,0 +1,91 @@
+---
+id: 65fd97f3c1b4c4839bdeb8d2
+title: Step 60
+challengeType: 20
+dashedName: step-60
+---
+
+# --description--
+
+To compare two vectors, you are going to check that each component of the first vector is equal to the same component of the second vector.
+
+After the `if` statement you created in the previous step, return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+# --hints--
+
+The `__eq__` method should return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1 == v2 and not v1 == v3 and v4 == v5 and not v5 == v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
new file mode 100644
index 00000000000..a7f5d701215
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
@@ -0,0 +1,102 @@
+---
+id: 65fd9aa649f6cc84631882a9
+title: Step 61
+challengeType: 20
+dashedName: step-61
+---
+
+# --description--
+
+The `__ne__` method is called under the hood when the `!=` operator is used. Define a `__ne__` method with two parameters `self` and `other`. From your new method, return the opposite of `self == other`.
+
+# --hints--
+
+You should define a `__ne__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ne__")`)) })
+```
+
+Your `__ne__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ne__").has_args("self, other")`)) })
+```
+
+The `__ne__` method should return `False` if each attribute of the current instance is equal to the same attribute of `other` and `True` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+not v1 != v2 and v1 != v3 and not v4 != v5 and v5 != v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
new file mode 100644
index 00000000000..8dc85c4a70b
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
@@ -0,0 +1,86 @@
+---
+id: 65fd9c6e49d7cd8513ab1005
+title: Step 62
+challengeType: 20
+dashedName: step-62
+---
+
+# --description--
+
+At the end of your code, use the equality operator to compare `v1` and `R2Vector(x=2, y=3)` and print the result.
+
+# --hints--
+
+You should print the result of comparing `v1` and `R2Vector(x=2, y=3)` using the equality operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 == R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) == v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
new file mode 100644
index 00000000000..b488bbcf86f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9d6203afea85931094c9
+title: Step 63
+challengeType: 20
+dashedName: step-63
+---
+
+# --description--
+
+The comparison returns `True`, since the two vectors have the same components. Now, modify the argument of the `print` call you added in the previous step to use the inequality operator.
+
+# --hints--
+
+You should modify the `print` call you added in the previous step using the inequality operator to compare `v1` and `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) != v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 == R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
new file mode 100644
index 00000000000..fbc628b1a0c
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
@@ -0,0 +1,97 @@
+---
+id: 65fd9e2c56ff19862dfb8cbb
+title: Step 64
+challengeType: 20
+dashedName: step-64
+---
+
+# --description--
+
+The `__lt__` method is called under the hood when the `<` operator is used to compare an object with something else.
+
+Add an empty `__lt__` method and give it two parameters: `self`, `other`.
+
+# --hints--
+
+You should define a `__lt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__lt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
new file mode 100644
index 00000000000..1b50fbea3d0
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
@@ -0,0 +1,100 @@
+---
+id: 65fdc3c8478ee70fc7966151
+title: Step 65
+challengeType: 20
+dashedName: step-65
+---
+
+# --description--
+
+In the same way you did before for the `__eq__` method, create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
new file mode 100644
index 00000000000..cd38c9db1b5
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
@@ -0,0 +1,91 @@
+---
+id: 65fdc496f4440e1055a2ac1b
+title: Step 66
+challengeType: 20
+dashedName: step-66
+---
+
+# --description--
+
+After the `if` statement, return the result of comparing the norm of the current instance with the norm of `other` using the less than operator.
+
+# --hints--
+
+The `__lt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the `<` operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_return("self.norm() < other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
new file mode 100644
index 00000000000..2ce64a91350
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
@@ -0,0 +1,122 @@
+---
+id: 6601918b44a11b4a8c986c6a
+title: Step 67
+challengeType: 20
+dashedName: step-67
+---
+
+# --description--
+
+The `__gt__` method is called under the hood when the `>` operator is used to compare an object with something else.
+
+After the `__lt__` method, in the same way you did for `__lt__`, implement the `__gt__` method. Pay attention to use the appropriate operator.
+
+# --hints--
+
+You should define a `__gt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__gt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_args("self, other")`)) })
+```
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+The `__gt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the greater than operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_return("self.norm() > other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
new file mode 100644
index 00000000000..0e7af024e72
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
@@ -0,0 +1,111 @@
+---
+id: 66019258a7c71d4ae50da42e
+title: Step 68
+challengeType: 20
+dashedName: step-68
+---
+
+# --description--
+
+There are still two possible comparisons to implement. The `__le__` method is called when the `<=` operator is used to compare two objects.
+
+Define a `__le__` method with `self` and `other` as the parameters and make it return the opposite of `self > other`.
+
+# --hints--
+
+You should define a `__le__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__le__")`)) })
+```
+
+Your `__le__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_args("self, other")`)) })
+```
+
+Your `__le__` method return the opposite of `self > other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_return("not self > other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
new file mode 100644
index 00000000000..090a4c25718
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
@@ -0,0 +1,116 @@
+---
+id: 66019319edb1cb4b57d3a793
+title: Step 69
+challengeType: 20
+dashedName: step-69
+---
+
+# --description--
+
+The last method you need is `__ge__`, which is called when the `>=` is used to compare two objects.
+
+Define a `__ge__` method with `self` and `other` as the parameters and make it return the opposite of `self < other`.
+
+# --hints--
+
+You should define a `__ge__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ge__")`)) })
+```
+
+Your `__ge__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_args("self, other")`)) })
+```
+
+Your `__ge__` method should return the opposite of `self < other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_return("not self < other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
new file mode 100644
index 00000000000..feda5e7fb02
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
@@ -0,0 +1,104 @@
+---
+id: 660193a2a71faa4bd8f10970
+title: Step 70
+challengeType: 20
+dashedName: step-70
+---
+
+# --description--
+
+Feel free to play around with the new comparison operations you implemented. Then, remove your last `print` call.
+
+
+# --hints--
+
+You should not have `print(v1 != R2Vector(x=2, y=3))` in your code.
+
+```js
+({test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
new file mode 100644
index 00000000000..6690882d473
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
@@ -0,0 +1,111 @@
+---
+id: 66019977710caa516276c0a8
+title: Step 71
+challengeType: 20
+dashedName: step-71
+---
+
+# --description--
+
+The *cross product*, or *vector product*, is defined between 3-dimensional vectors and results in a third vector perpendicular to both of them.
+
+The `R3Vector` class inherits from `R2Vector`, meaning it has access to all the methods and properties defined in `R2Vector`. A child class can implement additional features. You already saw a way to change the implementation of a method. Now, you are going to give the child class `R3Vector` a new method instead.
+
+Within the `R3Vector` class, define a `cross` method and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `cross` method within the `R3Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").has_function("cross")`)) })
+```
+
+Your `cross` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
new file mode 100644
index 00000000000..f4245103e64
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
@@ -0,0 +1,114 @@
+---
+id: 6601a7eb860fb8546516674d
+title: Step 72
+challengeType: 20
+dashedName: step-72
+---
+
+# --description--
+
+Create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
new file mode 100644
index 00000000000..11c27b74700
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
@@ -0,0 +1,105 @@
+---
+id: 6601a88a6e2ccc550d7d7208
+title: Step 73
+challengeType: 20
+dashedName: step-73
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_variable("kwargs").is_equivalent("kwargs = {}")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
new file mode 100644
index 00000000000..4369122717f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
@@ -0,0 +1,117 @@
+---
+id: 6601a8fb2e993b55912f9e9f
+title: Step 74
+challengeType: 20
+dashedName: step-74
+---
+
+# --description--
+
+The dot product between two 3D vectors \\( \mathbf{a} \\) and \\( \mathbf{b} \\) can be computed as it follows:
+
+\\[ \mathbf{a} \times \mathbf{b} = \begin{pmatrix} a_yb_z - a_zb_y \\\ a_zb_x - a_xb_z \\\ a_xb_y - a_yb_x \end{pmatrix}
+ \\]
+
+Where the resulting vector is represented as a column vector.
+
+Implement the formula above to compute the dot product between two 3-dimensional vectors and return the resulting vector from the `cross()` method.
+
+# --hints--
+
+The `cross()` method should return a new `R3Vector` instance resulting from the dot product computation.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+v1.cross(v2) == R3Vector(x=4.75, y=-3.5, z=1.0) and v2.cross(v1) == R3Vector(x=-4.75, y=3.5, z=-1.0) and v1.cross(v1) == R3Vector(x=0, y=0, z=0)
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
new file mode 100644
index 00000000000..2093aecdc16
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
@@ -0,0 +1,119 @@
+---
+id: 6601ab2809898f57591f2f7f
+title: Step 75
+challengeType: 20
+dashedName: step-75
+---
+
+# --description--
+
+Now, modify the assignments of `v1` and `v2`. Turn them into `R3Vector` instances and pass `z=1` and `z=2` to `v1` and `v2`, respectively.
+
+# --hints--
+
+You should modify the assignment of `v1` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R3Vector(x=2, y=3, z=1)")`)) })
+```
+
+You should modify the assignment of `v2` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=0.5, y=1.25, z=2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+--fcc-editable-region--
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
new file mode 100644
index 00000000000..c7d46d75ac7
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
@@ -0,0 +1,113 @@
+---
+id: 6601ac48a2ee6b59e6a5060d
+title: Step 76
+challengeType: 20
+dashedName: step-76
+---
+
+# --description--
+
+Call `cross()` on `v1` and pass `v2` as the argument. Assign this call to a new variable `v6`.
+
+# --hints--
+
+You should declare a variable named `v6` and assign it a call to the `cross()` method on `v1` passing it `v2` as the `argument`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v6").is_equivalent("v6 = v1.cross(v2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
new file mode 100644
index 00000000000..48e3a3a353f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
@@ -0,0 +1,210 @@
+---
+id: 6601ad0fe415985a5c83f3cc
+title: Step 77
+challengeType: 20
+dashedName: step-77
+---
+
+# --description--
+
+As a final step, call the `print` function and pass it the f-string `f'v1 x v2 = {v6}'` to see the output of the dot product.
+
+With that, you have completed the vector space project. Well done!
+
+# --hints--
+
+You should print `f'v1 x v2 = {v6}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 x v2 = {v6}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+print(f'v1 x v2 = {v6}')
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
new file mode 100644
index 00000000000..d25b1a4c723
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
@@ -0,0 +1,53 @@
+---
+id: 6659875502b6d7765498f324
+title: Step 26
+challengeType: 20
+dashedName: step-26
+---
+
+# --description--
+
+Use f-strings to modify your `print` calls so that they result in the output `v1 = (2, 3)` and `v2 = (2, 2, 3)`, respectively.
+
+# --hints--
+
+You should use an f-string to interpolate `v1` and generate the output `v1 = (2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}')")`)) })
+```
+
+You should use an f-string to interpolate `v2` and generate the output `v2 = (2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
new file mode 100644
index 00000000000..ff34ca74d7f
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
@@ -0,0 +1,51 @@
+---
+id: 66680ddfd0f8c76782923cb0
+title: Step 22
+challengeType: 20
+dashedName: step-22
+---
+
+# --description--
+
+The `norm()` method is returning the correct values, but there's still something you can improve: readability.
+
+The `vars()` built-in function takes an object as its argument and returns the `__dict__` attribute of that object.
+
+Instead of directly accessing the `__dict__` attribute of `self`, modify the `norm` method to use the `vars()` function.
+
+# --hints--
+
+You should modify your `norm` method to use `vars(self)` instead of `self.__dict__`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in vars(self).values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
new file mode 100644
index 00000000000..0dc691b65b8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
@@ -0,0 +1,61 @@
+---
+id: 66682150151af29efec9727d
+title: Step 33
+challengeType: 20
+dashedName: step-33
+---
+
+# --description--
+
+The `__getattribute__` method is called under the hood any time you try to access an instance attribute. If the attribute is not found at the instance level, the method will search for it at the class level, and eventually in parent classes.
+
+Inside your class, define a `__getattribute__` method with two parameters, `self` and `attr`, and make it return the string `'calling __getattribute__'`. You'll override momentarily the default implementation just to see how the attribute access works.
+
+# --hints--
+
+You should define a method named `__getattribute__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_args("self, attr")`)) })
+```
+
+Your `__getattribute__` method should return the string `'calling __getattribute__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_return("'calling __getattribute__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
new file mode 100644
index 00000000000..80410b55106
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
@@ -0,0 +1,61 @@
+---
+id: 666826f258fda1ab3396a509
+title: Step 34
+challengeType: 20
+dashedName: step-34
+---
+
+# --description--
+
+Now, print the result of accessing the `x` attribute of `v1` both with the dot operator and the `getattr()` built-in function.
+
+You will see that `__getattribute__` is called in both cases.
+
+# --hints--
+
+You should print the `x` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.x)") and n.has_call("print(getattr(v1, 'x'))")) or n.has_call("print(v1.x, getattr(v1, 'x'))") or n.has_call("print(getattr(v1, 'x'), v1.x)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
new file mode 100644
index 00000000000..8c3a650010b
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
@@ -0,0 +1,69 @@
+---
+id: 666827a6fd0dbaafe8330ea6
+title: Step 35
+challengeType: 20
+dashedName: step-35
+---
+
+# --description--
+
+`__getattr__` is another special method that plays a role in accessing attributes.
+
+The default implementation of `__getattribute__` is to raise an `AttributeError` when the requested attribute is not an instance attribute or it is not present in the class tree.
+
+In that case, `__getattr__` is called if defined by the class. You can consider it as a sort of fallback when the usual attribute accessing procedure fails.
+
+Turn the `__getattribute__` method into `__getattr__` and modify the string returned by the method into `'calling __getattr__'`.
+
+# --hints--
+
+You should define a method named `__getattr__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_args("self, attr")`)) })
+```
+
+Your `__getattr__` method should return the string `'calling __getattr__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_return("'calling __getattr__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+print(v1.x)
+print(getattr(v1, 'x'))
+
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
new file mode 100644
index 00000000000..598c9822428
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
@@ -0,0 +1,62 @@
+---
+id: 666832e427d70bc5219dc62a
+title: Step 36
+challengeType: 20
+dashedName: step-36
+---
+
+# --description--
+
+As you can see from the output, although you defined `__getattr__` in your class, this method is not called yet. This happens because the default attribute access occurs through `__getattribute__`. Therefore, you can see the attribute value printed on the terminal.
+
+Now modify the last two lines of code to access the `z` attribute of `v1` in both your `print()` calls. This time, you are going to access an attribute that `v1` does not have. As a result, `__getattribute__` will raise an error and `__getattr__` will be called.
+
+# --hints--
+
+You should modify your code to print the `z` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.z)") and n.has_call("print(getattr(v1, 'z'))")) or n.has_call("print(v1.z, getattr(v1, 'z'))") or n.has_call("print(getattr(v1, 'z'), v1.z)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+print(v1.x)
+print(getattr(v1, 'x'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
new file mode 100644
index 00000000000..bb55eb1f3a8
--- /dev/null
+++ b/curriculum/challenges/chinese-traditional/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
@@ -0,0 +1,75 @@
+---
+id: 6668374ed18b7fce10259cb3
+title: Step 37
+challengeType: 20
+dashedName: step-37
+---
+
+# --description--
+
+Now that you have an idea of how the attribute access work, remove the last two lines of your code together with the `__getattr__` method.
+
+Then, restore the `print()` calls you commented out before and delete the second argument from both of them.
+
+# --hints--
+
+You should not have a `__getattr__` method.
+
+```js
+({ test: () => assert.isFalse(runPython(`_Node(_code).find_class("R2Vector").has_function("__getattr__")`)) })
+```
+
+You should not have `print(v1.z)`and `print(getattr(v1, 'z'))` in your code.
+
+```js
+({ test: () => assert.isFalse(runPython(`
+n = _Node(_code)
+n.has_call("print(v1.z)") or n.has_call("print(getattr(v1, 'z'))")
+`)) })
+```
+
+You should restore the `print()` calls you commented out before and remove the second argument from both of them.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).has_call("print(f'v1 = {v1}')") and _Node(_code).has_call("print(f'v2 = {v2}')")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+print(v1.z)
+print(getattr(v1, 'z'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md b/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
deleted file mode 100644
index 632abe728dd..00000000000
--- a/curriculum/challenges/chinese-traditional/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
+++ /dev/null
@@ -1,344 +0,0 @@
----
-id: 62aa1fed3d4e873366ff3131
-title: Step 150
-challengeType: 0
-dashedName: step-150
----
-
-# --description--
-
-In your `attack` function, below the `health` variable, create an `if` statement. Set the condition to call the `isMonsterHit` function.
-
-# --hints--
-
-You should add an `if` statement which calls `isMonsterHit` in the condition.
-
-```js
-assert.match(attack.toString(), /if\s*\(\s*isMonsterHit\s*\(\s*\)/)
-```
-
-# --seed--
-
-## --seed-contents--
-
-```html
-
-
-
-
-
-
+
+Within the `Vector` class, create an `__init__` method and give it three parameters, `self`, `x`, and `y`.
+
+# --hints--
+
+You should define an `__init__` method inside the `Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").has_function("__init__")`)) })
+```
+
+Your `__init__` method should take three parameters: `self`, `x`, and `y`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").find_function("__init__").has_args("self, x, y")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ pass
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
new file mode 100644
index 00000000000..62ab349a8db
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
@@ -0,0 +1,38 @@
+---
+id: 65f055b9190fc41ca35549b8
+title: Step 3
+challengeType: 20
+dashedName: step-3
+---
+
+# --description--
+
+Python offers various methods that include both a leading and trailing double underscore in their names. You may already be familiar with some, such as `__init__` and `__str__`. These methods, which follow the `__
+
+So far, you created a 2-dimensional vector. You want to be able to represent vectors with a different number of dimensions without rewriting the necessary code for each specific case. For that, you will use inheritance.
+
+Start by renaming the `Vector` class into `R2Vector` to specify that this class is going to deal with 2-dimensional vectors. Remember to modify the instantiation of `v1`, too.
+
+# --hints--
+
+You should rename the `Vector` class into `R2Vector`. Remember to modify the instantiation of `v1`, too.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+v1 = Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
new file mode 100644
index 00000000000..62b7794dba3
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
@@ -0,0 +1,70 @@
+---
+id: 65f40051d6b09a139f253e8e
+title: Step 12
+challengeType: 20
+dashedName: step-12
+---
+
+# --description--
+
+Inheritance enables you to define a class from an existing one. The new class, called child, inherits all the methods and properties of the existing class, called parent.
+
+```py
+class Tree:
+ def sprout(self):
+ print('Making new leaves!')
+
+class Oak(Tree):
+ pass
+
+Oak().sprout() # Output: Making new leaves!
+```
+
+In the example above, the child class `Oak` inherits from `Tree` and inherits the `sprout` method from the parent class `Tree`.
+
+Create a new class named `R3Vector` and follow the example above to make it inherit from the `R2Vector` class.
+
+# --hints--
+
+You should define a new class `R3Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R3Vector")
+ `))
+})
+```
+
+Your new class `R3Vector` should inherit from `R2Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").inherits_from("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
new file mode 100644
index 00000000000..dfdb08a15d3
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
@@ -0,0 +1,56 @@
+---
+id: 65f40401e6ef53173c04e27d
+title: Step 13
+challengeType: 20
+dashedName: step-13
+---
+
+# --description--
+
+Within your new class, declare an `__init__` method. Give it `self`, `x`, `y`, and `z` as the parameters.
+
+# --hints--
+
+You should define an `__init__` method inside your `R3Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").has_function("__init__")
+ `))
+})
+```
+
+Your `__init__` method should have four parameters `self`, `x`, `y`, and `z`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, x, y, z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
new file mode 100644
index 00000000000..f329157bd30
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
@@ -0,0 +1,49 @@
+---
+id: 65f407ea37ad6e181b90462e
+title: Step 14
+challengeType: 20
+dashedName: step-14
+---
+
+# --description--
+
+You could assign each `i` parameter to `self.i` as you did before. Although in this case you have few lines to repeat, one way to avoid this repetition is using the `super()` function. `super()` enables you to refer implicitly to the parent class: `super().__init__(x, y)` calls the `__init__` method of the parent class.
+
+Add a `super().__init__(x, y)` call to your `__init__` method.
+
+# --hints--
+
+You should have a `super().__init__(x, y)` call in your `__init__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_stmt("super().__init__(x, y)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
new file mode 100644
index 00000000000..ecf329fe7e7
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
@@ -0,0 +1,47 @@
+---
+id: 65f40f8af784751c613d638a
+title: Step 15
+challengeType: 20
+dashedName: step-15
+---
+
+# --description--
+
+Now, you need to assign `z` to the `z` attribute of your `R3Vector` object.
+
+# --hints--
+
+You should assign `z` to `self.z` after the `super` call.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").is_ordered("super().__init__(x, y)", "self.z = z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
new file mode 100644
index 00000000000..5a13be02b39
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
@@ -0,0 +1,47 @@
+---
+id: 65f40fdb3579aa1ced28b2eb
+title: Step 16
+challengeType: 20
+dashedName: step-16
+---
+
+# --description--
+
+Create an `R3Vector` instance with `2`, `2`, and `3` as the values of `x`, `y`, and `z`, respectively. Assign the new instance to `v2`.
+
+# --hints--
+
+You should declare a variable `v2` and assign it `R3Vector(2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(2, 2, 3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
new file mode 100644
index 00000000000..c659dbc8460
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
@@ -0,0 +1,72 @@
+---
+id: 65f412c208c3791fee305acf
+title: Step 17
+challengeType: 20
+dashedName: step-17
+---
+
+# --description--
+
+In Python, you can enforce the use of keyword-only arguments by adding a `*` as an additional argument to the function or method signature. Modify both `__init__` methods by adding a `*` as the second parameter (after `self`). Every parameter placed after that will require the use of a keyword argument in the function/method call.
+
+This means that you need to modify the `super().__init__(x, y)` call, too. Do it by giving `x` the value `x`, and `y` the value `y`.
+
+Finally, modify the instantiation of `v1` and `v2` by using keyword arguments.
+
+# --hints--
+
+You should enforce keyword arguments by adding a `*` as the second parameter in both your `__init__` methods.
+
+```js
+({ test: () => {
+ assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__init__").has_args("self, *, x, y")`));
+ assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, *, x, y, z")`));
+} })
+```
+
+You should modify your `super.__init__(x, y)` call to use keyword arguments.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").find_body().is_equivalent("super().__init__(x=x, y=y)\\nself.z = z")`)) })
+```
+
+You should modify the assignment of `v1` to be `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R2Vector(x=2, y=3)")`)) })
+```
+
+You should modify the assignment of `v2` to be `R3Vector(x=2, y=2, z=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=2, y=2, z=3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+v2 = R3Vector(2, 2, 3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
new file mode 100644
index 00000000000..05cdf4f49a6
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
@@ -0,0 +1,64 @@
+---
+id: 65f4148dea0f802040225e0c
+title: Step 18
+challengeType: 20
+dashedName: step-18
+---
+
+# --description--
+
+Remove the existing `print` calls. Then, as you did before for `v1`, print `v2` and the value returned by `v2.norm()`.
+
+# --hints--
+
+You should not have `print(v1)` and `print(v1.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1.norm())")`));
+ }
+})
+```
+
+You should print `v2` and `v2.norm()`.
+
+```js
+({
+ test: () => {
+ assert(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+print(v1.norm())
+print(v1)
+
+v2 = R3Vector(x=2, y=2, z=3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
new file mode 100644
index 00000000000..411bc02d955
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
@@ -0,0 +1,64 @@
+---
+id: 65f4520e363e2642f8112e33
+title: Step 19
+challengeType: 20
+dashedName: step-19
+---
+
+# --description--
+
+As you can see, something is not quite right. The `norm` and `__str__` methods inherited from `R2Vector` cannot adapt to a 3-dimensional vector. Their implementation has to be more flexible.
+
+Every object in Python has a special attribute named `__dict__`, which is a dictionary that stores the object attributes.
+
+Remove the existing `print` calls. Then, print the `__dict__` attribute of your `v1` and `v2` vectors to see what they look like.
+
+# --hints--
+
+You should not have `print(v2)` and `print(v2.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+You should print the `__dict__` attribute of `v1` and `v2`.
+
+```js
+({ test: () => assert(runPython(`
+(_Node(_code).has_call("print(v1.__dict__)") and _Node(_code).has_call("print(v2.__dict__)")) or _Node(_code).has_call("print(v1.__dict__, v2.__dict__)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v2.norm())
+print(v2)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
new file mode 100644
index 00000000000..2a2c8f28376
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
@@ -0,0 +1,49 @@
+---
+id: 65f4535bbdb28d436ff3ddc9
+title: Step 20
+challengeType: 20
+dashedName: step-20
+---
+
+# --description--
+
+As you can see from the output, `__dict__` contains the values of your instance attributes. Instead of explicitly adding the squares of `self.x` and `self.y`, you are going to iterate over the values stored in `__dict__` to calculate the value of the norm.
+
+Within the `norm` method body, replace the content of the parentheses with a generator expression that elevates each value `val` in `self.__dict__.values()` to the power of `2`. Also, pass that generator expression as the argument to the `sum` function, so that all the squares are added together before calculating the square root.
+
+# --hints--
+
+You should return `sum(val**2 for val in self.__dict__.values())**0.5` from `norm()` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in self.__dict__.values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
new file mode 100644
index 00000000000..bbb82436c52
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
@@ -0,0 +1,53 @@
+---
+id: 65f870003444fb1a2ad171f2
+title: Step 21
+challengeType: 20
+dashedName: step-21
+---
+
+# --description--
+
+Modify the two `print` calls to print the norm of your vectors and verify that the `norm()` method works fine.
+
+# --hints--
+
+You should print `v1.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1.norm())")`)) })
+```
+
+You should print `v2.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v2.norm())")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
new file mode 100644
index 00000000000..22e3cab792e
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
@@ -0,0 +1,61 @@
+---
+id: 65f8709620b2ce1a62608f5a
+title: Step 23
+challengeType: 20
+dashedName: step-23
+---
+
+# --description--
+
+When you need to dynamically access some attributes starting from a string input, the built-in `getattr()` function is what you need. It takes an object as its first argument, and a string containing the attribute name as its second attribute.
+
+Start to fix the `__str__` method by replacing the string returned by `__str__()` with a generator expression that iterates through the object attributes and calls `getattr()` for each attribute `i`.
+
+# --hints--
+
+You should return a generator expression that iterates over `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_iters()[0].is_equivalent("vars(self)")`)) })
+```
+
+You should return a generator expression that uses `i` as the iteration variable.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_targets()[0].is_equivalent("i")`)) })
+```
+
+You should return a generator expression that calls `getattr(self, i)` for each item `i` in `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_expr().is_equivalent("getattr(self, i)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
new file mode 100644
index 00000000000..668bd89de56
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
@@ -0,0 +1,47 @@
+---
+id: 65f8720685ec351abef26740
+title: Step 24
+challengeType: 20
+dashedName: step-24
+---
+
+# --description--
+
+To obtain a proper string representation, call the `tuple()` constructor and pass it the generator expression you wrote in the previous step as the argument.
+
+# --hints--
+
+You should pass the expression returned by the `__str__` method to the `tuple()` constructor.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("tuple(getattr(self, i) for i in vars(self))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return (getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
new file mode 100644
index 00000000000..f687795519e
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
@@ -0,0 +1,47 @@
+---
+id: 65f872a0fe6aa21b456ad4fe
+title: Step 25
+challengeType: 20
+dashedName: step-25
+---
+
+# --description--
+
+Finally, pass the `tuple()` call as the argument to the `str()` function.
+
+# --hints--
+
+You should pass the `tuple()` call you are currently returning from the `__str__` method to the `str()` function.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("str(tuple(getattr(self, i) for i in vars(self)))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return tuple(getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
new file mode 100644
index 00000000000..9f1d1e16d92
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
@@ -0,0 +1,56 @@
+---
+id: 65f8749b13774b1d2e4a7fba
+title: Step 27
+challengeType: 20
+dashedName: step-27
+---
+
+# --description--
+
+While the `__str__` method returns a human-readable string representation of an object, the `__repr__` method is supposed to return the string needed to instantiate the object.
+
+Add a `__repr__` method with a `self` parameter within the `R2Vector` class.
+
+# --hints--
+
+Your `R2Vector` class should have a `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__repr__")`)) })
+```
+
+Your `__repr__` method should have a `self` parameter.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_args("self")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
new file mode 100644
index 00000000000..7f5a3e0f9c9
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
@@ -0,0 +1,74 @@
+---
+id: 65f876d17832001e8e1abb05
+title: Step 28
+challengeType: 20
+dashedName: step-28
+---
+
+# --description--
+
+Declare a variable `arg_list`. Give it the value of a list comprehension that iterates over `key` and `val` for each key-value pair in `vars(self).items()` and computes the f-string `f'{key}={val}'` at each iteration.
+
+# --hints--
+
+You should declare a variable `arg_list`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_variable("arg_list")`)) })
+```
+
+You should assign a list comprehension that iterates over `vars(self).items()` to `arg_list`.
+
+```js
+({ test: () => runPython(`
+import ast
+var = _Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list")
+assert isinstance(var.tree.value, ast.ListComp), "Expected arg_list to be a list comprehension"
+assert (actual := var.find_comp_iters()[0].is_equivalent("vars(self).items()")), f"Expected vars(self).items(), got {actual}"
+`) })
+```
+
+The list comprehension assigned to `arg_list` should use `key` and `val` to iterate over `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_targets()[0].is_equivalent("key, val")
+`)) })
+```
+
+The list comprehension assigned to `arg_list` should compute the string `f'{key}={val}'` for each key-value pair in `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_expr().is_equivalent("f'{key}={val}'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
new file mode 100644
index 00000000000..0c56316394e
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
@@ -0,0 +1,50 @@
+---
+id: 65f93acbb514857003510e79
+title: Step 29
+challengeType: 20
+dashedName: step-29
+---
+
+# --description--
+
+Declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+# --hints--
+
+You should declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("args").is_equivalent("args = ', '.join(arg_list)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
new file mode 100644
index 00000000000..e826611fa57
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
@@ -0,0 +1,52 @@
+---
+id: 65f93b67169a9c703264458a
+title: Step 30
+challengeType: 20
+dashedName: step-30
+---
+
+# --description--
+
+Since the method should return the string to instantiate the object for `R2Vector` as well as `R3Vector` when inherited, you cannot build the string specifying the class name.
+
+You can access the name of a class with `__class__.__name__`. Add a `return` statement to the `__repr__` method and return the string necessary to instantiate the object.
+
+# --hints--
+
+You should use `__class__.__name__` to build the f-string needed to instantiate a vector object and return it from the `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_return("f'{self.__class__.__name__}({args})'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
new file mode 100644
index 00000000000..13682539c2c
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
@@ -0,0 +1,57 @@
+---
+id: 65f93d4647ce2670dc6f095c
+title: Step 31
+challengeType: 20
+dashedName: step-31
+---
+
+# --description--
+
+The `__repr__` method is called under the hood by the `repr` function. Verify that `__repr__` works properly by adding `f'\nrepr = {repr(v1)}'` and `f'\nrepr = {repr(v2)}'` as the second argument to your first and second `print` calls, respectively.
+
+# --hints--
+
+You should add `f'\nrepr = {repr(v1)}'` as the second argument to your `print(f'v1 = {v1}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}', f'\\\\nrepr = {repr(v1)}')")`)) })
+```
+
+You should add `f'\nrepr = {repr(v2)}'` as the second argument to your `print(f'v2 = {v2}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}', f'\\\\nrepr = {repr(v2)}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
new file mode 100644
index 00000000000..a25da243ba9
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
@@ -0,0 +1,56 @@
+---
+id: 65f93e54a9121571dcdd3e79
+title: Step 32
+challengeType: 20
+dashedName: step-32
+---
+
+# --description--
+
+The output is correct, `repr` is giving you the string required to instantiate the objects.
+
+Now comment out both your `print` calls.
+
+# --hints--
+
+You should comment out both your `print()` calls.
+
+```js
+({ test: () => {
+ assert.match(code, /#\s*print\s*\(\s*f('|")v1 = \{\s*v1\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v1\s*\)\s*\}\2\s*\)/);
+ assert.match(code, /#\s*print\s*\(\s*f('|")v2 = \{\s*v2\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v2\s*\)\s*\}\2\s*\)/);
+} })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
new file mode 100644
index 00000000000..86133f41f32
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
@@ -0,0 +1,62 @@
+---
+id: 65f9b17a638f0d0dcce8c354
+title: Step 38
+challengeType: 20
+dashedName: step-38
+---
+
+# --description--
+
+To create a vector space, you need to define how vectors should behave in several cases. Vectors can be added, forming a new vector.
+
+The special method `__add__` can be implemented to override what happens by default when two objects are added together using the `+` operator.
+
+Right now, trying to add two instances of `R2Vector` or `R3Vector` would raise an exception. Create an empty `__add__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define an `__add__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__add__")`)) })
+```
+
+Your `__add__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
new file mode 100644
index 00000000000..f90c14fe57b
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b486989cb90ff3e77ac8
+title: Step 39
+challengeType: 20
+dashedName: step-39
+---
+
+# --description--
+
+The `other` parameter of your `__add__` method represents the operand placed at the right side of the `+` operator in an addition operation.
+
+You want to verify that the right-hand operand is not an object of the same class as the left-hand operand (i.e. `self`). Create an `if` statement that verifies that by checking the type of the operands.
+
+# --hints--
+
+You should create an `if` statement that checks if `type(self)` and `type(other)` are different.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
new file mode 100644
index 00000000000..1fa83e0f9aa
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b9710cca621244d3bde1
+title: Step 40
+challengeType: 20
+dashedName: step-40
+---
+
+# --description--
+
+In Python, `NotImplemented` is a special value used to indicate that an operation is not implemented for a specific case.
+
+`NotImplemented` does not raise an exception immediately. Instead, it signals to ask to the other operand how to perform the operation. If the request cannot be satisfied, a `TypeError` is returned by default.
+
+Because you want to be able to sum two vectors only if they belong to the same class, return `NotImplemented` from the `if` statement you created in the previous step.
+
+# --hints--
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
new file mode 100644
index 00000000000..9df77e46895
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
@@ -0,0 +1,58 @@
+---
+id: 65f9bb7c0d524612b2a88a4b
+title: Step 41
+challengeType: 20
+dashedName: step-41
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_stmt("kwargs = {}")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
new file mode 100644
index 00000000000..f5d28e43bd6
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
@@ -0,0 +1,92 @@
+---
+id: 65f9bc10a9fb1612e066e9e8
+title: Step 42
+challengeType: 20
+dashedName: step-42
+---
+
+# --description--
+
+When adding two vectors, each component of one vector is added to the same component of the other vector. For example, adding `(1, 2)` and `(2, 4)` generates a third vector `(3, 6)`, where `3` is the sum of `1` and `2` and `6` is the sum of `2` and `4`.
+
+The `kwargs` dictionary will contain the key-value pairs needed to instantiate a new vector of the same class of the two vectors added together.
+
+Turn the empty dictionary into a dictionary comprehension that iterates through `vars(self)` and for each key (`i`) creates a key-value pair, where the key is the same key of the current iteration and its value is the sum of the values of the `i` attributes of the two operands.
+
+# --hints--
+
+You should turn the empty dictionary assigned to `kwargs` into a dictionary comprehension that iterates over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_iters()[0].is_equivalent("vars(self)")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_key().is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the sum of the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i` in `vars(self)`. Use the `getattr()` function for that.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) + getattr(other, i)") or node.is_equivalent("getattr(other, i) + getattr(self, i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
new file mode 100644
index 00000000000..d1cd1755778
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
@@ -0,0 +1,70 @@
+---
+id: 65f9c2c2006feb1428ad2d4c
+title: Step 43
+challengeType: 20
+dashedName: step-43
+---
+
+# --description--
+
+You can unpack a dictionary into keyword arguments by using the `**` operator:
+
+```py
+def spam(a, b):
+ return a + b
+
+my_dict = {a: 11, b: 4}
+
+spam(**my_dict) # 15
+```
+
+Return an instance of the current class by using `__class__` and passing `**kwargs` as the argument.
+
+# --hints--
+
+You should return `self.__class__(**kwargs)` from the `__add__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
new file mode 100644
index 00000000000..3a19c864a1d
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
@@ -0,0 +1,90 @@
+---
+id: 65f9cb678070ca1668898c70
+title: Step 44
+challengeType: 20
+dashedName: step-44
+---
+
+# --description--
+
+In the same way `__add__` is called under the hood when two objects are added together, the `__sub__` method is called implicitly in case of subtraction.
+
+Now, define an empty `__sub__` method and give two parameters: `self`, and `other`. Inside your new method, create an if statement to check if `self` and `other` do not belong to the same class and return `NotImplemented`, as you did previously.
+
+# --hints--
+
+You should define a `__sub__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__sub__")
+ `))
+})
+```
+
+Your `__sub__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_args("self, other")
+ `))
+})
+```
+
+You should create an `if` statement that checks if `self` and `other` does not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+ `))
+})
+```
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
new file mode 100644
index 00000000000..2d452d2413e
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
@@ -0,0 +1,89 @@
+---
+id: 65f9dd6e5a08af19c196c2df
+title: Step 45
+challengeType: 20
+dashedName: step-45
+---
+
+# --description--
+
+The vector resulting from the subtraction of one vector from another is obtained by calculating the difference of each of their components. For example, subtracting `(2, 4)` from `(7, 3)` generates a third vector `(5, -1)`, where `5` is the difference between `7` and `2` and `-1` is the difference between `3` and `4`.
+
+As you did before inside the `__add__` method, declare a `kwargs` variable after the `if` statement. Assign it a dictionary comprehension that iterates through the object attributes and creates a key-value pair for each key `i`, where the key is the same key as the current iteration and its value is the difference between the values of the `i` attributes of two operands.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it a dictionary comprehension that iterates over the object attributes.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_iters()[0]
+node.is_equivalent("vars(self)") or node.is_equivalent("self.__dict__")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over the object attributes.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_key().is_equivalent("i")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the difference between the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i`.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) - getattr(other, i)") or node.is_equivalent("self.__getattribute__(i) - other.__getattribute__(i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
new file mode 100644
index 00000000000..095bce27c7c
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
@@ -0,0 +1,65 @@
+---
+id: 65f9dfd2e75e291a38695f13
+title: Step 46
+challengeType: 20
+dashedName: step-46
+---
+
+# --description--
+
+Finally, return a new vector object. Use `__class__` and unpack `kwargs` to instantiate the new vector.
+
+# --hints--
+
+You should return a new vector using `__class__` and unpacking `kwargs` from the `__sub__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
new file mode 100644
index 00000000000..c5cb7742541
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
@@ -0,0 +1,67 @@
+---
+id: 65f9e0a578b22c1a736f3d82
+title: Step 47
+challengeType: 20
+dashedName: step-47
+---
+
+# --description--
+
+Modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+# --hints--
+
+You should modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v2 = R2Vector(x=0.5, y=1.25)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
new file mode 100644
index 00000000000..1d277671da4
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
@@ -0,0 +1,67 @@
+---
+id: 65fa8d5cf0ef3b141010f5d8
+title: Step 48
+challengeType: 20
+dashedName: step-48
+---
+
+# --description--
+
+It's time to verify that the addition and subtraction operations work as expected. Declare another variable `v3` and assign it the sum of `v1` plus `v2`.
+
+# --hints--
+
+You should declare a variable `v3` and assign it the sum of `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v3 = v1 + v2") or _Node(_code).has_stmt("v3 = v2 + v1")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
new file mode 100644
index 00000000000..87ddac5ea5f
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
@@ -0,0 +1,64 @@
+---
+id: 65fa8df56a0e2c149b4d24fe
+title: Step 49
+challengeType: 20
+dashedName: step-49
+---
+
+# --description--
+
+Next, check the new vector by printing the following f-string `f'v1 + v2 = {v3}'`.
+
+# --hints--
+
+You should print `f'v1 + v2 = {v3}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 + v2 = {v3}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
new file mode 100644
index 00000000000..e526a9cd4cc
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
@@ -0,0 +1,77 @@
+---
+id: 65fa9402d1fb5516aa42159d
+title: Step 50
+challengeType: 20
+dashedName: step-50
+---
+
+# --description--
+
+Feel free to modify `v3` so that it sums an `R2Vector` instance with an object of a different type, such as an integer or a string. You will be able to see a `TypeError` message printed on the console.
+
+Then, restore the original line and create a new variable `v4`. Assign the difference between `v1` and `v2` to your new variable and print the result following the same structure as the previous f-string.
+
+# --hints--
+
+You should declare a variable `v4` and assign it the difference between `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v4 = v1 - v2")
+ `))
+})
+```
+
+You should print `f'v1 - v2 = {v4}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 - v2 = {v4}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
new file mode 100644
index 00000000000..17afd8a185f
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
@@ -0,0 +1,85 @@
+---
+id: 65fa9e1b6c6db919385359ec
+title: Step 51
+challengeType: 20
+dashedName: step-51
+---
+
+# --description--
+
+The special method `__mul__` can be implemented to specify what should happen when the current instance is multiplied by another object.
+
+Create an empty `__mul__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `__mul__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__mul__")
+ `))
+})
+```
+
+Your `__mul__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__mul__").has_args("self, other")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
new file mode 100644
index 00000000000..0a18b8b69d1
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
@@ -0,0 +1,94 @@
+---
+id: 65faaed8f7a9772f023ea816
+title: Step 52
+challengeType: 20
+dashedName: step-52
+---
+
+# --description--
+
+Vectors can be multiplied by a *scalar*, i.e. a number that multiplies each single component. The result of scalar multiplication is a vector with the same orientation as the original vector but a different magnitude.
+
+Implement the scalar multiplication by checking if `other` is either an `int` or a `float`. If it is, return a new instance of the current class that has each component of the starting vector multiplied by `other`. This will be the vector resulting from the scalar multiplication.
+
+Make sure the methods can be applied to compute the scalar multiplication of vectors with any number of dimensions.
+
+# --hints--
+
+Your method should return a new instance of the current class only when the type of `other` is either `int` or `float`.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=0, y=0)
+v2 = R3Vector(x=0, y=0, z=0)
+types = ["", True, [], {}]
+assert all((v1 * i) is None for i in types)
+types = [1, 1.0]
+assert all(type(v1 * i) is type(v1) for i in types)
+assert all(type(v2 * i) is type(v2) for i in types)
+`) })
+```
+
+The vector resulting from the scalar multiplication should have each component of the starting vector multiplied by the scalar.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=1, y=1.5)
+v2 = R3Vector(x=2.2, y=3, z=-1)
+assert vars(v1 * 3) == vars(R2Vector(x=3, y=4.5))
+assert vars(v2 * (-2.0)) == vars(R3Vector(x=-4.4, y=-6.0, z=2.0))
+`) })
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
new file mode 100644
index 00000000000..bcf1d3d0b55
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
@@ -0,0 +1,79 @@
+---
+id: 65fc87e19930a503e5f05500
+title: Step 53
+challengeType: 20
+dashedName: step-53
+---
+
+# --description--
+
+A vector can be multiplied by another vector, too. This operation is called *dot product*, or *scalar product*.
+
+Create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+You are going to implement the dot product inside this block during the next step.
+
+# --hints--
+
+You should create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__mul__").find_ifs()[0].find_conditions()[1]
+node.is_equivalent("type(self) == type(other)") or node.is_equivalent("type(other) == type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
new file mode 100644
index 00000000000..21e11cbc791
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
@@ -0,0 +1,87 @@
+---
+id: 65fc899d77495504d6deeccc
+title: Step 54
+challengeType: 20
+dashedName: step-54
+---
+
+# --description--
+
+The scalar product between two vectors $\mathbf{a}$ and $\mathbf{b}$ is indicated as:
+
+\\( \mathbf{a} \cdot \mathbf{b} = a_1 \cdot b_1 + a_2 \cdot b_2 + \ldots + a_n \cdot b_n = \sum_{i=1}^{n} a_i \cdot b_i \\)
+
+Where each component of $\mathbf{a}$ is multiplied by the correspondent component of $\mathbf{b}$, and all the products are summed together, resulting in a number.
+
+Within the `elif` clause, implement the above formula to compute the result of a scalar product and return the result. Remember that your implementation must be valid for any vector, independently from the number of components, when the method is inherited.
+
+# --hints--
+
+You should implement the scalar product calculation and return the result inside the `elif` body of your `__mul__` method.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+v3 = R3Vector(x=2, y=3, z=1.5)
+v4 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1*v2 == 4.75 and v3*v4 == 7.0
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
new file mode 100644
index 00000000000..7d818367bf8
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
@@ -0,0 +1,78 @@
+---
+id: 65fc8e7c766ab1070213aadb
+title: Step 55
+challengeType: 20
+dashedName: step-55
+---
+
+# --description--
+
+In case `other` is not an integer, a floating point number, or another instance of the current class, no product can be computed.
+
+After the `elif` clause, return `NotImplemented`.
+
+# --hints--
+
+You should return `NotImplemented` after the `elif` clause.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__mul__").has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
new file mode 100644
index 00000000000..f0cc7d866b4
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
@@ -0,0 +1,83 @@
+---
+id: 65fc8fa7e7860407ab479bf0
+title: Step 56
+challengeType: 20
+dashedName: step-56
+---
+
+# --description--
+
+It's time to test the multiplication. Declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
+Then, call the `print` function and pass it the following f-string: `f'v1 * 3 = {v5}'`.
+
+# --hints--
+
+You should declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * 3")`)) })
+```
+
+You should print the f-string `f'v1 * 3 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * 3 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
new file mode 100644
index 00000000000..603375e34cc
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
@@ -0,0 +1,87 @@
+---
+id: 65fd681b20b7e45f55def415
+title: Step 57
+challengeType: 20
+dashedName: step-57
+---
+
+# --description--
+
+The scalar multiplication works fine. Now, modify the assignment of `v5` to be the dot product `v1 * v2`. Also, update the `print` call.
+
+Before doing that, feel free to experiment and multiply `v1` by an object of invalid type to see the error message printed on the console.
+
+
+# --hints--
+
+You should update the assignment of `v5` assigning it the scalar product `v1 * v2`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * v2")`)) })
+```
+
+You should update your `print` call to print the f-string `f'v1 * v2 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * v2 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * 3
+print(f'v1 * 3 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
new file mode 100644
index 00000000000..3773c95a395
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9250db0d6b8198cf29ef
+title: Step 58
+challengeType: 20
+dashedName: step-58
+---
+
+# --description--
+
+The `__eq__` method can be implemented to specify what should happen in case the comparison operator (`==`) is used to compare an object with something else.
+
+Within the `R2Vector` class, create an `__eq__` method and give it two parameters: `self` and `other`.
+
+# --hints--
+
+You should define a `__eq__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__eq__")`)) })
+```
+
+Your `__eq__` method should take two parameters: `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
new file mode 100644
index 00000000000..5d2d8cfc678
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
@@ -0,0 +1,88 @@
+---
+id: 65fd95c23beef982af29004c
+title: Step 59
+challengeType: 20
+dashedName: step-59
+---
+
+# --description--
+
+You want to compare two vectors, only when they belong to the same class. For that create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented` in that case.
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
new file mode 100644
index 00000000000..c3bea995dc8
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
@@ -0,0 +1,91 @@
+---
+id: 65fd97f3c1b4c4839bdeb8d2
+title: Step 60
+challengeType: 20
+dashedName: step-60
+---
+
+# --description--
+
+To compare two vectors, you are going to check that each component of the first vector is equal to the same component of the second vector.
+
+After the `if` statement you created in the previous step, return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+# --hints--
+
+The `__eq__` method should return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1 == v2 and not v1 == v3 and v4 == v5 and not v5 == v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
new file mode 100644
index 00000000000..a7f5d701215
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
@@ -0,0 +1,102 @@
+---
+id: 65fd9aa649f6cc84631882a9
+title: Step 61
+challengeType: 20
+dashedName: step-61
+---
+
+# --description--
+
+The `__ne__` method is called under the hood when the `!=` operator is used. Define a `__ne__` method with two parameters `self` and `other`. From your new method, return the opposite of `self == other`.
+
+# --hints--
+
+You should define a `__ne__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ne__")`)) })
+```
+
+Your `__ne__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ne__").has_args("self, other")`)) })
+```
+
+The `__ne__` method should return `False` if each attribute of the current instance is equal to the same attribute of `other` and `True` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+not v1 != v2 and v1 != v3 and not v4 != v5 and v5 != v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
new file mode 100644
index 00000000000..8dc85c4a70b
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
@@ -0,0 +1,86 @@
+---
+id: 65fd9c6e49d7cd8513ab1005
+title: Step 62
+challengeType: 20
+dashedName: step-62
+---
+
+# --description--
+
+At the end of your code, use the equality operator to compare `v1` and `R2Vector(x=2, y=3)` and print the result.
+
+# --hints--
+
+You should print the result of comparing `v1` and `R2Vector(x=2, y=3)` using the equality operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 == R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) == v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
new file mode 100644
index 00000000000..b488bbcf86f
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9d6203afea85931094c9
+title: Step 63
+challengeType: 20
+dashedName: step-63
+---
+
+# --description--
+
+The comparison returns `True`, since the two vectors have the same components. Now, modify the argument of the `print` call you added in the previous step to use the inequality operator.
+
+# --hints--
+
+You should modify the `print` call you added in the previous step using the inequality operator to compare `v1` and `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) != v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 == R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
new file mode 100644
index 00000000000..fbc628b1a0c
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
@@ -0,0 +1,97 @@
+---
+id: 65fd9e2c56ff19862dfb8cbb
+title: Step 64
+challengeType: 20
+dashedName: step-64
+---
+
+# --description--
+
+The `__lt__` method is called under the hood when the `<` operator is used to compare an object with something else.
+
+Add an empty `__lt__` method and give it two parameters: `self`, `other`.
+
+# --hints--
+
+You should define a `__lt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__lt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
new file mode 100644
index 00000000000..1b50fbea3d0
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
@@ -0,0 +1,100 @@
+---
+id: 65fdc3c8478ee70fc7966151
+title: Step 65
+challengeType: 20
+dashedName: step-65
+---
+
+# --description--
+
+In the same way you did before for the `__eq__` method, create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
new file mode 100644
index 00000000000..cd38c9db1b5
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
@@ -0,0 +1,91 @@
+---
+id: 65fdc496f4440e1055a2ac1b
+title: Step 66
+challengeType: 20
+dashedName: step-66
+---
+
+# --description--
+
+After the `if` statement, return the result of comparing the norm of the current instance with the norm of `other` using the less than operator.
+
+# --hints--
+
+The `__lt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the `<` operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_return("self.norm() < other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
new file mode 100644
index 00000000000..2ce64a91350
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
@@ -0,0 +1,122 @@
+---
+id: 6601918b44a11b4a8c986c6a
+title: Step 67
+challengeType: 20
+dashedName: step-67
+---
+
+# --description--
+
+The `__gt__` method is called under the hood when the `>` operator is used to compare an object with something else.
+
+After the `__lt__` method, in the same way you did for `__lt__`, implement the `__gt__` method. Pay attention to use the appropriate operator.
+
+# --hints--
+
+You should define a `__gt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__gt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_args("self, other")`)) })
+```
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+The `__gt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the greater than operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_return("self.norm() > other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
new file mode 100644
index 00000000000..0e7af024e72
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
@@ -0,0 +1,111 @@
+---
+id: 66019258a7c71d4ae50da42e
+title: Step 68
+challengeType: 20
+dashedName: step-68
+---
+
+# --description--
+
+There are still two possible comparisons to implement. The `__le__` method is called when the `<=` operator is used to compare two objects.
+
+Define a `__le__` method with `self` and `other` as the parameters and make it return the opposite of `self > other`.
+
+# --hints--
+
+You should define a `__le__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__le__")`)) })
+```
+
+Your `__le__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_args("self, other")`)) })
+```
+
+Your `__le__` method return the opposite of `self > other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_return("not self > other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
new file mode 100644
index 00000000000..090a4c25718
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
@@ -0,0 +1,116 @@
+---
+id: 66019319edb1cb4b57d3a793
+title: Step 69
+challengeType: 20
+dashedName: step-69
+---
+
+# --description--
+
+The last method you need is `__ge__`, which is called when the `>=` is used to compare two objects.
+
+Define a `__ge__` method with `self` and `other` as the parameters and make it return the opposite of `self < other`.
+
+# --hints--
+
+You should define a `__ge__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ge__")`)) })
+```
+
+Your `__ge__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_args("self, other")`)) })
+```
+
+Your `__ge__` method should return the opposite of `self < other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_return("not self < other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
new file mode 100644
index 00000000000..feda5e7fb02
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
@@ -0,0 +1,104 @@
+---
+id: 660193a2a71faa4bd8f10970
+title: Step 70
+challengeType: 20
+dashedName: step-70
+---
+
+# --description--
+
+Feel free to play around with the new comparison operations you implemented. Then, remove your last `print` call.
+
+
+# --hints--
+
+You should not have `print(v1 != R2Vector(x=2, y=3))` in your code.
+
+```js
+({test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
new file mode 100644
index 00000000000..6690882d473
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
@@ -0,0 +1,111 @@
+---
+id: 66019977710caa516276c0a8
+title: Step 71
+challengeType: 20
+dashedName: step-71
+---
+
+# --description--
+
+The *cross product*, or *vector product*, is defined between 3-dimensional vectors and results in a third vector perpendicular to both of them.
+
+The `R3Vector` class inherits from `R2Vector`, meaning it has access to all the methods and properties defined in `R2Vector`. A child class can implement additional features. You already saw a way to change the implementation of a method. Now, you are going to give the child class `R3Vector` a new method instead.
+
+Within the `R3Vector` class, define a `cross` method and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `cross` method within the `R3Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").has_function("cross")`)) })
+```
+
+Your `cross` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
new file mode 100644
index 00000000000..f4245103e64
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
@@ -0,0 +1,114 @@
+---
+id: 6601a7eb860fb8546516674d
+title: Step 72
+challengeType: 20
+dashedName: step-72
+---
+
+# --description--
+
+Create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
new file mode 100644
index 00000000000..11c27b74700
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
@@ -0,0 +1,105 @@
+---
+id: 6601a88a6e2ccc550d7d7208
+title: Step 73
+challengeType: 20
+dashedName: step-73
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_variable("kwargs").is_equivalent("kwargs = {}")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
new file mode 100644
index 00000000000..4369122717f
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
@@ -0,0 +1,117 @@
+---
+id: 6601a8fb2e993b55912f9e9f
+title: Step 74
+challengeType: 20
+dashedName: step-74
+---
+
+# --description--
+
+The dot product between two 3D vectors \\( \mathbf{a} \\) and \\( \mathbf{b} \\) can be computed as it follows:
+
+\\[ \mathbf{a} \times \mathbf{b} = \begin{pmatrix} a_yb_z - a_zb_y \\\ a_zb_x - a_xb_z \\\ a_xb_y - a_yb_x \end{pmatrix}
+ \\]
+
+Where the resulting vector is represented as a column vector.
+
+Implement the formula above to compute the dot product between two 3-dimensional vectors and return the resulting vector from the `cross()` method.
+
+# --hints--
+
+The `cross()` method should return a new `R3Vector` instance resulting from the dot product computation.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+v1.cross(v2) == R3Vector(x=4.75, y=-3.5, z=1.0) and v2.cross(v1) == R3Vector(x=-4.75, y=3.5, z=-1.0) and v1.cross(v1) == R3Vector(x=0, y=0, z=0)
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
new file mode 100644
index 00000000000..2093aecdc16
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
@@ -0,0 +1,119 @@
+---
+id: 6601ab2809898f57591f2f7f
+title: Step 75
+challengeType: 20
+dashedName: step-75
+---
+
+# --description--
+
+Now, modify the assignments of `v1` and `v2`. Turn them into `R3Vector` instances and pass `z=1` and `z=2` to `v1` and `v2`, respectively.
+
+# --hints--
+
+You should modify the assignment of `v1` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R3Vector(x=2, y=3, z=1)")`)) })
+```
+
+You should modify the assignment of `v2` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=0.5, y=1.25, z=2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+--fcc-editable-region--
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
new file mode 100644
index 00000000000..c7d46d75ac7
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
@@ -0,0 +1,113 @@
+---
+id: 6601ac48a2ee6b59e6a5060d
+title: Step 76
+challengeType: 20
+dashedName: step-76
+---
+
+# --description--
+
+Call `cross()` on `v1` and pass `v2` as the argument. Assign this call to a new variable `v6`.
+
+# --hints--
+
+You should declare a variable named `v6` and assign it a call to the `cross()` method on `v1` passing it `v2` as the `argument`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v6").is_equivalent("v6 = v1.cross(v2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
new file mode 100644
index 00000000000..48e3a3a353f
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
@@ -0,0 +1,210 @@
+---
+id: 6601ad0fe415985a5c83f3cc
+title: Step 77
+challengeType: 20
+dashedName: step-77
+---
+
+# --description--
+
+As a final step, call the `print` function and pass it the f-string `f'v1 x v2 = {v6}'` to see the output of the dot product.
+
+With that, you have completed the vector space project. Well done!
+
+# --hints--
+
+You should print `f'v1 x v2 = {v6}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 x v2 = {v6}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+print(f'v1 x v2 = {v6}')
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
new file mode 100644
index 00000000000..d25b1a4c723
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
@@ -0,0 +1,53 @@
+---
+id: 6659875502b6d7765498f324
+title: Step 26
+challengeType: 20
+dashedName: step-26
+---
+
+# --description--
+
+Use f-strings to modify your `print` calls so that they result in the output `v1 = (2, 3)` and `v2 = (2, 2, 3)`, respectively.
+
+# --hints--
+
+You should use an f-string to interpolate `v1` and generate the output `v1 = (2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}')")`)) })
+```
+
+You should use an f-string to interpolate `v2` and generate the output `v2 = (2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
new file mode 100644
index 00000000000..ff34ca74d7f
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
@@ -0,0 +1,51 @@
+---
+id: 66680ddfd0f8c76782923cb0
+title: Step 22
+challengeType: 20
+dashedName: step-22
+---
+
+# --description--
+
+The `norm()` method is returning the correct values, but there's still something you can improve: readability.
+
+The `vars()` built-in function takes an object as its argument and returns the `__dict__` attribute of that object.
+
+Instead of directly accessing the `__dict__` attribute of `self`, modify the `norm` method to use the `vars()` function.
+
+# --hints--
+
+You should modify your `norm` method to use `vars(self)` instead of `self.__dict__`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in vars(self).values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
new file mode 100644
index 00000000000..0dc691b65b8
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
@@ -0,0 +1,61 @@
+---
+id: 66682150151af29efec9727d
+title: Step 33
+challengeType: 20
+dashedName: step-33
+---
+
+# --description--
+
+The `__getattribute__` method is called under the hood any time you try to access an instance attribute. If the attribute is not found at the instance level, the method will search for it at the class level, and eventually in parent classes.
+
+Inside your class, define a `__getattribute__` method with two parameters, `self` and `attr`, and make it return the string `'calling __getattribute__'`. You'll override momentarily the default implementation just to see how the attribute access works.
+
+# --hints--
+
+You should define a method named `__getattribute__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_args("self, attr")`)) })
+```
+
+Your `__getattribute__` method should return the string `'calling __getattribute__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_return("'calling __getattribute__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
new file mode 100644
index 00000000000..80410b55106
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
@@ -0,0 +1,61 @@
+---
+id: 666826f258fda1ab3396a509
+title: Step 34
+challengeType: 20
+dashedName: step-34
+---
+
+# --description--
+
+Now, print the result of accessing the `x` attribute of `v1` both with the dot operator and the `getattr()` built-in function.
+
+You will see that `__getattribute__` is called in both cases.
+
+# --hints--
+
+You should print the `x` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.x)") and n.has_call("print(getattr(v1, 'x'))")) or n.has_call("print(v1.x, getattr(v1, 'x'))") or n.has_call("print(getattr(v1, 'x'), v1.x)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
new file mode 100644
index 00000000000..8c3a650010b
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
@@ -0,0 +1,69 @@
+---
+id: 666827a6fd0dbaafe8330ea6
+title: Step 35
+challengeType: 20
+dashedName: step-35
+---
+
+# --description--
+
+`__getattr__` is another special method that plays a role in accessing attributes.
+
+The default implementation of `__getattribute__` is to raise an `AttributeError` when the requested attribute is not an instance attribute or it is not present in the class tree.
+
+In that case, `__getattr__` is called if defined by the class. You can consider it as a sort of fallback when the usual attribute accessing procedure fails.
+
+Turn the `__getattribute__` method into `__getattr__` and modify the string returned by the method into `'calling __getattr__'`.
+
+# --hints--
+
+You should define a method named `__getattr__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_args("self, attr")`)) })
+```
+
+Your `__getattr__` method should return the string `'calling __getattr__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_return("'calling __getattr__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+print(v1.x)
+print(getattr(v1, 'x'))
+
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
new file mode 100644
index 00000000000..598c9822428
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
@@ -0,0 +1,62 @@
+---
+id: 666832e427d70bc5219dc62a
+title: Step 36
+challengeType: 20
+dashedName: step-36
+---
+
+# --description--
+
+As you can see from the output, although you defined `__getattr__` in your class, this method is not called yet. This happens because the default attribute access occurs through `__getattribute__`. Therefore, you can see the attribute value printed on the terminal.
+
+Now modify the last two lines of code to access the `z` attribute of `v1` in both your `print()` calls. This time, you are going to access an attribute that `v1` does not have. As a result, `__getattribute__` will raise an error and `__getattr__` will be called.
+
+# --hints--
+
+You should modify your code to print the `z` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.z)") and n.has_call("print(getattr(v1, 'z'))")) or n.has_call("print(v1.z, getattr(v1, 'z'))") or n.has_call("print(getattr(v1, 'z'), v1.z)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+print(v1.x)
+print(getattr(v1, 'x'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
new file mode 100644
index 00000000000..bb55eb1f3a8
--- /dev/null
+++ b/curriculum/challenges/chinese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
@@ -0,0 +1,75 @@
+---
+id: 6668374ed18b7fce10259cb3
+title: Step 37
+challengeType: 20
+dashedName: step-37
+---
+
+# --description--
+
+Now that you have an idea of how the attribute access work, remove the last two lines of your code together with the `__getattr__` method.
+
+Then, restore the `print()` calls you commented out before and delete the second argument from both of them.
+
+# --hints--
+
+You should not have a `__getattr__` method.
+
+```js
+({ test: () => assert.isFalse(runPython(`_Node(_code).find_class("R2Vector").has_function("__getattr__")`)) })
+```
+
+You should not have `print(v1.z)`and `print(getattr(v1, 'z'))` in your code.
+
+```js
+({ test: () => assert.isFalse(runPython(`
+n = _Node(_code)
+n.has_call("print(v1.z)") or n.has_call("print(getattr(v1, 'z'))")
+`)) })
+```
+
+You should restore the `print()` calls you commented out before and remove the second argument from both of them.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).has_call("print(f'v1 = {v1}')") and _Node(_code).has_call("print(f'v2 = {v2}')")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+print(v1.z)
+print(getattr(v1, 'z'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md b/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
deleted file mode 100644
index 632abe728dd..00000000000
--- a/curriculum/challenges/chinese/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
+++ /dev/null
@@ -1,344 +0,0 @@
----
-id: 62aa1fed3d4e873366ff3131
-title: Step 150
-challengeType: 0
-dashedName: step-150
----
-
-# --description--
-
-In your `attack` function, below the `health` variable, create an `if` statement. Set the condition to call the `isMonsterHit` function.
-
-# --hints--
-
-You should add an `if` statement which calls `isMonsterHit` in the condition.
-
-```js
-assert.match(attack.toString(), /if\s*\(\s*isMonsterHit\s*\(\s*\)/)
-```
-
-# --seed--
-
-## --seed-contents--
-
-```html
-
-
-
-
-
-
+
+Within the `Vector` class, create an `__init__` method and give it three parameters, `self`, `x`, and `y`.
+
+# --hints--
+
+You should define an `__init__` method inside the `Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").has_function("__init__")`)) })
+```
+
+Your `__init__` method should take three parameters: `self`, `x`, and `y`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").find_function("__init__").has_args("self, x, y")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ pass
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
new file mode 100644
index 00000000000..62ab349a8db
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
@@ -0,0 +1,38 @@
+---
+id: 65f055b9190fc41ca35549b8
+title: Step 3
+challengeType: 20
+dashedName: step-3
+---
+
+# --description--
+
+Python offers various methods that include both a leading and trailing double underscore in their names. You may already be familiar with some, such as `__init__` and `__str__`. These methods, which follow the `__
+
+So far, you created a 2-dimensional vector. You want to be able to represent vectors with a different number of dimensions without rewriting the necessary code for each specific case. For that, you will use inheritance.
+
+Start by renaming the `Vector` class into `R2Vector` to specify that this class is going to deal with 2-dimensional vectors. Remember to modify the instantiation of `v1`, too.
+
+# --hints--
+
+You should rename the `Vector` class into `R2Vector`. Remember to modify the instantiation of `v1`, too.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+v1 = Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
new file mode 100644
index 00000000000..e26a20b0730
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
@@ -0,0 +1,70 @@
+---
+id: 65f40051d6b09a139f253e8e
+title: Step 12
+challengeType: 20
+dashedName: step-12
+---
+
+# --description--
+
+Inheritance enables you to define a class from an existing one. The new class, called child, inherits all the methods and properties of the existing class, called parent.
+
+```py
+class Tree:
+ def sprout(self):
+ print('Making new leaves!')
+
+class Oak(Tree):
+ pass
+
+Oak().sprout() # Output: Making new leaves!
+```
+
+In the example above, the child class `Oak` inherits from `Tree` and inherits the `sprout` method from the parent class `Tree`.
+
+Create a new class named `R3Vector` and follow the example above to make it inherit from the `R2Vector` class.
+
+# --hints--
+
+You should define a new class `R3Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R3Vector")
+ `))
+})
+```
+
+Your new class `R3Vector` should inherit from `R2Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").inherits_from("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
new file mode 100644
index 00000000000..c50cbefeb4a
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
@@ -0,0 +1,56 @@
+---
+id: 65f40401e6ef53173c04e27d
+title: Step 13
+challengeType: 20
+dashedName: step-13
+---
+
+# --description--
+
+Within your new class, declare an `__init__` method. Give it `self`, `x`, `y`, and `z` as the parameters.
+
+# --hints--
+
+You should define an `__init__` method inside your `R3Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").has_function("__init__")
+ `))
+})
+```
+
+Your `__init__` method should have four parameters `self`, `x`, `y`, and `z`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, x, y, z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
new file mode 100644
index 00000000000..cb7a33c0eb1
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
@@ -0,0 +1,49 @@
+---
+id: 65f407ea37ad6e181b90462e
+title: Step 14
+challengeType: 20
+dashedName: step-14
+---
+
+# --description--
+
+You could assign each `i` parameter to `self.i` as you did before. Although in this case you have few lines to repeat, one way to avoid this repetition is using the `super()` function. `super()` enables you to refer implicitly to the parent class: `super().__init__(x, y)` calls the `__init__` method of the parent class.
+
+Add a `super().__init__(x, y)` call to your `__init__` method.
+
+# --hints--
+
+You should have a `super().__init__(x, y)` call in your `__init__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_stmt("super().__init__(x, y)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
new file mode 100644
index 00000000000..caf708394fc
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
@@ -0,0 +1,47 @@
+---
+id: 65f40f8af784751c613d638a
+title: Step 15
+challengeType: 20
+dashedName: step-15
+---
+
+# --description--
+
+Now, you need to assign `z` to the `z` attribute of your `R3Vector` object.
+
+# --hints--
+
+You should assign `z` to `self.z` after the `super` call.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").is_ordered("super().__init__(x, y)", "self.z = z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
new file mode 100644
index 00000000000..68340ee6c11
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
@@ -0,0 +1,47 @@
+---
+id: 65f40fdb3579aa1ced28b2eb
+title: Step 16
+challengeType: 20
+dashedName: step-16
+---
+
+# --description--
+
+Create an `R3Vector` instance with `2`, `2`, and `3` as the values of `x`, `y`, and `z`, respectively. Assign the new instance to `v2`.
+
+# --hints--
+
+You should declare a variable `v2` and assign it `R3Vector(2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(2, 2, 3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
new file mode 100644
index 00000000000..06b727e3b29
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
@@ -0,0 +1,72 @@
+---
+id: 65f412c208c3791fee305acf
+title: Step 17
+challengeType: 20
+dashedName: step-17
+---
+
+# --description--
+
+In Python, you can enforce the use of keyword-only arguments by adding a `*` as an additional argument to the function or method signature. Modify both `__init__` methods by adding a `*` as the second parameter (after `self`). Every parameter placed after that will require the use of a keyword argument in the function/method call.
+
+This means that you need to modify the `super().__init__(x, y)` call, too. Do it by giving `x` the value `x`, and `y` the value `y`.
+
+Finally, modify the instantiation of `v1` and `v2` by using keyword arguments.
+
+# --hints--
+
+You should enforce keyword arguments by adding a `*` as the second parameter in both your `__init__` methods.
+
+```js
+({ test: () => {
+ assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__init__").has_args("self, *, x, y")`));
+ assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, *, x, y, z")`));
+} })
+```
+
+You should modify your `super.__init__(x, y)` call to use keyword arguments.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").find_body().is_equivalent("super().__init__(x=x, y=y)\\nself.z = z")`)) })
+```
+
+You should modify the assignment of `v1` to be `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R2Vector(x=2, y=3)")`)) })
+```
+
+You should modify the assignment of `v2` to be `R3Vector(x=2, y=2, z=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=2, y=2, z=3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+v2 = R3Vector(2, 2, 3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
new file mode 100644
index 00000000000..ef31cdd6194
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
@@ -0,0 +1,64 @@
+---
+id: 65f4148dea0f802040225e0c
+title: Step 18
+challengeType: 20
+dashedName: step-18
+---
+
+# --description--
+
+Remove the existing `print` calls. Then, as you did before for `v1`, print `v2` and the value returned by `v2.norm()`.
+
+# --hints--
+
+You should not have `print(v1)` and `print(v1.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1.norm())")`));
+ }
+})
+```
+
+You should print `v2` and `v2.norm()`.
+
+```js
+({
+ test: () => {
+ assert(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+print(v1.norm())
+print(v1)
+
+v2 = R3Vector(x=2, y=2, z=3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
new file mode 100644
index 00000000000..1a83f17e994
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
@@ -0,0 +1,64 @@
+---
+id: 65f4520e363e2642f8112e33
+title: Step 19
+challengeType: 20
+dashedName: step-19
+---
+
+# --description--
+
+As you can see, something is not quite right. The `norm` and `__str__` methods inherited from `R2Vector` cannot adapt to a 3-dimensional vector. Their implementation has to be more flexible.
+
+Every object in Python has a special attribute named `__dict__`, which is a dictionary that stores the object attributes.
+
+Remove the existing `print` calls. Then, print the `__dict__` attribute of your `v1` and `v2` vectors to see what they look like.
+
+# --hints--
+
+You should not have `print(v2)` and `print(v2.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+You should print the `__dict__` attribute of `v1` and `v2`.
+
+```js
+({ test: () => assert(runPython(`
+(_Node(_code).has_call("print(v1.__dict__)") and _Node(_code).has_call("print(v2.__dict__)")) or _Node(_code).has_call("print(v1.__dict__, v2.__dict__)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v2.norm())
+print(v2)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
new file mode 100644
index 00000000000..2a2c8f28376
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
@@ -0,0 +1,49 @@
+---
+id: 65f4535bbdb28d436ff3ddc9
+title: Step 20
+challengeType: 20
+dashedName: step-20
+---
+
+# --description--
+
+As you can see from the output, `__dict__` contains the values of your instance attributes. Instead of explicitly adding the squares of `self.x` and `self.y`, you are going to iterate over the values stored in `__dict__` to calculate the value of the norm.
+
+Within the `norm` method body, replace the content of the parentheses with a generator expression that elevates each value `val` in `self.__dict__.values()` to the power of `2`. Also, pass that generator expression as the argument to the `sum` function, so that all the squares are added together before calculating the square root.
+
+# --hints--
+
+You should return `sum(val**2 for val in self.__dict__.values())**0.5` from `norm()` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in self.__dict__.values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
new file mode 100644
index 00000000000..bbb82436c52
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
@@ -0,0 +1,53 @@
+---
+id: 65f870003444fb1a2ad171f2
+title: Step 21
+challengeType: 20
+dashedName: step-21
+---
+
+# --description--
+
+Modify the two `print` calls to print the norm of your vectors and verify that the `norm()` method works fine.
+
+# --hints--
+
+You should print `v1.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1.norm())")`)) })
+```
+
+You should print `v2.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v2.norm())")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
new file mode 100644
index 00000000000..22e3cab792e
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
@@ -0,0 +1,61 @@
+---
+id: 65f8709620b2ce1a62608f5a
+title: Step 23
+challengeType: 20
+dashedName: step-23
+---
+
+# --description--
+
+When you need to dynamically access some attributes starting from a string input, the built-in `getattr()` function is what you need. It takes an object as its first argument, and a string containing the attribute name as its second attribute.
+
+Start to fix the `__str__` method by replacing the string returned by `__str__()` with a generator expression that iterates through the object attributes and calls `getattr()` for each attribute `i`.
+
+# --hints--
+
+You should return a generator expression that iterates over `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_iters()[0].is_equivalent("vars(self)")`)) })
+```
+
+You should return a generator expression that uses `i` as the iteration variable.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_targets()[0].is_equivalent("i")`)) })
+```
+
+You should return a generator expression that calls `getattr(self, i)` for each item `i` in `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_expr().is_equivalent("getattr(self, i)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
new file mode 100644
index 00000000000..668bd89de56
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
@@ -0,0 +1,47 @@
+---
+id: 65f8720685ec351abef26740
+title: Step 24
+challengeType: 20
+dashedName: step-24
+---
+
+# --description--
+
+To obtain a proper string representation, call the `tuple()` constructor and pass it the generator expression you wrote in the previous step as the argument.
+
+# --hints--
+
+You should pass the expression returned by the `__str__` method to the `tuple()` constructor.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("tuple(getattr(self, i) for i in vars(self))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return (getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
new file mode 100644
index 00000000000..789f37ee6fe
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
@@ -0,0 +1,47 @@
+---
+id: 65f872a0fe6aa21b456ad4fe
+title: Step 25
+challengeType: 20
+dashedName: step-25
+---
+
+# --description--
+
+Finally, pass the `tuple()` call as the argument to the `str()` function.
+
+# --hints--
+
+You should pass the `tuple()` call you are currently returning from the `__str__` method to the `str()` function.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("str(tuple(getattr(self, i) for i in vars(self)))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return tuple(getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
new file mode 100644
index 00000000000..6a2c44baef5
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
@@ -0,0 +1,56 @@
+---
+id: 65f8749b13774b1d2e4a7fba
+title: Step 27
+challengeType: 20
+dashedName: step-27
+---
+
+# --description--
+
+While the `__str__` method returns a human-readable string representation of an object, the `__repr__` method is supposed to return the string needed to instantiate the object.
+
+Add a `__repr__` method with a `self` parameter within the `R2Vector` class.
+
+# --hints--
+
+Your `R2Vector` class should have a `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__repr__")`)) })
+```
+
+Your `__repr__` method should have a `self` parameter.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_args("self")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
new file mode 100644
index 00000000000..7f5a3e0f9c9
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
@@ -0,0 +1,74 @@
+---
+id: 65f876d17832001e8e1abb05
+title: Step 28
+challengeType: 20
+dashedName: step-28
+---
+
+# --description--
+
+Declare a variable `arg_list`. Give it the value of a list comprehension that iterates over `key` and `val` for each key-value pair in `vars(self).items()` and computes the f-string `f'{key}={val}'` at each iteration.
+
+# --hints--
+
+You should declare a variable `arg_list`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_variable("arg_list")`)) })
+```
+
+You should assign a list comprehension that iterates over `vars(self).items()` to `arg_list`.
+
+```js
+({ test: () => runPython(`
+import ast
+var = _Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list")
+assert isinstance(var.tree.value, ast.ListComp), "Expected arg_list to be a list comprehension"
+assert (actual := var.find_comp_iters()[0].is_equivalent("vars(self).items()")), f"Expected vars(self).items(), got {actual}"
+`) })
+```
+
+The list comprehension assigned to `arg_list` should use `key` and `val` to iterate over `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_targets()[0].is_equivalent("key, val")
+`)) })
+```
+
+The list comprehension assigned to `arg_list` should compute the string `f'{key}={val}'` for each key-value pair in `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_expr().is_equivalent("f'{key}={val}'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
new file mode 100644
index 00000000000..0c56316394e
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
@@ -0,0 +1,50 @@
+---
+id: 65f93acbb514857003510e79
+title: Step 29
+challengeType: 20
+dashedName: step-29
+---
+
+# --description--
+
+Declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+# --hints--
+
+You should declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("args").is_equivalent("args = ', '.join(arg_list)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
new file mode 100644
index 00000000000..e826611fa57
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
@@ -0,0 +1,52 @@
+---
+id: 65f93b67169a9c703264458a
+title: Step 30
+challengeType: 20
+dashedName: step-30
+---
+
+# --description--
+
+Since the method should return the string to instantiate the object for `R2Vector` as well as `R3Vector` when inherited, you cannot build the string specifying the class name.
+
+You can access the name of a class with `__class__.__name__`. Add a `return` statement to the `__repr__` method and return the string necessary to instantiate the object.
+
+# --hints--
+
+You should use `__class__.__name__` to build the f-string needed to instantiate a vector object and return it from the `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_return("f'{self.__class__.__name__}({args})'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
new file mode 100644
index 00000000000..13682539c2c
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
@@ -0,0 +1,57 @@
+---
+id: 65f93d4647ce2670dc6f095c
+title: Step 31
+challengeType: 20
+dashedName: step-31
+---
+
+# --description--
+
+The `__repr__` method is called under the hood by the `repr` function. Verify that `__repr__` works properly by adding `f'\nrepr = {repr(v1)}'` and `f'\nrepr = {repr(v2)}'` as the second argument to your first and second `print` calls, respectively.
+
+# --hints--
+
+You should add `f'\nrepr = {repr(v1)}'` as the second argument to your `print(f'v1 = {v1}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}', f'\\\\nrepr = {repr(v1)}')")`)) })
+```
+
+You should add `f'\nrepr = {repr(v2)}'` as the second argument to your `print(f'v2 = {v2}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}', f'\\\\nrepr = {repr(v2)}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
new file mode 100644
index 00000000000..a25da243ba9
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
@@ -0,0 +1,56 @@
+---
+id: 65f93e54a9121571dcdd3e79
+title: Step 32
+challengeType: 20
+dashedName: step-32
+---
+
+# --description--
+
+The output is correct, `repr` is giving you the string required to instantiate the objects.
+
+Now comment out both your `print` calls.
+
+# --hints--
+
+You should comment out both your `print()` calls.
+
+```js
+({ test: () => {
+ assert.match(code, /#\s*print\s*\(\s*f('|")v1 = \{\s*v1\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v1\s*\)\s*\}\2\s*\)/);
+ assert.match(code, /#\s*print\s*\(\s*f('|")v2 = \{\s*v2\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v2\s*\)\s*\}\2\s*\)/);
+} })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
new file mode 100644
index 00000000000..127f701ba31
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
@@ -0,0 +1,62 @@
+---
+id: 65f9b17a638f0d0dcce8c354
+title: Step 38
+challengeType: 20
+dashedName: step-38
+---
+
+# --description--
+
+To create a vector space, you need to define how vectors should behave in several cases. Vectors can be added, forming a new vector.
+
+The special method `__add__` can be implemented to override what happens by default when two objects are added together using the `+` operator.
+
+Right now, trying to add two instances of `R2Vector` or `R3Vector` would raise an exception. Create an empty `__add__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define an `__add__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__add__")`)) })
+```
+
+Your `__add__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
new file mode 100644
index 00000000000..f90c14fe57b
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b486989cb90ff3e77ac8
+title: Step 39
+challengeType: 20
+dashedName: step-39
+---
+
+# --description--
+
+The `other` parameter of your `__add__` method represents the operand placed at the right side of the `+` operator in an addition operation.
+
+You want to verify that the right-hand operand is not an object of the same class as the left-hand operand (i.e. `self`). Create an `if` statement that verifies that by checking the type of the operands.
+
+# --hints--
+
+You should create an `if` statement that checks if `type(self)` and `type(other)` are different.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
new file mode 100644
index 00000000000..1fa83e0f9aa
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b9710cca621244d3bde1
+title: Step 40
+challengeType: 20
+dashedName: step-40
+---
+
+# --description--
+
+In Python, `NotImplemented` is a special value used to indicate that an operation is not implemented for a specific case.
+
+`NotImplemented` does not raise an exception immediately. Instead, it signals to ask to the other operand how to perform the operation. If the request cannot be satisfied, a `TypeError` is returned by default.
+
+Because you want to be able to sum two vectors only if they belong to the same class, return `NotImplemented` from the `if` statement you created in the previous step.
+
+# --hints--
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
new file mode 100644
index 00000000000..9df77e46895
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
@@ -0,0 +1,58 @@
+---
+id: 65f9bb7c0d524612b2a88a4b
+title: Step 41
+challengeType: 20
+dashedName: step-41
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_stmt("kwargs = {}")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
new file mode 100644
index 00000000000..f5d28e43bd6
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
@@ -0,0 +1,92 @@
+---
+id: 65f9bc10a9fb1612e066e9e8
+title: Step 42
+challengeType: 20
+dashedName: step-42
+---
+
+# --description--
+
+When adding two vectors, each component of one vector is added to the same component of the other vector. For example, adding `(1, 2)` and `(2, 4)` generates a third vector `(3, 6)`, where `3` is the sum of `1` and `2` and `6` is the sum of `2` and `4`.
+
+The `kwargs` dictionary will contain the key-value pairs needed to instantiate a new vector of the same class of the two vectors added together.
+
+Turn the empty dictionary into a dictionary comprehension that iterates through `vars(self)` and for each key (`i`) creates a key-value pair, where the key is the same key of the current iteration and its value is the sum of the values of the `i` attributes of the two operands.
+
+# --hints--
+
+You should turn the empty dictionary assigned to `kwargs` into a dictionary comprehension that iterates over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_iters()[0].is_equivalent("vars(self)")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_key().is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the sum of the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i` in `vars(self)`. Use the `getattr()` function for that.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) + getattr(other, i)") or node.is_equivalent("getattr(other, i) + getattr(self, i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
new file mode 100644
index 00000000000..d1cd1755778
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
@@ -0,0 +1,70 @@
+---
+id: 65f9c2c2006feb1428ad2d4c
+title: Step 43
+challengeType: 20
+dashedName: step-43
+---
+
+# --description--
+
+You can unpack a dictionary into keyword arguments by using the `**` operator:
+
+```py
+def spam(a, b):
+ return a + b
+
+my_dict = {a: 11, b: 4}
+
+spam(**my_dict) # 15
+```
+
+Return an instance of the current class by using `__class__` and passing `**kwargs` as the argument.
+
+# --hints--
+
+You should return `self.__class__(**kwargs)` from the `__add__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
new file mode 100644
index 00000000000..689ab778fe5
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
@@ -0,0 +1,90 @@
+---
+id: 65f9cb678070ca1668898c70
+title: Step 44
+challengeType: 20
+dashedName: step-44
+---
+
+# --description--
+
+In the same way `__add__` is called under the hood when two objects are added together, the `__sub__` method is called implicitly in case of subtraction.
+
+Now, define an empty `__sub__` method and give two parameters: `self`, and `other`. Inside your new method, create an if statement to check if `self` and `other` do not belong to the same class and return `NotImplemented`, as you did previously.
+
+# --hints--
+
+You should define a `__sub__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__sub__")
+ `))
+})
+```
+
+Your `__sub__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_args("self, other")
+ `))
+})
+```
+
+You should create an `if` statement that checks if `self` and `other` does not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+ `))
+})
+```
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
new file mode 100644
index 00000000000..2d452d2413e
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
@@ -0,0 +1,89 @@
+---
+id: 65f9dd6e5a08af19c196c2df
+title: Step 45
+challengeType: 20
+dashedName: step-45
+---
+
+# --description--
+
+The vector resulting from the subtraction of one vector from another is obtained by calculating the difference of each of their components. For example, subtracting `(2, 4)` from `(7, 3)` generates a third vector `(5, -1)`, where `5` is the difference between `7` and `2` and `-1` is the difference between `3` and `4`.
+
+As you did before inside the `__add__` method, declare a `kwargs` variable after the `if` statement. Assign it a dictionary comprehension that iterates through the object attributes and creates a key-value pair for each key `i`, where the key is the same key as the current iteration and its value is the difference between the values of the `i` attributes of two operands.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it a dictionary comprehension that iterates over the object attributes.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_iters()[0]
+node.is_equivalent("vars(self)") or node.is_equivalent("self.__dict__")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over the object attributes.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_key().is_equivalent("i")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the difference between the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i`.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) - getattr(other, i)") or node.is_equivalent("self.__getattribute__(i) - other.__getattribute__(i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
new file mode 100644
index 00000000000..095bce27c7c
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
@@ -0,0 +1,65 @@
+---
+id: 65f9dfd2e75e291a38695f13
+title: Step 46
+challengeType: 20
+dashedName: step-46
+---
+
+# --description--
+
+Finally, return a new vector object. Use `__class__` and unpack `kwargs` to instantiate the new vector.
+
+# --hints--
+
+You should return a new vector using `__class__` and unpacking `kwargs` from the `__sub__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
new file mode 100644
index 00000000000..c5cb7742541
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
@@ -0,0 +1,67 @@
+---
+id: 65f9e0a578b22c1a736f3d82
+title: Step 47
+challengeType: 20
+dashedName: step-47
+---
+
+# --description--
+
+Modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+# --hints--
+
+You should modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v2 = R2Vector(x=0.5, y=1.25)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
new file mode 100644
index 00000000000..1d277671da4
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
@@ -0,0 +1,67 @@
+---
+id: 65fa8d5cf0ef3b141010f5d8
+title: Step 48
+challengeType: 20
+dashedName: step-48
+---
+
+# --description--
+
+It's time to verify that the addition and subtraction operations work as expected. Declare another variable `v3` and assign it the sum of `v1` plus `v2`.
+
+# --hints--
+
+You should declare a variable `v3` and assign it the sum of `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v3 = v1 + v2") or _Node(_code).has_stmt("v3 = v2 + v1")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
new file mode 100644
index 00000000000..87ddac5ea5f
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
@@ -0,0 +1,64 @@
+---
+id: 65fa8df56a0e2c149b4d24fe
+title: Step 49
+challengeType: 20
+dashedName: step-49
+---
+
+# --description--
+
+Next, check the new vector by printing the following f-string `f'v1 + v2 = {v3}'`.
+
+# --hints--
+
+You should print `f'v1 + v2 = {v3}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 + v2 = {v3}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
new file mode 100644
index 00000000000..e526a9cd4cc
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
@@ -0,0 +1,77 @@
+---
+id: 65fa9402d1fb5516aa42159d
+title: Step 50
+challengeType: 20
+dashedName: step-50
+---
+
+# --description--
+
+Feel free to modify `v3` so that it sums an `R2Vector` instance with an object of a different type, such as an integer or a string. You will be able to see a `TypeError` message printed on the console.
+
+Then, restore the original line and create a new variable `v4`. Assign the difference between `v1` and `v2` to your new variable and print the result following the same structure as the previous f-string.
+
+# --hints--
+
+You should declare a variable `v4` and assign it the difference between `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v4 = v1 - v2")
+ `))
+})
+```
+
+You should print `f'v1 - v2 = {v4}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 - v2 = {v4}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
new file mode 100644
index 00000000000..d2df1c3038d
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
@@ -0,0 +1,85 @@
+---
+id: 65fa9e1b6c6db919385359ec
+title: Step 51
+challengeType: 20
+dashedName: step-51
+---
+
+# --description--
+
+The special method `__mul__` can be implemented to specify what should happen when the current instance is multiplied by another object.
+
+Create an empty `__mul__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `__mul__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__mul__")
+ `))
+})
+```
+
+Your `__mul__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__mul__").has_args("self, other")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
new file mode 100644
index 00000000000..0a18b8b69d1
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
@@ -0,0 +1,94 @@
+---
+id: 65faaed8f7a9772f023ea816
+title: Step 52
+challengeType: 20
+dashedName: step-52
+---
+
+# --description--
+
+Vectors can be multiplied by a *scalar*, i.e. a number that multiplies each single component. The result of scalar multiplication is a vector with the same orientation as the original vector but a different magnitude.
+
+Implement the scalar multiplication by checking if `other` is either an `int` or a `float`. If it is, return a new instance of the current class that has each component of the starting vector multiplied by `other`. This will be the vector resulting from the scalar multiplication.
+
+Make sure the methods can be applied to compute the scalar multiplication of vectors with any number of dimensions.
+
+# --hints--
+
+Your method should return a new instance of the current class only when the type of `other` is either `int` or `float`.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=0, y=0)
+v2 = R3Vector(x=0, y=0, z=0)
+types = ["", True, [], {}]
+assert all((v1 * i) is None for i in types)
+types = [1, 1.0]
+assert all(type(v1 * i) is type(v1) for i in types)
+assert all(type(v2 * i) is type(v2) for i in types)
+`) })
+```
+
+The vector resulting from the scalar multiplication should have each component of the starting vector multiplied by the scalar.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=1, y=1.5)
+v2 = R3Vector(x=2.2, y=3, z=-1)
+assert vars(v1 * 3) == vars(R2Vector(x=3, y=4.5))
+assert vars(v2 * (-2.0)) == vars(R3Vector(x=-4.4, y=-6.0, z=2.0))
+`) })
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
new file mode 100644
index 00000000000..bcf1d3d0b55
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
@@ -0,0 +1,79 @@
+---
+id: 65fc87e19930a503e5f05500
+title: Step 53
+challengeType: 20
+dashedName: step-53
+---
+
+# --description--
+
+A vector can be multiplied by another vector, too. This operation is called *dot product*, or *scalar product*.
+
+Create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+You are going to implement the dot product inside this block during the next step.
+
+# --hints--
+
+You should create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__mul__").find_ifs()[0].find_conditions()[1]
+node.is_equivalent("type(self) == type(other)") or node.is_equivalent("type(other) == type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
new file mode 100644
index 00000000000..c5edc6d9b45
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
@@ -0,0 +1,87 @@
+---
+id: 65fc899d77495504d6deeccc
+title: Step 54
+challengeType: 20
+dashedName: step-54
+---
+
+# --description--
+
+The scalar product between two vectors $\mathbf{a}$ and $\mathbf{b}$ is indicated as:
+
+\\( \mathbf{a} \cdot \mathbf{b} = a_1 \cdot b_1 + a_2 \cdot b_2 + \ldots + a_n \cdot b_n = \sum_{i=1}^{n} a_i \cdot b_i \\)
+
+Where each component of $\mathbf{a}$ is multiplied by the correspondent component of $\mathbf{b}$, and all the products are summed together, resulting in a number.
+
+Within the `elif` clause, implement the above formula to compute the result of a scalar product and return the result. Remember that your implementation must be valid for any vector, independently from the number of components, when the method is inherited.
+
+# --hints--
+
+You should implement the scalar product calculation and return the result inside the `elif` body of your `__mul__` method.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+v3 = R3Vector(x=2, y=3, z=1.5)
+v4 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1*v2 == 4.75 and v3*v4 == 7.0
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
new file mode 100644
index 00000000000..36b78391926
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
@@ -0,0 +1,78 @@
+---
+id: 65fc8e7c766ab1070213aadb
+title: Step 55
+challengeType: 20
+dashedName: step-55
+---
+
+# --description--
+
+In case `other` is not an integer, a floating point number, or another instance of the current class, no product can be computed.
+
+After the `elif` clause, return `NotImplemented`.
+
+# --hints--
+
+You should return `NotImplemented` after the `elif` clause.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__mul__").has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
new file mode 100644
index 00000000000..bf365bd4903
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
@@ -0,0 +1,82 @@
+---
+id: 65fc8fa7e7860407ab479bf0
+title: Step 56
+challengeType: 20
+dashedName: step-56
+---
+
+# --description--
+
+It's time to test the multiplication. Declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`. Then, call the `print` function and pass it the following f-string: `f'v1 * 3 = {v5}'`.
+
+# --hints--
+
+You should declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * 3")`)) })
+```
+
+You should print the f-string `f'v1 * 3 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * 3 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
new file mode 100644
index 00000000000..034109b8c53
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
@@ -0,0 +1,87 @@
+---
+id: 65fd681b20b7e45f55def415
+title: Step 57
+challengeType: 20
+dashedName: step-57
+---
+
+# --description--
+
+The scalar multiplication works fine. Now, modify the assignment of `v5` to be the dot product `v1 * v2`. Also, update the `print` call.
+
+Before doing that, feel free to experiment and multiply `v1` by an object of invalid type to see the error message printed on the console.
+
+
+# --hints--
+
+You should update the assignment of `v5` assigning it the scalar product `v1 * v2`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * v2")`)) })
+```
+
+You should update your `print` call to print the f-string `f'v1 * v2 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * v2 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * 3
+print(f'v1 * 3 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
new file mode 100644
index 00000000000..f6184775ca4
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9250db0d6b8198cf29ef
+title: Step 58
+challengeType: 20
+dashedName: step-58
+---
+
+# --description--
+
+The `__eq__` method can be implemented to specify what should happen in case the comparison operator (`==`) is used to compare an object with something else.
+
+Within the `R2Vector` class, create an `__eq__` method and give it two parameters: `self` and `other`.
+
+# --hints--
+
+You should define a `__eq__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__eq__")`)) })
+```
+
+Your `__eq__` method should take two parameters: `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
new file mode 100644
index 00000000000..5d2d8cfc678
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
@@ -0,0 +1,88 @@
+---
+id: 65fd95c23beef982af29004c
+title: Step 59
+challengeType: 20
+dashedName: step-59
+---
+
+# --description--
+
+You want to compare two vectors, only when they belong to the same class. For that create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented` in that case.
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
new file mode 100644
index 00000000000..c3bea995dc8
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
@@ -0,0 +1,91 @@
+---
+id: 65fd97f3c1b4c4839bdeb8d2
+title: Step 60
+challengeType: 20
+dashedName: step-60
+---
+
+# --description--
+
+To compare two vectors, you are going to check that each component of the first vector is equal to the same component of the second vector.
+
+After the `if` statement you created in the previous step, return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+# --hints--
+
+The `__eq__` method should return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1 == v2 and not v1 == v3 and v4 == v5 and not v5 == v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
new file mode 100644
index 00000000000..a7f5d701215
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
@@ -0,0 +1,102 @@
+---
+id: 65fd9aa649f6cc84631882a9
+title: Step 61
+challengeType: 20
+dashedName: step-61
+---
+
+# --description--
+
+The `__ne__` method is called under the hood when the `!=` operator is used. Define a `__ne__` method with two parameters `self` and `other`. From your new method, return the opposite of `self == other`.
+
+# --hints--
+
+You should define a `__ne__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ne__")`)) })
+```
+
+Your `__ne__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ne__").has_args("self, other")`)) })
+```
+
+The `__ne__` method should return `False` if each attribute of the current instance is equal to the same attribute of `other` and `True` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+not v1 != v2 and v1 != v3 and not v4 != v5 and v5 != v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
new file mode 100644
index 00000000000..c151f678d86
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
@@ -0,0 +1,86 @@
+---
+id: 65fd9c6e49d7cd8513ab1005
+title: Step 62
+challengeType: 20
+dashedName: step-62
+---
+
+# --description--
+
+At the end of your code, use the equality operator to compare `v1` and `R2Vector(x=2, y=3)` and print the result.
+
+# --hints--
+
+You should print the result of comparing `v1` and `R2Vector(x=2, y=3)` using the equality operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 == R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) == v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
new file mode 100644
index 00000000000..804d4947304
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9d6203afea85931094c9
+title: Step 63
+challengeType: 20
+dashedName: step-63
+---
+
+# --description--
+
+The comparison returns `True`, since the two vectors have the same components. Now, modify the argument of the `print` call you added in the previous step to use the inequality operator.
+
+# --hints--
+
+You should modify the `print` call you added in the previous step using the inequality operator to compare `v1` and `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) != v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 == R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
new file mode 100644
index 00000000000..9255b41f2c6
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
@@ -0,0 +1,97 @@
+---
+id: 65fd9e2c56ff19862dfb8cbb
+title: Step 64
+challengeType: 20
+dashedName: step-64
+---
+
+# --description--
+
+The `__lt__` method is called under the hood when the `<` operator is used to compare an object with something else.
+
+Add an empty `__lt__` method and give it two parameters: `self`, `other`.
+
+# --hints--
+
+You should define a `__lt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__lt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
new file mode 100644
index 00000000000..ee258ff8a2a
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
@@ -0,0 +1,100 @@
+---
+id: 65fdc3c8478ee70fc7966151
+title: Step 65
+challengeType: 20
+dashedName: step-65
+---
+
+# --description--
+
+In the same way you did before for the `__eq__` method, create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
new file mode 100644
index 00000000000..390babbb01f
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
@@ -0,0 +1,91 @@
+---
+id: 65fdc496f4440e1055a2ac1b
+title: Step 66
+challengeType: 20
+dashedName: step-66
+---
+
+# --description--
+
+After the `if` statement, return the result of comparing the norm of the current instance with the norm of `other` using the less than operator.
+
+# --hints--
+
+The `__lt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the `<` operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_return("self.norm() < other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
new file mode 100644
index 00000000000..7193db8cba2
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
@@ -0,0 +1,122 @@
+---
+id: 6601918b44a11b4a8c986c6a
+title: Step 67
+challengeType: 20
+dashedName: step-67
+---
+
+# --description--
+
+The `__gt__` method is called under the hood when the `>` operator is used to compare an object with something else.
+
+After the `__lt__` method, in the same way you did for `__lt__`, implement the `__gt__` method. Pay attention to use the appropriate operator.
+
+# --hints--
+
+You should define a `__gt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__gt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_args("self, other")`)) })
+```
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+The `__gt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the greater than operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_return("self.norm() > other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
new file mode 100644
index 00000000000..fd051c7fca6
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
@@ -0,0 +1,111 @@
+---
+id: 66019258a7c71d4ae50da42e
+title: Step 68
+challengeType: 20
+dashedName: step-68
+---
+
+# --description--
+
+There are still two possible comparisons to implement. The `__le__` method is called when the `<=` operator is used to compare two objects.
+
+Define a `__le__` method with `self` and `other` as the parameters and make it return the opposite of `self > other`.
+
+# --hints--
+
+You should define a `__le__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__le__")`)) })
+```
+
+Your `__le__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_args("self, other")`)) })
+```
+
+Your `__le__` method return the opposite of `self > other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_return("not self > other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
new file mode 100644
index 00000000000..542035862a5
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
@@ -0,0 +1,116 @@
+---
+id: 66019319edb1cb4b57d3a793
+title: Step 69
+challengeType: 20
+dashedName: step-69
+---
+
+# --description--
+
+The last method you need is `__ge__`, which is called when the `>=` is used to compare two objects.
+
+Define a `__ge__` method with `self` and `other` as the parameters and make it return the opposite of `self < other`.
+
+# --hints--
+
+You should define a `__ge__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ge__")`)) })
+```
+
+Your `__ge__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_args("self, other")`)) })
+```
+
+Your `__ge__` method should return the opposite of `self < other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_return("not self < other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
new file mode 100644
index 00000000000..fe9c0cfa362
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
@@ -0,0 +1,104 @@
+---
+id: 660193a2a71faa4bd8f10970
+title: Step 70
+challengeType: 20
+dashedName: step-70
+---
+
+# --description--
+
+Feel free to play around with the new comparison operations you implemented. Then, remove your last `print` call.
+
+
+# --hints--
+
+You should not have `print(v1 != R2Vector(x=2, y=3))` in your code.
+
+```js
+({test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
new file mode 100644
index 00000000000..2157c6b8a3b
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
@@ -0,0 +1,111 @@
+---
+id: 66019977710caa516276c0a8
+title: Step 71
+challengeType: 20
+dashedName: step-71
+---
+
+# --description--
+
+The *cross product*, or *vector product*, is defined between 3-dimensional vectors and results in a third vector perpendicular to both of them.
+
+The `R3Vector` class inherits from `R2Vector`, meaning it has access to all the methods and properties defined in `R2Vector`. A child class can implement additional features. You already saw a way to change the implementation of a method. Now, you are going to give the child class `R3Vector` a new method instead.
+
+Within the `R3Vector` class, define a `cross` method and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `cross` method within the `R3Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").has_function("cross")`)) })
+```
+
+Your `cross` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
new file mode 100644
index 00000000000..b7948eb83c6
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
@@ -0,0 +1,114 @@
+---
+id: 6601a7eb860fb8546516674d
+title: Step 72
+challengeType: 20
+dashedName: step-72
+---
+
+# --description--
+
+Create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
new file mode 100644
index 00000000000..7a7cb7ef03c
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
@@ -0,0 +1,105 @@
+---
+id: 6601a88a6e2ccc550d7d7208
+title: Step 73
+challengeType: 20
+dashedName: step-73
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_variable("kwargs").is_equivalent("kwargs = {}")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
new file mode 100644
index 00000000000..c9e2224dad3
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
@@ -0,0 +1,116 @@
+---
+id: 6601a8fb2e993b55912f9e9f
+title: Step 74
+challengeType: 20
+dashedName: step-74
+---
+
+# --description--
+
+The dot product between two 3D vectors \\( \mathbf{a} \\) and \\( \mathbf{b} \\) can be computed as it follows:
+
+\\[ \mathbf{a} \times \mathbf{b} = \begin{pmatrix} a_yb_z - a_zb_y \\\ a_zb_x - a_xb_z \\\ a_xb_y - a_yb_x \end{pmatrix} \\]
+
+Where the resulting vector is represented as a column vector.
+
+Implement the formula above to compute the dot product between two 3-dimensional vectors and return the resulting vector from the `cross()` method.
+
+# --hints--
+
+The `cross()` method should return a new `R3Vector` instance resulting from the dot product computation.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+v1.cross(v2) == R3Vector(x=4.75, y=-3.5, z=1.0) and v2.cross(v1) == R3Vector(x=-4.75, y=3.5, z=-1.0) and v1.cross(v1) == R3Vector(x=0, y=0, z=0)
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
new file mode 100644
index 00000000000..c1435330d56
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
@@ -0,0 +1,119 @@
+---
+id: 6601ab2809898f57591f2f7f
+title: Step 75
+challengeType: 20
+dashedName: step-75
+---
+
+# --description--
+
+Now, modify the assignments of `v1` and `v2`. Turn them into `R3Vector` instances and pass `z=1` and `z=2` to `v1` and `v2`, respectively.
+
+# --hints--
+
+You should modify the assignment of `v1` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R3Vector(x=2, y=3, z=1)")`)) })
+```
+
+You should modify the assignment of `v2` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=0.5, y=1.25, z=2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+--fcc-editable-region--
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
new file mode 100644
index 00000000000..6904f99b5e1
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
@@ -0,0 +1,113 @@
+---
+id: 6601ac48a2ee6b59e6a5060d
+title: Step 76
+challengeType: 20
+dashedName: step-76
+---
+
+# --description--
+
+Call `cross()` on `v1` and pass `v2` as the argument. Assign this call to a new variable `v6`.
+
+# --hints--
+
+You should declare a variable named `v6` and assign it a call to the `cross()` method on `v1` passing it `v2` as the `argument`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v6").is_equivalent("v6 = v1.cross(v2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
new file mode 100644
index 00000000000..47d13a7bd4d
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
@@ -0,0 +1,210 @@
+---
+id: 6601ad0fe415985a5c83f3cc
+title: Step 77
+challengeType: 20
+dashedName: step-77
+---
+
+# --description--
+
+As a final step, call the `print` function and pass it the f-string `f'v1 x v2 = {v6}'` to see the output of the dot product.
+
+With that, you have completed the vector space project. Well done!
+
+# --hints--
+
+You should print `f'v1 x v2 = {v6}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 x v2 = {v6}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+print(f'v1 x v2 = {v6}')
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
new file mode 100644
index 00000000000..d25b1a4c723
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
@@ -0,0 +1,53 @@
+---
+id: 6659875502b6d7765498f324
+title: Step 26
+challengeType: 20
+dashedName: step-26
+---
+
+# --description--
+
+Use f-strings to modify your `print` calls so that they result in the output `v1 = (2, 3)` and `v2 = (2, 2, 3)`, respectively.
+
+# --hints--
+
+You should use an f-string to interpolate `v1` and generate the output `v1 = (2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}')")`)) })
+```
+
+You should use an f-string to interpolate `v2` and generate the output `v2 = (2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
new file mode 100644
index 00000000000..bc5ffa5f75d
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
@@ -0,0 +1,51 @@
+---
+id: 66680ddfd0f8c76782923cb0
+title: Step 22
+challengeType: 20
+dashedName: step-22
+---
+
+# --description--
+
+The `norm()` method is returning the correct values, but there's still something you can improve: readability.
+
+The `vars()` built-in function takes an object as its argument and returns the `__dict__` attribute of that object.
+
+Instead of directly accessing the `__dict__` attribute of `self`, modify the `norm` method to use the `vars()` function.
+
+# --hints--
+
+You should modify your `norm` method to use `vars(self)` instead of `self.__dict__`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in vars(self).values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
new file mode 100644
index 00000000000..e0f1c196265
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
@@ -0,0 +1,61 @@
+---
+id: 66682150151af29efec9727d
+title: Step 33
+challengeType: 20
+dashedName: step-33
+---
+
+# --description--
+
+The `__getattribute__` method is called under the hood any time you try to access an instance attribute. If the attribute is not found at the instance level, the method will search for it at the class level, and eventually in parent classes.
+
+Inside your class, define a `__getattribute__` method with two parameters, `self` and `attr`, and make it return the string `'calling __getattribute__'`. You'll override momentarily the default implementation just to see how the attribute access works.
+
+# --hints--
+
+You should define a method named `__getattribute__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_args("self, attr")`)) })
+```
+
+Your `__getattribute__` method should return the string `'calling __getattribute__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_return("'calling __getattribute__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
new file mode 100644
index 00000000000..948a541cb76
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
@@ -0,0 +1,61 @@
+---
+id: 666826f258fda1ab3396a509
+title: Step 34
+challengeType: 20
+dashedName: step-34
+---
+
+# --description--
+
+Now, print the result of accessing the `x` attribute of `v1` both with the dot operator and the `getattr()` built-in function.
+
+You will see that `__getattribute__` is called in both cases.
+
+# --hints--
+
+You should print the `x` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.x)") and n.has_call("print(getattr(v1, 'x'))")) or n.has_call("print(v1.x, getattr(v1, 'x'))") or n.has_call("print(getattr(v1, 'x'), v1.x)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
new file mode 100644
index 00000000000..8c3a650010b
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
@@ -0,0 +1,69 @@
+---
+id: 666827a6fd0dbaafe8330ea6
+title: Step 35
+challengeType: 20
+dashedName: step-35
+---
+
+# --description--
+
+`__getattr__` is another special method that plays a role in accessing attributes.
+
+The default implementation of `__getattribute__` is to raise an `AttributeError` when the requested attribute is not an instance attribute or it is not present in the class tree.
+
+In that case, `__getattr__` is called if defined by the class. You can consider it as a sort of fallback when the usual attribute accessing procedure fails.
+
+Turn the `__getattribute__` method into `__getattr__` and modify the string returned by the method into `'calling __getattr__'`.
+
+# --hints--
+
+You should define a method named `__getattr__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_args("self, attr")`)) })
+```
+
+Your `__getattr__` method should return the string `'calling __getattr__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_return("'calling __getattr__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+print(v1.x)
+print(getattr(v1, 'x'))
+
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
new file mode 100644
index 00000000000..598c9822428
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
@@ -0,0 +1,62 @@
+---
+id: 666832e427d70bc5219dc62a
+title: Step 36
+challengeType: 20
+dashedName: step-36
+---
+
+# --description--
+
+As you can see from the output, although you defined `__getattr__` in your class, this method is not called yet. This happens because the default attribute access occurs through `__getattribute__`. Therefore, you can see the attribute value printed on the terminal.
+
+Now modify the last two lines of code to access the `z` attribute of `v1` in both your `print()` calls. This time, you are going to access an attribute that `v1` does not have. As a result, `__getattribute__` will raise an error and `__getattr__` will be called.
+
+# --hints--
+
+You should modify your code to print the `z` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.z)") and n.has_call("print(getattr(v1, 'z'))")) or n.has_call("print(v1.z, getattr(v1, 'z'))") or n.has_call("print(getattr(v1, 'z'), v1.z)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+print(v1.x)
+print(getattr(v1, 'x'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
new file mode 100644
index 00000000000..3f18e7c657c
--- /dev/null
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
@@ -0,0 +1,75 @@
+---
+id: 6668374ed18b7fce10259cb3
+title: Step 37
+challengeType: 20
+dashedName: step-37
+---
+
+# --description--
+
+Now that you have an idea of how the attribute access work, remove the last two lines of your code together with the `__getattr__` method.
+
+Then, restore the `print()` calls you commented out before and delete the second argument from both of them.
+
+# --hints--
+
+You should not have a `__getattr__` method.
+
+```js
+({ test: () => assert.isFalse(runPython(`_Node(_code).find_class("R2Vector").has_function("__getattr__")`)) })
+```
+
+You should not have `print(v1.z)`and `print(getattr(v1, 'z'))` in your code.
+
+```js
+({ test: () => assert.isFalse(runPython(`
+n = _Node(_code)
+n.has_call("print(v1.z)") or n.has_call("print(getattr(v1, 'z'))")
+`)) })
+```
+
+You should restore the `print()` calls you commented out before and remove the second argument from both of them.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).has_call("print(f'v1 = {v1}')") and _Node(_code).has_call("print(f'v2 = {v2}')")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+print(v1.z)
+print(getattr(v1, 'z'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
index f84624b42de..e9870c4826a 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
@@ -1,6 +1,6 @@
---
id: 6553ed69ece88d29594748aa
-title: Step 50
+title: Step 52
challengeType: 20
dashedName: step-52
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
index bf46d6f32ca..36913664567 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
@@ -1,6 +1,6 @@
---
id: 6553efd6ada3f42aa2d75448
-title: Step 51
+title: Step 53
challengeType: 20
dashedName: step-53
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
index 2688363421c..bdc61a56deb 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
@@ -1,6 +1,6 @@
---
id: 6553f3fc92741c2bf8ded140
-title: Step 52
+title: Step 54
challengeType: 20
dashedName: step-54
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
index 16b2b7a8c78..c54923b4ea2 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
@@ -1,6 +1,6 @@
---
id: 6553f4f66099802c6ae94613
-title: Step 53
+title: Step 55
challengeType: 20
dashedName: step-55
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
index bcae9e4c2a5..92734e07289 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
@@ -1,6 +1,6 @@
---
id: 6553f6086add4b2cbb99fd78
-title: Step 54
+title: Step 56
challengeType: 20
dashedName: step-56
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
index 2f0fc79d3ff..1355edcf141 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
@@ -1,6 +1,6 @@
---
id: 6553f8c570f9982e013a8886
-title: Step 55
+title: Step 57
challengeType: 20
dashedName: step-57
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
index 51c7c51620d..5b984de7d3b 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
@@ -1,6 +1,6 @@
---
id: 655491bd5b98b813fa5bedca
-title: Step 56
+title: Step 58
challengeType: 20
dashedName: step-58
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
index 64bef622b35..b6a7f0aa9c6 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
@@ -1,6 +1,6 @@
---
id: 6554930320d70414e7b6acc6
-title: Step 57
+title: Step 59
challengeType: 20
dashedName: step-59
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
index c2b67a816d2..ab8d95e137d 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
@@ -1,6 +1,6 @@
---
id: 65549561463f0016876e852c
-title: Step 58
+title: Step 60
challengeType: 20
dashedName: step-60
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
index 5d4a37a2fe9..839352832e3 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
@@ -1,6 +1,6 @@
---
id: 65549f90cf78131c96ebcf28
-title: Step 59
+title: Step 61
challengeType: 20
dashedName: step-61
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
index 4c05b0584c4..01181c37df7 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
@@ -1,6 +1,6 @@
---
id: 6554a334a40edb1fb4eff827
-title: Step 60
+title: Step 62
challengeType: 20
dashedName: step-62
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
index 63e5be90540..921879d9acc 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
@@ -1,6 +1,6 @@
---
id: 6554a49a4f782f208abcc87e
-title: Step 61
+title: Step 63
challengeType: 20
dashedName: step-63
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
index c8c045af50c..139a3fea8db 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
@@ -1,6 +1,6 @@
---
id: 6554a57ec0a2c52106e7ee50
-title: Step 62
+title: Step 64
challengeType: 20
dashedName: step-64
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
index f8aec7c6f01..b1c21af09e5 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
@@ -1,6 +1,6 @@
---
id: 6554a88d5af937226f4a9121
-title: Step 63
+title: Step 65
challengeType: 20
dashedName: step-65
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
index 9f67d3e0905..2bff453ec4b 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
@@ -1,6 +1,6 @@
---
id: 6554ac937a49be2701af4f2f
-title: Step 64
+title: Step 66
challengeType: 20
dashedName: step-66
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
index d9b8dbfc283..4c7bb7ab462 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
@@ -1,6 +1,6 @@
---
id: 6554ad2463b8892748f8efdd
-title: Step 65
+title: Step 67
challengeType: 20
dashedName: step-67
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
index e2ed67b3ab6..1eeeb3697b1 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
@@ -1,6 +1,6 @@
---
id: 6554d0332949b133a0b35eaa
-title: Step 66
+title: Step 68
challengeType: 20
dashedName: step-68
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
index 863de41bbc0..5f093f3df2c 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
@@ -1,6 +1,6 @@
---
id: 6554d15c8acb5f34499ad789
-title: Step 67
+title: Step 69
challengeType: 20
dashedName: step-69
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
index c24fa10d6c6..65ac8f3f6c4 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
@@ -1,6 +1,6 @@
---
id: 6554d25dc5ceaa354307a77e
-title: Step 68
+title: Step 70
challengeType: 20
dashedName: step-70
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
index 076f1a41e91..2df3eb6fceb 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
@@ -1,6 +1,6 @@
---
id: 6554de295ade563a069936a1
-title: Step 69
+title: Step 71
challengeType: 20
dashedName: step-71
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
index 9793f1023c3..5e52b90279e 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
@@ -1,6 +1,6 @@
---
id: 6554dfce1683be3c0c9609a6
-title: Step 70
+title: Step 72
challengeType: 20
dashedName: step-72
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
index 9454a27cb5e..02e14d9019c 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
@@ -1,6 +1,6 @@
---
id: 6554e0adc7bb193cbfdb36d5
-title: Step 71
+title: Step 73
challengeType: 20
dashedName: step-73
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
index 182346eca82..7f91537aead 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
@@ -1,6 +1,6 @@
---
id: 6554e2ee23bfd93f2c83640f
-title: Step 72
+title: Step 74
challengeType: 20
dashedName: step-74
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
index 48ececac1ab..d5bdb7ff5d1 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
@@ -1,6 +1,6 @@
---
id: 6554e343caea913ffba7bec6
-title: Step 73
+title: Step 75
challengeType: 20
dashedName: step-75
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
index 368cf69b225..a80c318bd1d 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
@@ -1,6 +1,6 @@
---
id: 655516e410b8e30fb4fb64e8
-title: Step 74
+title: Step 76
challengeType: 20
dashedName: step-76
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
index e4d257548fb..19fa2bb8b2b 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
@@ -1,6 +1,6 @@
---
id: 65551a628bcb7e121e32d04b
-title: Step 77
+title: Step 79
challengeType: 20
dashedName: step-79
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
index 7f0ec8191b3..8603eb7e6d8 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
@@ -1,6 +1,6 @@
---
id: 6555201d9b7fc917399f9f0b
-title: Step 78
+title: Step 80
challengeType: 20
dashedName: step-80
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
index 01549558a4b..5c6c8181984 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
@@ -1,6 +1,6 @@
---
id: 655520c20cb1e6177b0641d6
-title: Step 79
+title: Step 81
challengeType: 20
dashedName: step-81
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
index cc4f4eacee1..db091c232cc 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
@@ -1,6 +1,6 @@
---
id: 655522883e66f618e03a9411
-title: Step 80
+title: Step 82
challengeType: 20
dashedName: step-82
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
index cd29fc36bb4..9588d739f44 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
@@ -1,6 +1,6 @@
---
id: 6555231eac4d9f19bd3d44b5
-title: Step 81
+title: Step 83
challengeType: 20
dashedName: step-83
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
index c02b037de64..b8c910a3aa5 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
@@ -1,6 +1,6 @@
---
id: 65552a111190e11f0963949e
-title: Step 82
+title: Step 84
challengeType: 20
dashedName: step-84
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
index eb0c5d14c63..28da95df2b0 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
@@ -1,6 +1,6 @@
---
id: 65552a9593755e1fb2f5ab50
-title: Step 83
+title: Step 85
challengeType: 20
dashedName: step-85
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
index aa1a050cf04..4fcaff7b89c 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
@@ -1,6 +1,6 @@
---
id: 65552b14e803731fe3c1e4ca
-title: Step 84
+title: Step 86
challengeType: 20
dashedName: step-86
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
index 3b6cc0579a3..f8ea2a67964 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
@@ -1,6 +1,6 @@
---
id: 65553159615a8123b190ee43
-title: Step 85
+title: Step 87
challengeType: 20
dashedName: step-87
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
index 1e3ad3dfb8a..6799724af14 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
@@ -1,6 +1,6 @@
---
id: 6555d6e12c95701172b55709
-title: Step 75
+title: Step 77
challengeType: 20
dashedName: step-77
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
index f3c3b93e0c6..97049b3b537 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
@@ -1,6 +1,6 @@
---
id: 6555d8b0b3d20b128bdadd37
-title: Step 76
+title: Step 78
challengeType: 20
dashedName: step-78
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
index 866b80d387b..d310105bfe1 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
@@ -1,6 +1,6 @@
---
id: 6555db4a7b788e15795674e5
-title: Step 87
+title: Step 89
challengeType: 20
dashedName: step-89
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
index 2cf86f2dd96..3a91139cf33 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
@@ -1,6 +1,6 @@
---
id: 6555df0c81300b175308557d
-title: Step 88
+title: Step 90
challengeType: 20
dashedName: step-90
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
index 959034b7875..bc5788b45f8 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
@@ -1,6 +1,6 @@
---
id: 6555e1bfcd374e18c6be8e58
-title: Step 89
+title: Step 91
challengeType: 20
dashedName: step-91
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
index 791d9bdbd6d..4d7848b4be9 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
@@ -1,6 +1,6 @@
---
id: 6555e3f387381a19d5e00333
-title: Step 90
+title: Step 92
challengeType: 20
dashedName: step-92
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
index 20f69b6bd24..e895a41b321 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
@@ -1,6 +1,6 @@
---
id: 6555e43e783ed31a0532b1b2
-title: Step 91
+title: Step 93
challengeType: 20
dashedName: step-93
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
index 9acf44cfdc2..f878bb6c12b 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
@@ -1,6 +1,6 @@
---
id: 6555e547c18a2b1a7b795bd8
-title: Step 93
+title: Step 95
challengeType: 20
dashedName: step-95
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
index 312d322e32f..9b3df4758a0 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
@@ -1,6 +1,6 @@
---
id: 6555e5991af57d1ae0e35f0a
-title: Step 94
+title: Step 96
challengeType: 20
dashedName: step-96
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
index 3493c823d5d..1bb2f8f1567 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
@@ -1,6 +1,6 @@
---
id: 65a450e8fb2c9d75c7378d28
-title: Step 86
+title: Step 88
challengeType: 20
dashedName: step-88
---
diff --git a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
index a15a486b7eb..29a960e8277 100644
--- a/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
+++ b/curriculum/challenges/espanol/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
@@ -1,6 +1,6 @@
---
id: 65a51c9e000b660122b8b29e
-title: Step 92
+title: Step 94
challengeType: 20
dashedName: step-94
---
diff --git a/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a00ed1ca871a2b3aca0cb.md b/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a00ed1ca871a2b3aca0cb.md
index 7e6ea1e0802..a04e31b5367 100644
--- a/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a00ed1ca871a2b3aca0cb.md
+++ b/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/618a00ed1ca871a2b3aca0cb.md
@@ -9,7 +9,7 @@ dashedName: step-35
Una vez estudiados los colores primarios, secundarios y terciarios sobre un círculo cromático, será más sencillo comprender otros conceptos de teoría del color y qué impacto pueden tener en el diseño.
-First, in the CSS rules `.one`, `.two`, and `.three`, adjust the values in the `rgb` function so that the `background-color` of each element is set to pure black. Recuérdese que la función `rgb` utiliza el modelo aditivo, en el que los colores comienzan como negro y cambian a medida que los valores de rojo, verde y azul aumentan.
+Primero, en las reglas CSS `.one`, `.two` y `.three`, ajusta los valores de la función `rgb` para que el color de fondo, `background-color` de cada elemento, sea completamente negro. Recuérdese que la función `rgb` utiliza el modelo aditivo, en el que los colores comienzan como negro y cambian a medida que los valores de rojo, verde y azul aumentan.
# --hints--
diff --git a/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b74fa777a2b2473c94f82.md b/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b74fa777a2b2473c94f82.md
index 2e84aa02aec..3701aecdd22 100644
--- a/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b74fa777a2b2473c94f82.md
+++ b/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/619b74fa777a2b2473c94f82.md
@@ -7,7 +7,7 @@ dashedName: step-45
# --description--
-Actualiza el selector de clase CSS `.two` de manera que apunte a la nueva clase `green`. And update the `.three` class selector so it targets the new `blue` class.
+Actualiza el selector de clase CSS `.two` de manera que apunte a la nueva clase `green`. Y actualiza el selector de clase `.three` para que apunte a la nueva clase `blue`.
# --hints--
diff --git a/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61a5d7ef1cfcf45764df07a2.md b/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61a5d7ef1cfcf45764df07a2.md
index 03894510678..08e0b9d7e9a 100644
--- a/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61a5d7ef1cfcf45764df07a2.md
+++ b/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61a5d7ef1cfcf45764df07a2.md
@@ -9,7 +9,7 @@ dashedName: step-70
Ahora que los marcadores tienen los colores correctos, es hora de construir las fundas de los marcadores. Empieza con el marcador rojo.
-Inside the red marker `div` element, create a new `div` element and give it a class of `sleeve`.
+Crea un elemento `div` dentro del elemento `div` del marcador rojo y asígnale la clase `sleeve`.
# --hints--
diff --git a/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b093329e7fc020b43b1bb5.md b/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b093329e7fc020b43b1bb5.md
index 98cb3637e10..ee8772bcdbe 100644
--- a/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b093329e7fc020b43b1bb5.md
+++ b/curriculum/challenges/espanol/14-responsive-web-design-22/learn-css-colors-by-building-a-set-of-colored-markers/61b093329e7fc020b43b1bb5.md
@@ -17,11 +17,11 @@ rgba(redValue, greenValue, blueValue, alphaValue);
También puedes usar un canal alfa con colores `hsl` y `hex`. Más adelante verás como hacerlo.
-In the `.sleeve` rule, use the `rgba` function to set the `background-color` property to pure white with 50% opacity.
+En la regla `.sleeve`, utiliza la función `rgba` para establecer la propiedad `background-color` a blanco puro con un 50% de opacidad.
# --hints--
-Your `.sleeve` CSS rule should have a `background-color` property set to `rgba(255, 255, 255, 0.5)`.
+Tu regla CSS `.sleeve` debe tener una propiedad `background-color` con valor `rgba(255, 255, 255, 0.5)`.
```js
assert(new __helpers.CSSHelp(document).getStyle('.sleeve')?.backgroundColor === 'rgba(255, 255, 255, 0.5)');
diff --git a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md b/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
deleted file mode 100644
index 632abe728dd..00000000000
--- a/curriculum/challenges/espanol/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
+++ /dev/null
@@ -1,344 +0,0 @@
----
-id: 62aa1fed3d4e873366ff3131
-title: Step 150
-challengeType: 0
-dashedName: step-150
----
-
-# --description--
-
-In your `attack` function, below the `health` variable, create an `if` statement. Set the condition to call the `isMonsterHit` function.
-
-# --hints--
-
-You should add an `if` statement which calls `isMonsterHit` in the condition.
-
-```js
-assert.match(attack.toString(), /if\s*\(\s*isMonsterHit\s*\(\s*\)/)
-```
-
-# --seed--
-
-## --seed-contents--
-
-```html
-
-
-
-
-
-
+
+Within the `Vector` class, create an `__init__` method and give it three parameters, `self`, `x`, and `y`.
+
+# --hints--
+
+You should define an `__init__` method inside the `Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").has_function("__init__")`)) })
+```
+
+Your `__init__` method should take three parameters: `self`, `x`, and `y`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").find_function("__init__").has_args("self, x, y")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ pass
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
new file mode 100644
index 00000000000..62ab349a8db
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
@@ -0,0 +1,38 @@
+---
+id: 65f055b9190fc41ca35549b8
+title: Step 3
+challengeType: 20
+dashedName: step-3
+---
+
+# --description--
+
+Python offers various methods that include both a leading and trailing double underscore in their names. You may already be familiar with some, such as `__init__` and `__str__`. These methods, which follow the `__
+
+So far, you created a 2-dimensional vector. You want to be able to represent vectors with a different number of dimensions without rewriting the necessary code for each specific case. For that, you will use inheritance.
+
+Start by renaming the `Vector` class into `R2Vector` to specify that this class is going to deal with 2-dimensional vectors. Remember to modify the instantiation of `v1`, too.
+
+# --hints--
+
+You should rename the `Vector` class into `R2Vector`. Remember to modify the instantiation of `v1`, too.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+v1 = Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
new file mode 100644
index 00000000000..e26a20b0730
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
@@ -0,0 +1,70 @@
+---
+id: 65f40051d6b09a139f253e8e
+title: Step 12
+challengeType: 20
+dashedName: step-12
+---
+
+# --description--
+
+Inheritance enables you to define a class from an existing one. The new class, called child, inherits all the methods and properties of the existing class, called parent.
+
+```py
+class Tree:
+ def sprout(self):
+ print('Making new leaves!')
+
+class Oak(Tree):
+ pass
+
+Oak().sprout() # Output: Making new leaves!
+```
+
+In the example above, the child class `Oak` inherits from `Tree` and inherits the `sprout` method from the parent class `Tree`.
+
+Create a new class named `R3Vector` and follow the example above to make it inherit from the `R2Vector` class.
+
+# --hints--
+
+You should define a new class `R3Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R3Vector")
+ `))
+})
+```
+
+Your new class `R3Vector` should inherit from `R2Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").inherits_from("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
new file mode 100644
index 00000000000..c50cbefeb4a
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
@@ -0,0 +1,56 @@
+---
+id: 65f40401e6ef53173c04e27d
+title: Step 13
+challengeType: 20
+dashedName: step-13
+---
+
+# --description--
+
+Within your new class, declare an `__init__` method. Give it `self`, `x`, `y`, and `z` as the parameters.
+
+# --hints--
+
+You should define an `__init__` method inside your `R3Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").has_function("__init__")
+ `))
+})
+```
+
+Your `__init__` method should have four parameters `self`, `x`, `y`, and `z`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, x, y, z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
new file mode 100644
index 00000000000..cb7a33c0eb1
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
@@ -0,0 +1,49 @@
+---
+id: 65f407ea37ad6e181b90462e
+title: Step 14
+challengeType: 20
+dashedName: step-14
+---
+
+# --description--
+
+You could assign each `i` parameter to `self.i` as you did before. Although in this case you have few lines to repeat, one way to avoid this repetition is using the `super()` function. `super()` enables you to refer implicitly to the parent class: `super().__init__(x, y)` calls the `__init__` method of the parent class.
+
+Add a `super().__init__(x, y)` call to your `__init__` method.
+
+# --hints--
+
+You should have a `super().__init__(x, y)` call in your `__init__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_stmt("super().__init__(x, y)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
new file mode 100644
index 00000000000..caf708394fc
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
@@ -0,0 +1,47 @@
+---
+id: 65f40f8af784751c613d638a
+title: Step 15
+challengeType: 20
+dashedName: step-15
+---
+
+# --description--
+
+Now, you need to assign `z` to the `z` attribute of your `R3Vector` object.
+
+# --hints--
+
+You should assign `z` to `self.z` after the `super` call.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").is_ordered("super().__init__(x, y)", "self.z = z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
new file mode 100644
index 00000000000..68340ee6c11
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
@@ -0,0 +1,47 @@
+---
+id: 65f40fdb3579aa1ced28b2eb
+title: Step 16
+challengeType: 20
+dashedName: step-16
+---
+
+# --description--
+
+Create an `R3Vector` instance with `2`, `2`, and `3` as the values of `x`, `y`, and `z`, respectively. Assign the new instance to `v2`.
+
+# --hints--
+
+You should declare a variable `v2` and assign it `R3Vector(2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(2, 2, 3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
new file mode 100644
index 00000000000..06b727e3b29
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
@@ -0,0 +1,72 @@
+---
+id: 65f412c208c3791fee305acf
+title: Step 17
+challengeType: 20
+dashedName: step-17
+---
+
+# --description--
+
+In Python, you can enforce the use of keyword-only arguments by adding a `*` as an additional argument to the function or method signature. Modify both `__init__` methods by adding a `*` as the second parameter (after `self`). Every parameter placed after that will require the use of a keyword argument in the function/method call.
+
+This means that you need to modify the `super().__init__(x, y)` call, too. Do it by giving `x` the value `x`, and `y` the value `y`.
+
+Finally, modify the instantiation of `v1` and `v2` by using keyword arguments.
+
+# --hints--
+
+You should enforce keyword arguments by adding a `*` as the second parameter in both your `__init__` methods.
+
+```js
+({ test: () => {
+ assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__init__").has_args("self, *, x, y")`));
+ assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, *, x, y, z")`));
+} })
+```
+
+You should modify your `super.__init__(x, y)` call to use keyword arguments.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").find_body().is_equivalent("super().__init__(x=x, y=y)\\nself.z = z")`)) })
+```
+
+You should modify the assignment of `v1` to be `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R2Vector(x=2, y=3)")`)) })
+```
+
+You should modify the assignment of `v2` to be `R3Vector(x=2, y=2, z=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=2, y=2, z=3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+v2 = R3Vector(2, 2, 3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
new file mode 100644
index 00000000000..ef31cdd6194
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
@@ -0,0 +1,64 @@
+---
+id: 65f4148dea0f802040225e0c
+title: Step 18
+challengeType: 20
+dashedName: step-18
+---
+
+# --description--
+
+Remove the existing `print` calls. Then, as you did before for `v1`, print `v2` and the value returned by `v2.norm()`.
+
+# --hints--
+
+You should not have `print(v1)` and `print(v1.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1.norm())")`));
+ }
+})
+```
+
+You should print `v2` and `v2.norm()`.
+
+```js
+({
+ test: () => {
+ assert(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+print(v1.norm())
+print(v1)
+
+v2 = R3Vector(x=2, y=2, z=3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
new file mode 100644
index 00000000000..1a83f17e994
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
@@ -0,0 +1,64 @@
+---
+id: 65f4520e363e2642f8112e33
+title: Step 19
+challengeType: 20
+dashedName: step-19
+---
+
+# --description--
+
+As you can see, something is not quite right. The `norm` and `__str__` methods inherited from `R2Vector` cannot adapt to a 3-dimensional vector. Their implementation has to be more flexible.
+
+Every object in Python has a special attribute named `__dict__`, which is a dictionary that stores the object attributes.
+
+Remove the existing `print` calls. Then, print the `__dict__` attribute of your `v1` and `v2` vectors to see what they look like.
+
+# --hints--
+
+You should not have `print(v2)` and `print(v2.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+You should print the `__dict__` attribute of `v1` and `v2`.
+
+```js
+({ test: () => assert(runPython(`
+(_Node(_code).has_call("print(v1.__dict__)") and _Node(_code).has_call("print(v2.__dict__)")) or _Node(_code).has_call("print(v1.__dict__, v2.__dict__)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v2.norm())
+print(v2)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
new file mode 100644
index 00000000000..2a2c8f28376
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
@@ -0,0 +1,49 @@
+---
+id: 65f4535bbdb28d436ff3ddc9
+title: Step 20
+challengeType: 20
+dashedName: step-20
+---
+
+# --description--
+
+As you can see from the output, `__dict__` contains the values of your instance attributes. Instead of explicitly adding the squares of `self.x` and `self.y`, you are going to iterate over the values stored in `__dict__` to calculate the value of the norm.
+
+Within the `norm` method body, replace the content of the parentheses with a generator expression that elevates each value `val` in `self.__dict__.values()` to the power of `2`. Also, pass that generator expression as the argument to the `sum` function, so that all the squares are added together before calculating the square root.
+
+# --hints--
+
+You should return `sum(val**2 for val in self.__dict__.values())**0.5` from `norm()` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in self.__dict__.values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
new file mode 100644
index 00000000000..bbb82436c52
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
@@ -0,0 +1,53 @@
+---
+id: 65f870003444fb1a2ad171f2
+title: Step 21
+challengeType: 20
+dashedName: step-21
+---
+
+# --description--
+
+Modify the two `print` calls to print the norm of your vectors and verify that the `norm()` method works fine.
+
+# --hints--
+
+You should print `v1.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1.norm())")`)) })
+```
+
+You should print `v2.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v2.norm())")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
new file mode 100644
index 00000000000..22e3cab792e
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
@@ -0,0 +1,61 @@
+---
+id: 65f8709620b2ce1a62608f5a
+title: Step 23
+challengeType: 20
+dashedName: step-23
+---
+
+# --description--
+
+When you need to dynamically access some attributes starting from a string input, the built-in `getattr()` function is what you need. It takes an object as its first argument, and a string containing the attribute name as its second attribute.
+
+Start to fix the `__str__` method by replacing the string returned by `__str__()` with a generator expression that iterates through the object attributes and calls `getattr()` for each attribute `i`.
+
+# --hints--
+
+You should return a generator expression that iterates over `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_iters()[0].is_equivalent("vars(self)")`)) })
+```
+
+You should return a generator expression that uses `i` as the iteration variable.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_targets()[0].is_equivalent("i")`)) })
+```
+
+You should return a generator expression that calls `getattr(self, i)` for each item `i` in `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_expr().is_equivalent("getattr(self, i)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
new file mode 100644
index 00000000000..668bd89de56
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
@@ -0,0 +1,47 @@
+---
+id: 65f8720685ec351abef26740
+title: Step 24
+challengeType: 20
+dashedName: step-24
+---
+
+# --description--
+
+To obtain a proper string representation, call the `tuple()` constructor and pass it the generator expression you wrote in the previous step as the argument.
+
+# --hints--
+
+You should pass the expression returned by the `__str__` method to the `tuple()` constructor.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("tuple(getattr(self, i) for i in vars(self))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return (getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
new file mode 100644
index 00000000000..789f37ee6fe
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
@@ -0,0 +1,47 @@
+---
+id: 65f872a0fe6aa21b456ad4fe
+title: Step 25
+challengeType: 20
+dashedName: step-25
+---
+
+# --description--
+
+Finally, pass the `tuple()` call as the argument to the `str()` function.
+
+# --hints--
+
+You should pass the `tuple()` call you are currently returning from the `__str__` method to the `str()` function.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("str(tuple(getattr(self, i) for i in vars(self)))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return tuple(getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
new file mode 100644
index 00000000000..6a2c44baef5
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
@@ -0,0 +1,56 @@
+---
+id: 65f8749b13774b1d2e4a7fba
+title: Step 27
+challengeType: 20
+dashedName: step-27
+---
+
+# --description--
+
+While the `__str__` method returns a human-readable string representation of an object, the `__repr__` method is supposed to return the string needed to instantiate the object.
+
+Add a `__repr__` method with a `self` parameter within the `R2Vector` class.
+
+# --hints--
+
+Your `R2Vector` class should have a `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__repr__")`)) })
+```
+
+Your `__repr__` method should have a `self` parameter.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_args("self")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
new file mode 100644
index 00000000000..7f5a3e0f9c9
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
@@ -0,0 +1,74 @@
+---
+id: 65f876d17832001e8e1abb05
+title: Step 28
+challengeType: 20
+dashedName: step-28
+---
+
+# --description--
+
+Declare a variable `arg_list`. Give it the value of a list comprehension that iterates over `key` and `val` for each key-value pair in `vars(self).items()` and computes the f-string `f'{key}={val}'` at each iteration.
+
+# --hints--
+
+You should declare a variable `arg_list`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_variable("arg_list")`)) })
+```
+
+You should assign a list comprehension that iterates over `vars(self).items()` to `arg_list`.
+
+```js
+({ test: () => runPython(`
+import ast
+var = _Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list")
+assert isinstance(var.tree.value, ast.ListComp), "Expected arg_list to be a list comprehension"
+assert (actual := var.find_comp_iters()[0].is_equivalent("vars(self).items()")), f"Expected vars(self).items(), got {actual}"
+`) })
+```
+
+The list comprehension assigned to `arg_list` should use `key` and `val` to iterate over `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_targets()[0].is_equivalent("key, val")
+`)) })
+```
+
+The list comprehension assigned to `arg_list` should compute the string `f'{key}={val}'` for each key-value pair in `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_expr().is_equivalent("f'{key}={val}'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
new file mode 100644
index 00000000000..0c56316394e
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
@@ -0,0 +1,50 @@
+---
+id: 65f93acbb514857003510e79
+title: Step 29
+challengeType: 20
+dashedName: step-29
+---
+
+# --description--
+
+Declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+# --hints--
+
+You should declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("args").is_equivalent("args = ', '.join(arg_list)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
new file mode 100644
index 00000000000..e826611fa57
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
@@ -0,0 +1,52 @@
+---
+id: 65f93b67169a9c703264458a
+title: Step 30
+challengeType: 20
+dashedName: step-30
+---
+
+# --description--
+
+Since the method should return the string to instantiate the object for `R2Vector` as well as `R3Vector` when inherited, you cannot build the string specifying the class name.
+
+You can access the name of a class with `__class__.__name__`. Add a `return` statement to the `__repr__` method and return the string necessary to instantiate the object.
+
+# --hints--
+
+You should use `__class__.__name__` to build the f-string needed to instantiate a vector object and return it from the `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_return("f'{self.__class__.__name__}({args})'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
new file mode 100644
index 00000000000..13682539c2c
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
@@ -0,0 +1,57 @@
+---
+id: 65f93d4647ce2670dc6f095c
+title: Step 31
+challengeType: 20
+dashedName: step-31
+---
+
+# --description--
+
+The `__repr__` method is called under the hood by the `repr` function. Verify that `__repr__` works properly by adding `f'\nrepr = {repr(v1)}'` and `f'\nrepr = {repr(v2)}'` as the second argument to your first and second `print` calls, respectively.
+
+# --hints--
+
+You should add `f'\nrepr = {repr(v1)}'` as the second argument to your `print(f'v1 = {v1}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}', f'\\\\nrepr = {repr(v1)}')")`)) })
+```
+
+You should add `f'\nrepr = {repr(v2)}'` as the second argument to your `print(f'v2 = {v2}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}', f'\\\\nrepr = {repr(v2)}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
new file mode 100644
index 00000000000..a25da243ba9
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
@@ -0,0 +1,56 @@
+---
+id: 65f93e54a9121571dcdd3e79
+title: Step 32
+challengeType: 20
+dashedName: step-32
+---
+
+# --description--
+
+The output is correct, `repr` is giving you the string required to instantiate the objects.
+
+Now comment out both your `print` calls.
+
+# --hints--
+
+You should comment out both your `print()` calls.
+
+```js
+({ test: () => {
+ assert.match(code, /#\s*print\s*\(\s*f('|")v1 = \{\s*v1\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v1\s*\)\s*\}\2\s*\)/);
+ assert.match(code, /#\s*print\s*\(\s*f('|")v2 = \{\s*v2\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v2\s*\)\s*\}\2\s*\)/);
+} })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
new file mode 100644
index 00000000000..127f701ba31
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
@@ -0,0 +1,62 @@
+---
+id: 65f9b17a638f0d0dcce8c354
+title: Step 38
+challengeType: 20
+dashedName: step-38
+---
+
+# --description--
+
+To create a vector space, you need to define how vectors should behave in several cases. Vectors can be added, forming a new vector.
+
+The special method `__add__` can be implemented to override what happens by default when two objects are added together using the `+` operator.
+
+Right now, trying to add two instances of `R2Vector` or `R3Vector` would raise an exception. Create an empty `__add__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define an `__add__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__add__")`)) })
+```
+
+Your `__add__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
new file mode 100644
index 00000000000..f90c14fe57b
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b486989cb90ff3e77ac8
+title: Step 39
+challengeType: 20
+dashedName: step-39
+---
+
+# --description--
+
+The `other` parameter of your `__add__` method represents the operand placed at the right side of the `+` operator in an addition operation.
+
+You want to verify that the right-hand operand is not an object of the same class as the left-hand operand (i.e. `self`). Create an `if` statement that verifies that by checking the type of the operands.
+
+# --hints--
+
+You should create an `if` statement that checks if `type(self)` and `type(other)` are different.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
new file mode 100644
index 00000000000..1fa83e0f9aa
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b9710cca621244d3bde1
+title: Step 40
+challengeType: 20
+dashedName: step-40
+---
+
+# --description--
+
+In Python, `NotImplemented` is a special value used to indicate that an operation is not implemented for a specific case.
+
+`NotImplemented` does not raise an exception immediately. Instead, it signals to ask to the other operand how to perform the operation. If the request cannot be satisfied, a `TypeError` is returned by default.
+
+Because you want to be able to sum two vectors only if they belong to the same class, return `NotImplemented` from the `if` statement you created in the previous step.
+
+# --hints--
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
new file mode 100644
index 00000000000..9df77e46895
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
@@ -0,0 +1,58 @@
+---
+id: 65f9bb7c0d524612b2a88a4b
+title: Step 41
+challengeType: 20
+dashedName: step-41
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_stmt("kwargs = {}")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
new file mode 100644
index 00000000000..f5d28e43bd6
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
@@ -0,0 +1,92 @@
+---
+id: 65f9bc10a9fb1612e066e9e8
+title: Step 42
+challengeType: 20
+dashedName: step-42
+---
+
+# --description--
+
+When adding two vectors, each component of one vector is added to the same component of the other vector. For example, adding `(1, 2)` and `(2, 4)` generates a third vector `(3, 6)`, where `3` is the sum of `1` and `2` and `6` is the sum of `2` and `4`.
+
+The `kwargs` dictionary will contain the key-value pairs needed to instantiate a new vector of the same class of the two vectors added together.
+
+Turn the empty dictionary into a dictionary comprehension that iterates through `vars(self)` and for each key (`i`) creates a key-value pair, where the key is the same key of the current iteration and its value is the sum of the values of the `i` attributes of the two operands.
+
+# --hints--
+
+You should turn the empty dictionary assigned to `kwargs` into a dictionary comprehension that iterates over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_iters()[0].is_equivalent("vars(self)")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_key().is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the sum of the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i` in `vars(self)`. Use the `getattr()` function for that.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) + getattr(other, i)") or node.is_equivalent("getattr(other, i) + getattr(self, i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
new file mode 100644
index 00000000000..d1cd1755778
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
@@ -0,0 +1,70 @@
+---
+id: 65f9c2c2006feb1428ad2d4c
+title: Step 43
+challengeType: 20
+dashedName: step-43
+---
+
+# --description--
+
+You can unpack a dictionary into keyword arguments by using the `**` operator:
+
+```py
+def spam(a, b):
+ return a + b
+
+my_dict = {a: 11, b: 4}
+
+spam(**my_dict) # 15
+```
+
+Return an instance of the current class by using `__class__` and passing `**kwargs` as the argument.
+
+# --hints--
+
+You should return `self.__class__(**kwargs)` from the `__add__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
new file mode 100644
index 00000000000..689ab778fe5
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
@@ -0,0 +1,90 @@
+---
+id: 65f9cb678070ca1668898c70
+title: Step 44
+challengeType: 20
+dashedName: step-44
+---
+
+# --description--
+
+In the same way `__add__` is called under the hood when two objects are added together, the `__sub__` method is called implicitly in case of subtraction.
+
+Now, define an empty `__sub__` method and give two parameters: `self`, and `other`. Inside your new method, create an if statement to check if `self` and `other` do not belong to the same class and return `NotImplemented`, as you did previously.
+
+# --hints--
+
+You should define a `__sub__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__sub__")
+ `))
+})
+```
+
+Your `__sub__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_args("self, other")
+ `))
+})
+```
+
+You should create an `if` statement that checks if `self` and `other` does not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+ `))
+})
+```
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
new file mode 100644
index 00000000000..2d452d2413e
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
@@ -0,0 +1,89 @@
+---
+id: 65f9dd6e5a08af19c196c2df
+title: Step 45
+challengeType: 20
+dashedName: step-45
+---
+
+# --description--
+
+The vector resulting from the subtraction of one vector from another is obtained by calculating the difference of each of their components. For example, subtracting `(2, 4)` from `(7, 3)` generates a third vector `(5, -1)`, where `5` is the difference between `7` and `2` and `-1` is the difference between `3` and `4`.
+
+As you did before inside the `__add__` method, declare a `kwargs` variable after the `if` statement. Assign it a dictionary comprehension that iterates through the object attributes and creates a key-value pair for each key `i`, where the key is the same key as the current iteration and its value is the difference between the values of the `i` attributes of two operands.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it a dictionary comprehension that iterates over the object attributes.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_iters()[0]
+node.is_equivalent("vars(self)") or node.is_equivalent("self.__dict__")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over the object attributes.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_key().is_equivalent("i")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the difference between the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i`.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) - getattr(other, i)") or node.is_equivalent("self.__getattribute__(i) - other.__getattribute__(i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
new file mode 100644
index 00000000000..095bce27c7c
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
@@ -0,0 +1,65 @@
+---
+id: 65f9dfd2e75e291a38695f13
+title: Step 46
+challengeType: 20
+dashedName: step-46
+---
+
+# --description--
+
+Finally, return a new vector object. Use `__class__` and unpack `kwargs` to instantiate the new vector.
+
+# --hints--
+
+You should return a new vector using `__class__` and unpacking `kwargs` from the `__sub__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
new file mode 100644
index 00000000000..c5cb7742541
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
@@ -0,0 +1,67 @@
+---
+id: 65f9e0a578b22c1a736f3d82
+title: Step 47
+challengeType: 20
+dashedName: step-47
+---
+
+# --description--
+
+Modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+# --hints--
+
+You should modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v2 = R2Vector(x=0.5, y=1.25)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
new file mode 100644
index 00000000000..1d277671da4
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
@@ -0,0 +1,67 @@
+---
+id: 65fa8d5cf0ef3b141010f5d8
+title: Step 48
+challengeType: 20
+dashedName: step-48
+---
+
+# --description--
+
+It's time to verify that the addition and subtraction operations work as expected. Declare another variable `v3` and assign it the sum of `v1` plus `v2`.
+
+# --hints--
+
+You should declare a variable `v3` and assign it the sum of `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v3 = v1 + v2") or _Node(_code).has_stmt("v3 = v2 + v1")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
new file mode 100644
index 00000000000..87ddac5ea5f
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
@@ -0,0 +1,64 @@
+---
+id: 65fa8df56a0e2c149b4d24fe
+title: Step 49
+challengeType: 20
+dashedName: step-49
+---
+
+# --description--
+
+Next, check the new vector by printing the following f-string `f'v1 + v2 = {v3}'`.
+
+# --hints--
+
+You should print `f'v1 + v2 = {v3}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 + v2 = {v3}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
new file mode 100644
index 00000000000..e526a9cd4cc
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
@@ -0,0 +1,77 @@
+---
+id: 65fa9402d1fb5516aa42159d
+title: Step 50
+challengeType: 20
+dashedName: step-50
+---
+
+# --description--
+
+Feel free to modify `v3` so that it sums an `R2Vector` instance with an object of a different type, such as an integer or a string. You will be able to see a `TypeError` message printed on the console.
+
+Then, restore the original line and create a new variable `v4`. Assign the difference between `v1` and `v2` to your new variable and print the result following the same structure as the previous f-string.
+
+# --hints--
+
+You should declare a variable `v4` and assign it the difference between `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v4 = v1 - v2")
+ `))
+})
+```
+
+You should print `f'v1 - v2 = {v4}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 - v2 = {v4}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
new file mode 100644
index 00000000000..d2df1c3038d
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
@@ -0,0 +1,85 @@
+---
+id: 65fa9e1b6c6db919385359ec
+title: Step 51
+challengeType: 20
+dashedName: step-51
+---
+
+# --description--
+
+The special method `__mul__` can be implemented to specify what should happen when the current instance is multiplied by another object.
+
+Create an empty `__mul__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `__mul__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__mul__")
+ `))
+})
+```
+
+Your `__mul__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__mul__").has_args("self, other")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
new file mode 100644
index 00000000000..0a18b8b69d1
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
@@ -0,0 +1,94 @@
+---
+id: 65faaed8f7a9772f023ea816
+title: Step 52
+challengeType: 20
+dashedName: step-52
+---
+
+# --description--
+
+Vectors can be multiplied by a *scalar*, i.e. a number that multiplies each single component. The result of scalar multiplication is a vector with the same orientation as the original vector but a different magnitude.
+
+Implement the scalar multiplication by checking if `other` is either an `int` or a `float`. If it is, return a new instance of the current class that has each component of the starting vector multiplied by `other`. This will be the vector resulting from the scalar multiplication.
+
+Make sure the methods can be applied to compute the scalar multiplication of vectors with any number of dimensions.
+
+# --hints--
+
+Your method should return a new instance of the current class only when the type of `other` is either `int` or `float`.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=0, y=0)
+v2 = R3Vector(x=0, y=0, z=0)
+types = ["", True, [], {}]
+assert all((v1 * i) is None for i in types)
+types = [1, 1.0]
+assert all(type(v1 * i) is type(v1) for i in types)
+assert all(type(v2 * i) is type(v2) for i in types)
+`) })
+```
+
+The vector resulting from the scalar multiplication should have each component of the starting vector multiplied by the scalar.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=1, y=1.5)
+v2 = R3Vector(x=2.2, y=3, z=-1)
+assert vars(v1 * 3) == vars(R2Vector(x=3, y=4.5))
+assert vars(v2 * (-2.0)) == vars(R3Vector(x=-4.4, y=-6.0, z=2.0))
+`) })
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
new file mode 100644
index 00000000000..bcf1d3d0b55
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
@@ -0,0 +1,79 @@
+---
+id: 65fc87e19930a503e5f05500
+title: Step 53
+challengeType: 20
+dashedName: step-53
+---
+
+# --description--
+
+A vector can be multiplied by another vector, too. This operation is called *dot product*, or *scalar product*.
+
+Create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+You are going to implement the dot product inside this block during the next step.
+
+# --hints--
+
+You should create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__mul__").find_ifs()[0].find_conditions()[1]
+node.is_equivalent("type(self) == type(other)") or node.is_equivalent("type(other) == type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
new file mode 100644
index 00000000000..c5edc6d9b45
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
@@ -0,0 +1,87 @@
+---
+id: 65fc899d77495504d6deeccc
+title: Step 54
+challengeType: 20
+dashedName: step-54
+---
+
+# --description--
+
+The scalar product between two vectors $\mathbf{a}$ and $\mathbf{b}$ is indicated as:
+
+\\( \mathbf{a} \cdot \mathbf{b} = a_1 \cdot b_1 + a_2 \cdot b_2 + \ldots + a_n \cdot b_n = \sum_{i=1}^{n} a_i \cdot b_i \\)
+
+Where each component of $\mathbf{a}$ is multiplied by the correspondent component of $\mathbf{b}$, and all the products are summed together, resulting in a number.
+
+Within the `elif` clause, implement the above formula to compute the result of a scalar product and return the result. Remember that your implementation must be valid for any vector, independently from the number of components, when the method is inherited.
+
+# --hints--
+
+You should implement the scalar product calculation and return the result inside the `elif` body of your `__mul__` method.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+v3 = R3Vector(x=2, y=3, z=1.5)
+v4 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1*v2 == 4.75 and v3*v4 == 7.0
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
new file mode 100644
index 00000000000..36b78391926
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
@@ -0,0 +1,78 @@
+---
+id: 65fc8e7c766ab1070213aadb
+title: Step 55
+challengeType: 20
+dashedName: step-55
+---
+
+# --description--
+
+In case `other` is not an integer, a floating point number, or another instance of the current class, no product can be computed.
+
+After the `elif` clause, return `NotImplemented`.
+
+# --hints--
+
+You should return `NotImplemented` after the `elif` clause.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__mul__").has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
new file mode 100644
index 00000000000..bf365bd4903
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
@@ -0,0 +1,82 @@
+---
+id: 65fc8fa7e7860407ab479bf0
+title: Step 56
+challengeType: 20
+dashedName: step-56
+---
+
+# --description--
+
+It's time to test the multiplication. Declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`. Then, call the `print` function and pass it the following f-string: `f'v1 * 3 = {v5}'`.
+
+# --hints--
+
+You should declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * 3")`)) })
+```
+
+You should print the f-string `f'v1 * 3 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * 3 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
new file mode 100644
index 00000000000..034109b8c53
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
@@ -0,0 +1,87 @@
+---
+id: 65fd681b20b7e45f55def415
+title: Step 57
+challengeType: 20
+dashedName: step-57
+---
+
+# --description--
+
+The scalar multiplication works fine. Now, modify the assignment of `v5` to be the dot product `v1 * v2`. Also, update the `print` call.
+
+Before doing that, feel free to experiment and multiply `v1` by an object of invalid type to see the error message printed on the console.
+
+
+# --hints--
+
+You should update the assignment of `v5` assigning it the scalar product `v1 * v2`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * v2")`)) })
+```
+
+You should update your `print` call to print the f-string `f'v1 * v2 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * v2 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * 3
+print(f'v1 * 3 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
new file mode 100644
index 00000000000..f6184775ca4
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9250db0d6b8198cf29ef
+title: Step 58
+challengeType: 20
+dashedName: step-58
+---
+
+# --description--
+
+The `__eq__` method can be implemented to specify what should happen in case the comparison operator (`==`) is used to compare an object with something else.
+
+Within the `R2Vector` class, create an `__eq__` method and give it two parameters: `self` and `other`.
+
+# --hints--
+
+You should define a `__eq__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__eq__")`)) })
+```
+
+Your `__eq__` method should take two parameters: `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
new file mode 100644
index 00000000000..5d2d8cfc678
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
@@ -0,0 +1,88 @@
+---
+id: 65fd95c23beef982af29004c
+title: Step 59
+challengeType: 20
+dashedName: step-59
+---
+
+# --description--
+
+You want to compare two vectors, only when they belong to the same class. For that create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented` in that case.
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
new file mode 100644
index 00000000000..c3bea995dc8
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
@@ -0,0 +1,91 @@
+---
+id: 65fd97f3c1b4c4839bdeb8d2
+title: Step 60
+challengeType: 20
+dashedName: step-60
+---
+
+# --description--
+
+To compare two vectors, you are going to check that each component of the first vector is equal to the same component of the second vector.
+
+After the `if` statement you created in the previous step, return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+# --hints--
+
+The `__eq__` method should return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1 == v2 and not v1 == v3 and v4 == v5 and not v5 == v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
new file mode 100644
index 00000000000..a7f5d701215
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
@@ -0,0 +1,102 @@
+---
+id: 65fd9aa649f6cc84631882a9
+title: Step 61
+challengeType: 20
+dashedName: step-61
+---
+
+# --description--
+
+The `__ne__` method is called under the hood when the `!=` operator is used. Define a `__ne__` method with two parameters `self` and `other`. From your new method, return the opposite of `self == other`.
+
+# --hints--
+
+You should define a `__ne__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ne__")`)) })
+```
+
+Your `__ne__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ne__").has_args("self, other")`)) })
+```
+
+The `__ne__` method should return `False` if each attribute of the current instance is equal to the same attribute of `other` and `True` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+not v1 != v2 and v1 != v3 and not v4 != v5 and v5 != v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
new file mode 100644
index 00000000000..c151f678d86
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
@@ -0,0 +1,86 @@
+---
+id: 65fd9c6e49d7cd8513ab1005
+title: Step 62
+challengeType: 20
+dashedName: step-62
+---
+
+# --description--
+
+At the end of your code, use the equality operator to compare `v1` and `R2Vector(x=2, y=3)` and print the result.
+
+# --hints--
+
+You should print the result of comparing `v1` and `R2Vector(x=2, y=3)` using the equality operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 == R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) == v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
new file mode 100644
index 00000000000..804d4947304
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9d6203afea85931094c9
+title: Step 63
+challengeType: 20
+dashedName: step-63
+---
+
+# --description--
+
+The comparison returns `True`, since the two vectors have the same components. Now, modify the argument of the `print` call you added in the previous step to use the inequality operator.
+
+# --hints--
+
+You should modify the `print` call you added in the previous step using the inequality operator to compare `v1` and `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) != v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 == R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
new file mode 100644
index 00000000000..9255b41f2c6
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
@@ -0,0 +1,97 @@
+---
+id: 65fd9e2c56ff19862dfb8cbb
+title: Step 64
+challengeType: 20
+dashedName: step-64
+---
+
+# --description--
+
+The `__lt__` method is called under the hood when the `<` operator is used to compare an object with something else.
+
+Add an empty `__lt__` method and give it two parameters: `self`, `other`.
+
+# --hints--
+
+You should define a `__lt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__lt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
new file mode 100644
index 00000000000..ee258ff8a2a
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
@@ -0,0 +1,100 @@
+---
+id: 65fdc3c8478ee70fc7966151
+title: Step 65
+challengeType: 20
+dashedName: step-65
+---
+
+# --description--
+
+In the same way you did before for the `__eq__` method, create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
new file mode 100644
index 00000000000..390babbb01f
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
@@ -0,0 +1,91 @@
+---
+id: 65fdc496f4440e1055a2ac1b
+title: Step 66
+challengeType: 20
+dashedName: step-66
+---
+
+# --description--
+
+After the `if` statement, return the result of comparing the norm of the current instance with the norm of `other` using the less than operator.
+
+# --hints--
+
+The `__lt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the `<` operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_return("self.norm() < other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
new file mode 100644
index 00000000000..7193db8cba2
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
@@ -0,0 +1,122 @@
+---
+id: 6601918b44a11b4a8c986c6a
+title: Step 67
+challengeType: 20
+dashedName: step-67
+---
+
+# --description--
+
+The `__gt__` method is called under the hood when the `>` operator is used to compare an object with something else.
+
+After the `__lt__` method, in the same way you did for `__lt__`, implement the `__gt__` method. Pay attention to use the appropriate operator.
+
+# --hints--
+
+You should define a `__gt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__gt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_args("self, other")`)) })
+```
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+The `__gt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the greater than operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_return("self.norm() > other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
new file mode 100644
index 00000000000..fd051c7fca6
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
@@ -0,0 +1,111 @@
+---
+id: 66019258a7c71d4ae50da42e
+title: Step 68
+challengeType: 20
+dashedName: step-68
+---
+
+# --description--
+
+There are still two possible comparisons to implement. The `__le__` method is called when the `<=` operator is used to compare two objects.
+
+Define a `__le__` method with `self` and `other` as the parameters and make it return the opposite of `self > other`.
+
+# --hints--
+
+You should define a `__le__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__le__")`)) })
+```
+
+Your `__le__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_args("self, other")`)) })
+```
+
+Your `__le__` method return the opposite of `self > other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_return("not self > other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
new file mode 100644
index 00000000000..542035862a5
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
@@ -0,0 +1,116 @@
+---
+id: 66019319edb1cb4b57d3a793
+title: Step 69
+challengeType: 20
+dashedName: step-69
+---
+
+# --description--
+
+The last method you need is `__ge__`, which is called when the `>=` is used to compare two objects.
+
+Define a `__ge__` method with `self` and `other` as the parameters and make it return the opposite of `self < other`.
+
+# --hints--
+
+You should define a `__ge__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ge__")`)) })
+```
+
+Your `__ge__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_args("self, other")`)) })
+```
+
+Your `__ge__` method should return the opposite of `self < other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_return("not self < other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
new file mode 100644
index 00000000000..fe9c0cfa362
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
@@ -0,0 +1,104 @@
+---
+id: 660193a2a71faa4bd8f10970
+title: Step 70
+challengeType: 20
+dashedName: step-70
+---
+
+# --description--
+
+Feel free to play around with the new comparison operations you implemented. Then, remove your last `print` call.
+
+
+# --hints--
+
+You should not have `print(v1 != R2Vector(x=2, y=3))` in your code.
+
+```js
+({test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
new file mode 100644
index 00000000000..2157c6b8a3b
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
@@ -0,0 +1,111 @@
+---
+id: 66019977710caa516276c0a8
+title: Step 71
+challengeType: 20
+dashedName: step-71
+---
+
+# --description--
+
+The *cross product*, or *vector product*, is defined between 3-dimensional vectors and results in a third vector perpendicular to both of them.
+
+The `R3Vector` class inherits from `R2Vector`, meaning it has access to all the methods and properties defined in `R2Vector`. A child class can implement additional features. You already saw a way to change the implementation of a method. Now, you are going to give the child class `R3Vector` a new method instead.
+
+Within the `R3Vector` class, define a `cross` method and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `cross` method within the `R3Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").has_function("cross")`)) })
+```
+
+Your `cross` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
new file mode 100644
index 00000000000..b7948eb83c6
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
@@ -0,0 +1,114 @@
+---
+id: 6601a7eb860fb8546516674d
+title: Step 72
+challengeType: 20
+dashedName: step-72
+---
+
+# --description--
+
+Create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
new file mode 100644
index 00000000000..7a7cb7ef03c
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
@@ -0,0 +1,105 @@
+---
+id: 6601a88a6e2ccc550d7d7208
+title: Step 73
+challengeType: 20
+dashedName: step-73
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_variable("kwargs").is_equivalent("kwargs = {}")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
new file mode 100644
index 00000000000..c9e2224dad3
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
@@ -0,0 +1,116 @@
+---
+id: 6601a8fb2e993b55912f9e9f
+title: Step 74
+challengeType: 20
+dashedName: step-74
+---
+
+# --description--
+
+The dot product between two 3D vectors \\( \mathbf{a} \\) and \\( \mathbf{b} \\) can be computed as it follows:
+
+\\[ \mathbf{a} \times \mathbf{b} = \begin{pmatrix} a_yb_z - a_zb_y \\\ a_zb_x - a_xb_z \\\ a_xb_y - a_yb_x \end{pmatrix} \\]
+
+Where the resulting vector is represented as a column vector.
+
+Implement the formula above to compute the dot product between two 3-dimensional vectors and return the resulting vector from the `cross()` method.
+
+# --hints--
+
+The `cross()` method should return a new `R3Vector` instance resulting from the dot product computation.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+v1.cross(v2) == R3Vector(x=4.75, y=-3.5, z=1.0) and v2.cross(v1) == R3Vector(x=-4.75, y=3.5, z=-1.0) and v1.cross(v1) == R3Vector(x=0, y=0, z=0)
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
new file mode 100644
index 00000000000..c1435330d56
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
@@ -0,0 +1,119 @@
+---
+id: 6601ab2809898f57591f2f7f
+title: Step 75
+challengeType: 20
+dashedName: step-75
+---
+
+# --description--
+
+Now, modify the assignments of `v1` and `v2`. Turn them into `R3Vector` instances and pass `z=1` and `z=2` to `v1` and `v2`, respectively.
+
+# --hints--
+
+You should modify the assignment of `v1` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R3Vector(x=2, y=3, z=1)")`)) })
+```
+
+You should modify the assignment of `v2` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=0.5, y=1.25, z=2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+--fcc-editable-region--
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
new file mode 100644
index 00000000000..6904f99b5e1
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
@@ -0,0 +1,113 @@
+---
+id: 6601ac48a2ee6b59e6a5060d
+title: Step 76
+challengeType: 20
+dashedName: step-76
+---
+
+# --description--
+
+Call `cross()` on `v1` and pass `v2` as the argument. Assign this call to a new variable `v6`.
+
+# --hints--
+
+You should declare a variable named `v6` and assign it a call to the `cross()` method on `v1` passing it `v2` as the `argument`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v6").is_equivalent("v6 = v1.cross(v2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
new file mode 100644
index 00000000000..47d13a7bd4d
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
@@ -0,0 +1,210 @@
+---
+id: 6601ad0fe415985a5c83f3cc
+title: Step 77
+challengeType: 20
+dashedName: step-77
+---
+
+# --description--
+
+As a final step, call the `print` function and pass it the f-string `f'v1 x v2 = {v6}'` to see the output of the dot product.
+
+With that, you have completed the vector space project. Well done!
+
+# --hints--
+
+You should print `f'v1 x v2 = {v6}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 x v2 = {v6}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+print(f'v1 x v2 = {v6}')
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
new file mode 100644
index 00000000000..d25b1a4c723
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
@@ -0,0 +1,53 @@
+---
+id: 6659875502b6d7765498f324
+title: Step 26
+challengeType: 20
+dashedName: step-26
+---
+
+# --description--
+
+Use f-strings to modify your `print` calls so that they result in the output `v1 = (2, 3)` and `v2 = (2, 2, 3)`, respectively.
+
+# --hints--
+
+You should use an f-string to interpolate `v1` and generate the output `v1 = (2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}')")`)) })
+```
+
+You should use an f-string to interpolate `v2` and generate the output `v2 = (2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
new file mode 100644
index 00000000000..bc5ffa5f75d
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
@@ -0,0 +1,51 @@
+---
+id: 66680ddfd0f8c76782923cb0
+title: Step 22
+challengeType: 20
+dashedName: step-22
+---
+
+# --description--
+
+The `norm()` method is returning the correct values, but there's still something you can improve: readability.
+
+The `vars()` built-in function takes an object as its argument and returns the `__dict__` attribute of that object.
+
+Instead of directly accessing the `__dict__` attribute of `self`, modify the `norm` method to use the `vars()` function.
+
+# --hints--
+
+You should modify your `norm` method to use `vars(self)` instead of `self.__dict__`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in vars(self).values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
new file mode 100644
index 00000000000..e0f1c196265
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
@@ -0,0 +1,61 @@
+---
+id: 66682150151af29efec9727d
+title: Step 33
+challengeType: 20
+dashedName: step-33
+---
+
+# --description--
+
+The `__getattribute__` method is called under the hood any time you try to access an instance attribute. If the attribute is not found at the instance level, the method will search for it at the class level, and eventually in parent classes.
+
+Inside your class, define a `__getattribute__` method with two parameters, `self` and `attr`, and make it return the string `'calling __getattribute__'`. You'll override momentarily the default implementation just to see how the attribute access works.
+
+# --hints--
+
+You should define a method named `__getattribute__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_args("self, attr")`)) })
+```
+
+Your `__getattribute__` method should return the string `'calling __getattribute__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_return("'calling __getattribute__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
new file mode 100644
index 00000000000..948a541cb76
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
@@ -0,0 +1,61 @@
+---
+id: 666826f258fda1ab3396a509
+title: Step 34
+challengeType: 20
+dashedName: step-34
+---
+
+# --description--
+
+Now, print the result of accessing the `x` attribute of `v1` both with the dot operator and the `getattr()` built-in function.
+
+You will see that `__getattribute__` is called in both cases.
+
+# --hints--
+
+You should print the `x` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.x)") and n.has_call("print(getattr(v1, 'x'))")) or n.has_call("print(v1.x, getattr(v1, 'x'))") or n.has_call("print(getattr(v1, 'x'), v1.x)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
new file mode 100644
index 00000000000..8c3a650010b
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
@@ -0,0 +1,69 @@
+---
+id: 666827a6fd0dbaafe8330ea6
+title: Step 35
+challengeType: 20
+dashedName: step-35
+---
+
+# --description--
+
+`__getattr__` is another special method that plays a role in accessing attributes.
+
+The default implementation of `__getattribute__` is to raise an `AttributeError` when the requested attribute is not an instance attribute or it is not present in the class tree.
+
+In that case, `__getattr__` is called if defined by the class. You can consider it as a sort of fallback when the usual attribute accessing procedure fails.
+
+Turn the `__getattribute__` method into `__getattr__` and modify the string returned by the method into `'calling __getattr__'`.
+
+# --hints--
+
+You should define a method named `__getattr__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_args("self, attr")`)) })
+```
+
+Your `__getattr__` method should return the string `'calling __getattr__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_return("'calling __getattr__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+print(v1.x)
+print(getattr(v1, 'x'))
+
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
new file mode 100644
index 00000000000..598c9822428
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
@@ -0,0 +1,62 @@
+---
+id: 666832e427d70bc5219dc62a
+title: Step 36
+challengeType: 20
+dashedName: step-36
+---
+
+# --description--
+
+As you can see from the output, although you defined `__getattr__` in your class, this method is not called yet. This happens because the default attribute access occurs through `__getattribute__`. Therefore, you can see the attribute value printed on the terminal.
+
+Now modify the last two lines of code to access the `z` attribute of `v1` in both your `print()` calls. This time, you are going to access an attribute that `v1` does not have. As a result, `__getattribute__` will raise an error and `__getattr__` will be called.
+
+# --hints--
+
+You should modify your code to print the `z` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.z)") and n.has_call("print(getattr(v1, 'z'))")) or n.has_call("print(v1.z, getattr(v1, 'z'))") or n.has_call("print(getattr(v1, 'z'), v1.z)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+print(v1.x)
+print(getattr(v1, 'x'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
new file mode 100644
index 00000000000..3f18e7c657c
--- /dev/null
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
@@ -0,0 +1,75 @@
+---
+id: 6668374ed18b7fce10259cb3
+title: Step 37
+challengeType: 20
+dashedName: step-37
+---
+
+# --description--
+
+Now that you have an idea of how the attribute access work, remove the last two lines of your code together with the `__getattr__` method.
+
+Then, restore the `print()` calls you commented out before and delete the second argument from both of them.
+
+# --hints--
+
+You should not have a `__getattr__` method.
+
+```js
+({ test: () => assert.isFalse(runPython(`_Node(_code).find_class("R2Vector").has_function("__getattr__")`)) })
+```
+
+You should not have `print(v1.z)`and `print(getattr(v1, 'z'))` in your code.
+
+```js
+({ test: () => assert.isFalse(runPython(`
+n = _Node(_code)
+n.has_call("print(v1.z)") or n.has_call("print(getattr(v1, 'z'))")
+`)) })
+```
+
+You should restore the `print()` calls you commented out before and remove the second argument from both of them.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).has_call("print(f'v1 = {v1}')") and _Node(_code).has_call("print(f'v2 = {v2}')")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+print(v1.z)
+print(getattr(v1, 'z'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
index f84624b42de..e9870c4826a 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
@@ -1,6 +1,6 @@
---
id: 6553ed69ece88d29594748aa
-title: Step 50
+title: Step 52
challengeType: 20
dashedName: step-52
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
index bf46d6f32ca..36913664567 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
@@ -1,6 +1,6 @@
---
id: 6553efd6ada3f42aa2d75448
-title: Step 51
+title: Step 53
challengeType: 20
dashedName: step-53
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
index 2688363421c..bdc61a56deb 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
@@ -1,6 +1,6 @@
---
id: 6553f3fc92741c2bf8ded140
-title: Step 52
+title: Step 54
challengeType: 20
dashedName: step-54
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
index 16b2b7a8c78..c54923b4ea2 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
@@ -1,6 +1,6 @@
---
id: 6553f4f66099802c6ae94613
-title: Step 53
+title: Step 55
challengeType: 20
dashedName: step-55
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
index bcae9e4c2a5..92734e07289 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
@@ -1,6 +1,6 @@
---
id: 6553f6086add4b2cbb99fd78
-title: Step 54
+title: Step 56
challengeType: 20
dashedName: step-56
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
index 2f0fc79d3ff..1355edcf141 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
@@ -1,6 +1,6 @@
---
id: 6553f8c570f9982e013a8886
-title: Step 55
+title: Step 57
challengeType: 20
dashedName: step-57
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
index 51c7c51620d..5b984de7d3b 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
@@ -1,6 +1,6 @@
---
id: 655491bd5b98b813fa5bedca
-title: Step 56
+title: Step 58
challengeType: 20
dashedName: step-58
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
index 64bef622b35..b6a7f0aa9c6 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
@@ -1,6 +1,6 @@
---
id: 6554930320d70414e7b6acc6
-title: Step 57
+title: Step 59
challengeType: 20
dashedName: step-59
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
index c2b67a816d2..ab8d95e137d 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
@@ -1,6 +1,6 @@
---
id: 65549561463f0016876e852c
-title: Step 58
+title: Step 60
challengeType: 20
dashedName: step-60
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
index 5d4a37a2fe9..839352832e3 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
@@ -1,6 +1,6 @@
---
id: 65549f90cf78131c96ebcf28
-title: Step 59
+title: Step 61
challengeType: 20
dashedName: step-61
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
index 4c05b0584c4..01181c37df7 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
@@ -1,6 +1,6 @@
---
id: 6554a334a40edb1fb4eff827
-title: Step 60
+title: Step 62
challengeType: 20
dashedName: step-62
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
index 63e5be90540..921879d9acc 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
@@ -1,6 +1,6 @@
---
id: 6554a49a4f782f208abcc87e
-title: Step 61
+title: Step 63
challengeType: 20
dashedName: step-63
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
index c8c045af50c..139a3fea8db 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
@@ -1,6 +1,6 @@
---
id: 6554a57ec0a2c52106e7ee50
-title: Step 62
+title: Step 64
challengeType: 20
dashedName: step-64
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
index f8aec7c6f01..b1c21af09e5 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
@@ -1,6 +1,6 @@
---
id: 6554a88d5af937226f4a9121
-title: Step 63
+title: Step 65
challengeType: 20
dashedName: step-65
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
index 9f67d3e0905..2bff453ec4b 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
@@ -1,6 +1,6 @@
---
id: 6554ac937a49be2701af4f2f
-title: Step 64
+title: Step 66
challengeType: 20
dashedName: step-66
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
index d9b8dbfc283..4c7bb7ab462 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
@@ -1,6 +1,6 @@
---
id: 6554ad2463b8892748f8efdd
-title: Step 65
+title: Step 67
challengeType: 20
dashedName: step-67
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
index e2ed67b3ab6..1eeeb3697b1 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
@@ -1,6 +1,6 @@
---
id: 6554d0332949b133a0b35eaa
-title: Step 66
+title: Step 68
challengeType: 20
dashedName: step-68
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
index 863de41bbc0..5f093f3df2c 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
@@ -1,6 +1,6 @@
---
id: 6554d15c8acb5f34499ad789
-title: Step 67
+title: Step 69
challengeType: 20
dashedName: step-69
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
index c24fa10d6c6..65ac8f3f6c4 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
@@ -1,6 +1,6 @@
---
id: 6554d25dc5ceaa354307a77e
-title: Step 68
+title: Step 70
challengeType: 20
dashedName: step-70
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
index 076f1a41e91..2df3eb6fceb 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
@@ -1,6 +1,6 @@
---
id: 6554de295ade563a069936a1
-title: Step 69
+title: Step 71
challengeType: 20
dashedName: step-71
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
index 9793f1023c3..5e52b90279e 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
@@ -1,6 +1,6 @@
---
id: 6554dfce1683be3c0c9609a6
-title: Step 70
+title: Step 72
challengeType: 20
dashedName: step-72
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
index 9454a27cb5e..02e14d9019c 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
@@ -1,6 +1,6 @@
---
id: 6554e0adc7bb193cbfdb36d5
-title: Step 71
+title: Step 73
challengeType: 20
dashedName: step-73
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
index 182346eca82..7f91537aead 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
@@ -1,6 +1,6 @@
---
id: 6554e2ee23bfd93f2c83640f
-title: Step 72
+title: Step 74
challengeType: 20
dashedName: step-74
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
index 48ececac1ab..d5bdb7ff5d1 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
@@ -1,6 +1,6 @@
---
id: 6554e343caea913ffba7bec6
-title: Step 73
+title: Step 75
challengeType: 20
dashedName: step-75
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
index 368cf69b225..a80c318bd1d 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
@@ -1,6 +1,6 @@
---
id: 655516e410b8e30fb4fb64e8
-title: Step 74
+title: Step 76
challengeType: 20
dashedName: step-76
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
index 22de7de4fa0..82e1790a7d8 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
@@ -1,6 +1,6 @@
---
id: 65551a628bcb7e121e32d04b
-title: Step 77
+title: Step 79
challengeType: 20
dashedName: step-79
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
index 7f0ec8191b3..8603eb7e6d8 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
@@ -1,6 +1,6 @@
---
id: 6555201d9b7fc917399f9f0b
-title: Step 78
+title: Step 80
challengeType: 20
dashedName: step-80
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
index 01549558a4b..5c6c8181984 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
@@ -1,6 +1,6 @@
---
id: 655520c20cb1e6177b0641d6
-title: Step 79
+title: Step 81
challengeType: 20
dashedName: step-81
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
index cc4f4eacee1..db091c232cc 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
@@ -1,6 +1,6 @@
---
id: 655522883e66f618e03a9411
-title: Step 80
+title: Step 82
challengeType: 20
dashedName: step-82
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
index cd29fc36bb4..9588d739f44 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
@@ -1,6 +1,6 @@
---
id: 6555231eac4d9f19bd3d44b5
-title: Step 81
+title: Step 83
challengeType: 20
dashedName: step-83
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
index c02b037de64..b8c910a3aa5 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
@@ -1,6 +1,6 @@
---
id: 65552a111190e11f0963949e
-title: Step 82
+title: Step 84
challengeType: 20
dashedName: step-84
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
index eb0c5d14c63..28da95df2b0 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
@@ -1,6 +1,6 @@
---
id: 65552a9593755e1fb2f5ab50
-title: Step 83
+title: Step 85
challengeType: 20
dashedName: step-85
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
index aa1a050cf04..4fcaff7b89c 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
@@ -1,6 +1,6 @@
---
id: 65552b14e803731fe3c1e4ca
-title: Step 84
+title: Step 86
challengeType: 20
dashedName: step-86
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
index 3b6cc0579a3..f8ea2a67964 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
@@ -1,6 +1,6 @@
---
id: 65553159615a8123b190ee43
-title: Step 85
+title: Step 87
challengeType: 20
dashedName: step-87
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
index 1e3ad3dfb8a..6799724af14 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
@@ -1,6 +1,6 @@
---
id: 6555d6e12c95701172b55709
-title: Step 75
+title: Step 77
challengeType: 20
dashedName: step-77
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
index f3c3b93e0c6..97049b3b537 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
@@ -1,6 +1,6 @@
---
id: 6555d8b0b3d20b128bdadd37
-title: Step 76
+title: Step 78
challengeType: 20
dashedName: step-78
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
index 866b80d387b..d310105bfe1 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
@@ -1,6 +1,6 @@
---
id: 6555db4a7b788e15795674e5
-title: Step 87
+title: Step 89
challengeType: 20
dashedName: step-89
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
index 2cf86f2dd96..3a91139cf33 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
@@ -1,6 +1,6 @@
---
id: 6555df0c81300b175308557d
-title: Step 88
+title: Step 90
challengeType: 20
dashedName: step-90
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
index 959034b7875..bc5788b45f8 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
@@ -1,6 +1,6 @@
---
id: 6555e1bfcd374e18c6be8e58
-title: Step 89
+title: Step 91
challengeType: 20
dashedName: step-91
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
index 791d9bdbd6d..4d7848b4be9 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
@@ -1,6 +1,6 @@
---
id: 6555e3f387381a19d5e00333
-title: Step 90
+title: Step 92
challengeType: 20
dashedName: step-92
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
index 20f69b6bd24..e895a41b321 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
@@ -1,6 +1,6 @@
---
id: 6555e43e783ed31a0532b1b2
-title: Step 91
+title: Step 93
challengeType: 20
dashedName: step-93
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
index 9acf44cfdc2..f878bb6c12b 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
@@ -1,6 +1,6 @@
---
id: 6555e547c18a2b1a7b795bd8
-title: Step 93
+title: Step 95
challengeType: 20
dashedName: step-95
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
index 312d322e32f..9b3df4758a0 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
@@ -1,6 +1,6 @@
---
id: 6555e5991af57d1ae0e35f0a
-title: Step 94
+title: Step 96
challengeType: 20
dashedName: step-96
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
index 3493c823d5d..1bb2f8f1567 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
@@ -1,6 +1,6 @@
---
id: 65a450e8fb2c9d75c7378d28
-title: Step 86
+title: Step 88
challengeType: 20
dashedName: step-88
---
diff --git a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
index a15a486b7eb..29a960e8277 100644
--- a/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
+++ b/curriculum/challenges/german/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
@@ -1,6 +1,6 @@
---
id: 65a51c9e000b660122b8b29e
-title: Step 92
+title: Step 94
challengeType: 20
dashedName: step-94
---
diff --git a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md b/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
deleted file mode 100644
index 632abe728dd..00000000000
--- a/curriculum/challenges/german/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
+++ /dev/null
@@ -1,344 +0,0 @@
----
-id: 62aa1fed3d4e873366ff3131
-title: Step 150
-challengeType: 0
-dashedName: step-150
----
-
-# --description--
-
-In your `attack` function, below the `health` variable, create an `if` statement. Set the condition to call the `isMonsterHit` function.
-
-# --hints--
-
-You should add an `if` statement which calls `isMonsterHit` in the condition.
-
-```js
-assert.match(attack.toString(), /if\s*\(\s*isMonsterHit\s*\(\s*\)/)
-```
-
-# --seed--
-
-## --seed-contents--
-
-```html
-
-
-
-
-
-
+
+Within the `Vector` class, create an `__init__` method and give it three parameters, `self`, `x`, and `y`.
+
+# --hints--
+
+You should define an `__init__` method inside the `Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").has_function("__init__")`)) })
+```
+
+Your `__init__` method should take three parameters: `self`, `x`, and `y`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").find_function("__init__").has_args("self, x, y")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ pass
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
new file mode 100644
index 00000000000..62ab349a8db
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
@@ -0,0 +1,38 @@
+---
+id: 65f055b9190fc41ca35549b8
+title: Step 3
+challengeType: 20
+dashedName: step-3
+---
+
+# --description--
+
+Python offers various methods that include both a leading and trailing double underscore in their names. You may already be familiar with some, such as `__init__` and `__str__`. These methods, which follow the `__
+
+So far, you created a 2-dimensional vector. You want to be able to represent vectors with a different number of dimensions without rewriting the necessary code for each specific case. For that, you will use inheritance.
+
+Start by renaming the `Vector` class into `R2Vector` to specify that this class is going to deal with 2-dimensional vectors. Remember to modify the instantiation of `v1`, too.
+
+# --hints--
+
+You should rename the `Vector` class into `R2Vector`. Remember to modify the instantiation of `v1`, too.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+v1 = Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
new file mode 100644
index 00000000000..e26a20b0730
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
@@ -0,0 +1,70 @@
+---
+id: 65f40051d6b09a139f253e8e
+title: Step 12
+challengeType: 20
+dashedName: step-12
+---
+
+# --description--
+
+Inheritance enables you to define a class from an existing one. The new class, called child, inherits all the methods and properties of the existing class, called parent.
+
+```py
+class Tree:
+ def sprout(self):
+ print('Making new leaves!')
+
+class Oak(Tree):
+ pass
+
+Oak().sprout() # Output: Making new leaves!
+```
+
+In the example above, the child class `Oak` inherits from `Tree` and inherits the `sprout` method from the parent class `Tree`.
+
+Create a new class named `R3Vector` and follow the example above to make it inherit from the `R2Vector` class.
+
+# --hints--
+
+You should define a new class `R3Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R3Vector")
+ `))
+})
+```
+
+Your new class `R3Vector` should inherit from `R2Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").inherits_from("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
new file mode 100644
index 00000000000..c50cbefeb4a
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
@@ -0,0 +1,56 @@
+---
+id: 65f40401e6ef53173c04e27d
+title: Step 13
+challengeType: 20
+dashedName: step-13
+---
+
+# --description--
+
+Within your new class, declare an `__init__` method. Give it `self`, `x`, `y`, and `z` as the parameters.
+
+# --hints--
+
+You should define an `__init__` method inside your `R3Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").has_function("__init__")
+ `))
+})
+```
+
+Your `__init__` method should have four parameters `self`, `x`, `y`, and `z`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, x, y, z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
new file mode 100644
index 00000000000..cb7a33c0eb1
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
@@ -0,0 +1,49 @@
+---
+id: 65f407ea37ad6e181b90462e
+title: Step 14
+challengeType: 20
+dashedName: step-14
+---
+
+# --description--
+
+You could assign each `i` parameter to `self.i` as you did before. Although in this case you have few lines to repeat, one way to avoid this repetition is using the `super()` function. `super()` enables you to refer implicitly to the parent class: `super().__init__(x, y)` calls the `__init__` method of the parent class.
+
+Add a `super().__init__(x, y)` call to your `__init__` method.
+
+# --hints--
+
+You should have a `super().__init__(x, y)` call in your `__init__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_stmt("super().__init__(x, y)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
new file mode 100644
index 00000000000..caf708394fc
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
@@ -0,0 +1,47 @@
+---
+id: 65f40f8af784751c613d638a
+title: Step 15
+challengeType: 20
+dashedName: step-15
+---
+
+# --description--
+
+Now, you need to assign `z` to the `z` attribute of your `R3Vector` object.
+
+# --hints--
+
+You should assign `z` to `self.z` after the `super` call.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").is_ordered("super().__init__(x, y)", "self.z = z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
new file mode 100644
index 00000000000..68340ee6c11
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
@@ -0,0 +1,47 @@
+---
+id: 65f40fdb3579aa1ced28b2eb
+title: Step 16
+challengeType: 20
+dashedName: step-16
+---
+
+# --description--
+
+Create an `R3Vector` instance with `2`, `2`, and `3` as the values of `x`, `y`, and `z`, respectively. Assign the new instance to `v2`.
+
+# --hints--
+
+You should declare a variable `v2` and assign it `R3Vector(2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(2, 2, 3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
new file mode 100644
index 00000000000..06b727e3b29
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
@@ -0,0 +1,72 @@
+---
+id: 65f412c208c3791fee305acf
+title: Step 17
+challengeType: 20
+dashedName: step-17
+---
+
+# --description--
+
+In Python, you can enforce the use of keyword-only arguments by adding a `*` as an additional argument to the function or method signature. Modify both `__init__` methods by adding a `*` as the second parameter (after `self`). Every parameter placed after that will require the use of a keyword argument in the function/method call.
+
+This means that you need to modify the `super().__init__(x, y)` call, too. Do it by giving `x` the value `x`, and `y` the value `y`.
+
+Finally, modify the instantiation of `v1` and `v2` by using keyword arguments.
+
+# --hints--
+
+You should enforce keyword arguments by adding a `*` as the second parameter in both your `__init__` methods.
+
+```js
+({ test: () => {
+ assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__init__").has_args("self, *, x, y")`));
+ assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, *, x, y, z")`));
+} })
+```
+
+You should modify your `super.__init__(x, y)` call to use keyword arguments.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").find_body().is_equivalent("super().__init__(x=x, y=y)\\nself.z = z")`)) })
+```
+
+You should modify the assignment of `v1` to be `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R2Vector(x=2, y=3)")`)) })
+```
+
+You should modify the assignment of `v2` to be `R3Vector(x=2, y=2, z=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=2, y=2, z=3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+v2 = R3Vector(2, 2, 3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
new file mode 100644
index 00000000000..ef31cdd6194
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
@@ -0,0 +1,64 @@
+---
+id: 65f4148dea0f802040225e0c
+title: Step 18
+challengeType: 20
+dashedName: step-18
+---
+
+# --description--
+
+Remove the existing `print` calls. Then, as you did before for `v1`, print `v2` and the value returned by `v2.norm()`.
+
+# --hints--
+
+You should not have `print(v1)` and `print(v1.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1.norm())")`));
+ }
+})
+```
+
+You should print `v2` and `v2.norm()`.
+
+```js
+({
+ test: () => {
+ assert(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+print(v1.norm())
+print(v1)
+
+v2 = R3Vector(x=2, y=2, z=3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
new file mode 100644
index 00000000000..1a83f17e994
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
@@ -0,0 +1,64 @@
+---
+id: 65f4520e363e2642f8112e33
+title: Step 19
+challengeType: 20
+dashedName: step-19
+---
+
+# --description--
+
+As you can see, something is not quite right. The `norm` and `__str__` methods inherited from `R2Vector` cannot adapt to a 3-dimensional vector. Their implementation has to be more flexible.
+
+Every object in Python has a special attribute named `__dict__`, which is a dictionary that stores the object attributes.
+
+Remove the existing `print` calls. Then, print the `__dict__` attribute of your `v1` and `v2` vectors to see what they look like.
+
+# --hints--
+
+You should not have `print(v2)` and `print(v2.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+You should print the `__dict__` attribute of `v1` and `v2`.
+
+```js
+({ test: () => assert(runPython(`
+(_Node(_code).has_call("print(v1.__dict__)") and _Node(_code).has_call("print(v2.__dict__)")) or _Node(_code).has_call("print(v1.__dict__, v2.__dict__)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v2.norm())
+print(v2)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
new file mode 100644
index 00000000000..2a2c8f28376
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
@@ -0,0 +1,49 @@
+---
+id: 65f4535bbdb28d436ff3ddc9
+title: Step 20
+challengeType: 20
+dashedName: step-20
+---
+
+# --description--
+
+As you can see from the output, `__dict__` contains the values of your instance attributes. Instead of explicitly adding the squares of `self.x` and `self.y`, you are going to iterate over the values stored in `__dict__` to calculate the value of the norm.
+
+Within the `norm` method body, replace the content of the parentheses with a generator expression that elevates each value `val` in `self.__dict__.values()` to the power of `2`. Also, pass that generator expression as the argument to the `sum` function, so that all the squares are added together before calculating the square root.
+
+# --hints--
+
+You should return `sum(val**2 for val in self.__dict__.values())**0.5` from `norm()` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in self.__dict__.values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
new file mode 100644
index 00000000000..bbb82436c52
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
@@ -0,0 +1,53 @@
+---
+id: 65f870003444fb1a2ad171f2
+title: Step 21
+challengeType: 20
+dashedName: step-21
+---
+
+# --description--
+
+Modify the two `print` calls to print the norm of your vectors and verify that the `norm()` method works fine.
+
+# --hints--
+
+You should print `v1.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1.norm())")`)) })
+```
+
+You should print `v2.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v2.norm())")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
new file mode 100644
index 00000000000..22e3cab792e
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
@@ -0,0 +1,61 @@
+---
+id: 65f8709620b2ce1a62608f5a
+title: Step 23
+challengeType: 20
+dashedName: step-23
+---
+
+# --description--
+
+When you need to dynamically access some attributes starting from a string input, the built-in `getattr()` function is what you need. It takes an object as its first argument, and a string containing the attribute name as its second attribute.
+
+Start to fix the `__str__` method by replacing the string returned by `__str__()` with a generator expression that iterates through the object attributes and calls `getattr()` for each attribute `i`.
+
+# --hints--
+
+You should return a generator expression that iterates over `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_iters()[0].is_equivalent("vars(self)")`)) })
+```
+
+You should return a generator expression that uses `i` as the iteration variable.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_targets()[0].is_equivalent("i")`)) })
+```
+
+You should return a generator expression that calls `getattr(self, i)` for each item `i` in `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_expr().is_equivalent("getattr(self, i)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
new file mode 100644
index 00000000000..668bd89de56
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
@@ -0,0 +1,47 @@
+---
+id: 65f8720685ec351abef26740
+title: Step 24
+challengeType: 20
+dashedName: step-24
+---
+
+# --description--
+
+To obtain a proper string representation, call the `tuple()` constructor and pass it the generator expression you wrote in the previous step as the argument.
+
+# --hints--
+
+You should pass the expression returned by the `__str__` method to the `tuple()` constructor.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("tuple(getattr(self, i) for i in vars(self))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return (getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
new file mode 100644
index 00000000000..789f37ee6fe
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
@@ -0,0 +1,47 @@
+---
+id: 65f872a0fe6aa21b456ad4fe
+title: Step 25
+challengeType: 20
+dashedName: step-25
+---
+
+# --description--
+
+Finally, pass the `tuple()` call as the argument to the `str()` function.
+
+# --hints--
+
+You should pass the `tuple()` call you are currently returning from the `__str__` method to the `str()` function.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("str(tuple(getattr(self, i) for i in vars(self)))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return tuple(getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
new file mode 100644
index 00000000000..6a2c44baef5
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
@@ -0,0 +1,56 @@
+---
+id: 65f8749b13774b1d2e4a7fba
+title: Step 27
+challengeType: 20
+dashedName: step-27
+---
+
+# --description--
+
+While the `__str__` method returns a human-readable string representation of an object, the `__repr__` method is supposed to return the string needed to instantiate the object.
+
+Add a `__repr__` method with a `self` parameter within the `R2Vector` class.
+
+# --hints--
+
+Your `R2Vector` class should have a `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__repr__")`)) })
+```
+
+Your `__repr__` method should have a `self` parameter.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_args("self")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
new file mode 100644
index 00000000000..7f5a3e0f9c9
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
@@ -0,0 +1,74 @@
+---
+id: 65f876d17832001e8e1abb05
+title: Step 28
+challengeType: 20
+dashedName: step-28
+---
+
+# --description--
+
+Declare a variable `arg_list`. Give it the value of a list comprehension that iterates over `key` and `val` for each key-value pair in `vars(self).items()` and computes the f-string `f'{key}={val}'` at each iteration.
+
+# --hints--
+
+You should declare a variable `arg_list`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_variable("arg_list")`)) })
+```
+
+You should assign a list comprehension that iterates over `vars(self).items()` to `arg_list`.
+
+```js
+({ test: () => runPython(`
+import ast
+var = _Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list")
+assert isinstance(var.tree.value, ast.ListComp), "Expected arg_list to be a list comprehension"
+assert (actual := var.find_comp_iters()[0].is_equivalent("vars(self).items()")), f"Expected vars(self).items(), got {actual}"
+`) })
+```
+
+The list comprehension assigned to `arg_list` should use `key` and `val` to iterate over `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_targets()[0].is_equivalent("key, val")
+`)) })
+```
+
+The list comprehension assigned to `arg_list` should compute the string `f'{key}={val}'` for each key-value pair in `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_expr().is_equivalent("f'{key}={val}'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
new file mode 100644
index 00000000000..0c56316394e
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
@@ -0,0 +1,50 @@
+---
+id: 65f93acbb514857003510e79
+title: Step 29
+challengeType: 20
+dashedName: step-29
+---
+
+# --description--
+
+Declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+# --hints--
+
+You should declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("args").is_equivalent("args = ', '.join(arg_list)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
new file mode 100644
index 00000000000..e826611fa57
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
@@ -0,0 +1,52 @@
+---
+id: 65f93b67169a9c703264458a
+title: Step 30
+challengeType: 20
+dashedName: step-30
+---
+
+# --description--
+
+Since the method should return the string to instantiate the object for `R2Vector` as well as `R3Vector` when inherited, you cannot build the string specifying the class name.
+
+You can access the name of a class with `__class__.__name__`. Add a `return` statement to the `__repr__` method and return the string necessary to instantiate the object.
+
+# --hints--
+
+You should use `__class__.__name__` to build the f-string needed to instantiate a vector object and return it from the `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_return("f'{self.__class__.__name__}({args})'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
new file mode 100644
index 00000000000..13682539c2c
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
@@ -0,0 +1,57 @@
+---
+id: 65f93d4647ce2670dc6f095c
+title: Step 31
+challengeType: 20
+dashedName: step-31
+---
+
+# --description--
+
+The `__repr__` method is called under the hood by the `repr` function. Verify that `__repr__` works properly by adding `f'\nrepr = {repr(v1)}'` and `f'\nrepr = {repr(v2)}'` as the second argument to your first and second `print` calls, respectively.
+
+# --hints--
+
+You should add `f'\nrepr = {repr(v1)}'` as the second argument to your `print(f'v1 = {v1}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}', f'\\\\nrepr = {repr(v1)}')")`)) })
+```
+
+You should add `f'\nrepr = {repr(v2)}'` as the second argument to your `print(f'v2 = {v2}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}', f'\\\\nrepr = {repr(v2)}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
new file mode 100644
index 00000000000..a25da243ba9
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
@@ -0,0 +1,56 @@
+---
+id: 65f93e54a9121571dcdd3e79
+title: Step 32
+challengeType: 20
+dashedName: step-32
+---
+
+# --description--
+
+The output is correct, `repr` is giving you the string required to instantiate the objects.
+
+Now comment out both your `print` calls.
+
+# --hints--
+
+You should comment out both your `print()` calls.
+
+```js
+({ test: () => {
+ assert.match(code, /#\s*print\s*\(\s*f('|")v1 = \{\s*v1\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v1\s*\)\s*\}\2\s*\)/);
+ assert.match(code, /#\s*print\s*\(\s*f('|")v2 = \{\s*v2\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v2\s*\)\s*\}\2\s*\)/);
+} })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
new file mode 100644
index 00000000000..127f701ba31
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
@@ -0,0 +1,62 @@
+---
+id: 65f9b17a638f0d0dcce8c354
+title: Step 38
+challengeType: 20
+dashedName: step-38
+---
+
+# --description--
+
+To create a vector space, you need to define how vectors should behave in several cases. Vectors can be added, forming a new vector.
+
+The special method `__add__` can be implemented to override what happens by default when two objects are added together using the `+` operator.
+
+Right now, trying to add two instances of `R2Vector` or `R3Vector` would raise an exception. Create an empty `__add__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define an `__add__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__add__")`)) })
+```
+
+Your `__add__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
new file mode 100644
index 00000000000..f90c14fe57b
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b486989cb90ff3e77ac8
+title: Step 39
+challengeType: 20
+dashedName: step-39
+---
+
+# --description--
+
+The `other` parameter of your `__add__` method represents the operand placed at the right side of the `+` operator in an addition operation.
+
+You want to verify that the right-hand operand is not an object of the same class as the left-hand operand (i.e. `self`). Create an `if` statement that verifies that by checking the type of the operands.
+
+# --hints--
+
+You should create an `if` statement that checks if `type(self)` and `type(other)` are different.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
new file mode 100644
index 00000000000..1fa83e0f9aa
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b9710cca621244d3bde1
+title: Step 40
+challengeType: 20
+dashedName: step-40
+---
+
+# --description--
+
+In Python, `NotImplemented` is a special value used to indicate that an operation is not implemented for a specific case.
+
+`NotImplemented` does not raise an exception immediately. Instead, it signals to ask to the other operand how to perform the operation. If the request cannot be satisfied, a `TypeError` is returned by default.
+
+Because you want to be able to sum two vectors only if they belong to the same class, return `NotImplemented` from the `if` statement you created in the previous step.
+
+# --hints--
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
new file mode 100644
index 00000000000..9df77e46895
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
@@ -0,0 +1,58 @@
+---
+id: 65f9bb7c0d524612b2a88a4b
+title: Step 41
+challengeType: 20
+dashedName: step-41
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_stmt("kwargs = {}")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
new file mode 100644
index 00000000000..f5d28e43bd6
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
@@ -0,0 +1,92 @@
+---
+id: 65f9bc10a9fb1612e066e9e8
+title: Step 42
+challengeType: 20
+dashedName: step-42
+---
+
+# --description--
+
+When adding two vectors, each component of one vector is added to the same component of the other vector. For example, adding `(1, 2)` and `(2, 4)` generates a third vector `(3, 6)`, where `3` is the sum of `1` and `2` and `6` is the sum of `2` and `4`.
+
+The `kwargs` dictionary will contain the key-value pairs needed to instantiate a new vector of the same class of the two vectors added together.
+
+Turn the empty dictionary into a dictionary comprehension that iterates through `vars(self)` and for each key (`i`) creates a key-value pair, where the key is the same key of the current iteration and its value is the sum of the values of the `i` attributes of the two operands.
+
+# --hints--
+
+You should turn the empty dictionary assigned to `kwargs` into a dictionary comprehension that iterates over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_iters()[0].is_equivalent("vars(self)")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_key().is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the sum of the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i` in `vars(self)`. Use the `getattr()` function for that.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) + getattr(other, i)") or node.is_equivalent("getattr(other, i) + getattr(self, i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
new file mode 100644
index 00000000000..d1cd1755778
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
@@ -0,0 +1,70 @@
+---
+id: 65f9c2c2006feb1428ad2d4c
+title: Step 43
+challengeType: 20
+dashedName: step-43
+---
+
+# --description--
+
+You can unpack a dictionary into keyword arguments by using the `**` operator:
+
+```py
+def spam(a, b):
+ return a + b
+
+my_dict = {a: 11, b: 4}
+
+spam(**my_dict) # 15
+```
+
+Return an instance of the current class by using `__class__` and passing `**kwargs` as the argument.
+
+# --hints--
+
+You should return `self.__class__(**kwargs)` from the `__add__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
new file mode 100644
index 00000000000..689ab778fe5
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
@@ -0,0 +1,90 @@
+---
+id: 65f9cb678070ca1668898c70
+title: Step 44
+challengeType: 20
+dashedName: step-44
+---
+
+# --description--
+
+In the same way `__add__` is called under the hood when two objects are added together, the `__sub__` method is called implicitly in case of subtraction.
+
+Now, define an empty `__sub__` method and give two parameters: `self`, and `other`. Inside your new method, create an if statement to check if `self` and `other` do not belong to the same class and return `NotImplemented`, as you did previously.
+
+# --hints--
+
+You should define a `__sub__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__sub__")
+ `))
+})
+```
+
+Your `__sub__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_args("self, other")
+ `))
+})
+```
+
+You should create an `if` statement that checks if `self` and `other` does not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+ `))
+})
+```
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
new file mode 100644
index 00000000000..2d452d2413e
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
@@ -0,0 +1,89 @@
+---
+id: 65f9dd6e5a08af19c196c2df
+title: Step 45
+challengeType: 20
+dashedName: step-45
+---
+
+# --description--
+
+The vector resulting from the subtraction of one vector from another is obtained by calculating the difference of each of their components. For example, subtracting `(2, 4)` from `(7, 3)` generates a third vector `(5, -1)`, where `5` is the difference between `7` and `2` and `-1` is the difference between `3` and `4`.
+
+As you did before inside the `__add__` method, declare a `kwargs` variable after the `if` statement. Assign it a dictionary comprehension that iterates through the object attributes and creates a key-value pair for each key `i`, where the key is the same key as the current iteration and its value is the difference between the values of the `i` attributes of two operands.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it a dictionary comprehension that iterates over the object attributes.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_iters()[0]
+node.is_equivalent("vars(self)") or node.is_equivalent("self.__dict__")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over the object attributes.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_key().is_equivalent("i")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the difference between the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i`.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) - getattr(other, i)") or node.is_equivalent("self.__getattribute__(i) - other.__getattribute__(i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
new file mode 100644
index 00000000000..095bce27c7c
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
@@ -0,0 +1,65 @@
+---
+id: 65f9dfd2e75e291a38695f13
+title: Step 46
+challengeType: 20
+dashedName: step-46
+---
+
+# --description--
+
+Finally, return a new vector object. Use `__class__` and unpack `kwargs` to instantiate the new vector.
+
+# --hints--
+
+You should return a new vector using `__class__` and unpacking `kwargs` from the `__sub__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
new file mode 100644
index 00000000000..c5cb7742541
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
@@ -0,0 +1,67 @@
+---
+id: 65f9e0a578b22c1a736f3d82
+title: Step 47
+challengeType: 20
+dashedName: step-47
+---
+
+# --description--
+
+Modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+# --hints--
+
+You should modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v2 = R2Vector(x=0.5, y=1.25)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
new file mode 100644
index 00000000000..1d277671da4
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
@@ -0,0 +1,67 @@
+---
+id: 65fa8d5cf0ef3b141010f5d8
+title: Step 48
+challengeType: 20
+dashedName: step-48
+---
+
+# --description--
+
+It's time to verify that the addition and subtraction operations work as expected. Declare another variable `v3` and assign it the sum of `v1` plus `v2`.
+
+# --hints--
+
+You should declare a variable `v3` and assign it the sum of `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v3 = v1 + v2") or _Node(_code).has_stmt("v3 = v2 + v1")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
new file mode 100644
index 00000000000..87ddac5ea5f
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
@@ -0,0 +1,64 @@
+---
+id: 65fa8df56a0e2c149b4d24fe
+title: Step 49
+challengeType: 20
+dashedName: step-49
+---
+
+# --description--
+
+Next, check the new vector by printing the following f-string `f'v1 + v2 = {v3}'`.
+
+# --hints--
+
+You should print `f'v1 + v2 = {v3}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 + v2 = {v3}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
new file mode 100644
index 00000000000..e526a9cd4cc
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
@@ -0,0 +1,77 @@
+---
+id: 65fa9402d1fb5516aa42159d
+title: Step 50
+challengeType: 20
+dashedName: step-50
+---
+
+# --description--
+
+Feel free to modify `v3` so that it sums an `R2Vector` instance with an object of a different type, such as an integer or a string. You will be able to see a `TypeError` message printed on the console.
+
+Then, restore the original line and create a new variable `v4`. Assign the difference between `v1` and `v2` to your new variable and print the result following the same structure as the previous f-string.
+
+# --hints--
+
+You should declare a variable `v4` and assign it the difference between `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v4 = v1 - v2")
+ `))
+})
+```
+
+You should print `f'v1 - v2 = {v4}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 - v2 = {v4}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
new file mode 100644
index 00000000000..d2df1c3038d
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
@@ -0,0 +1,85 @@
+---
+id: 65fa9e1b6c6db919385359ec
+title: Step 51
+challengeType: 20
+dashedName: step-51
+---
+
+# --description--
+
+The special method `__mul__` can be implemented to specify what should happen when the current instance is multiplied by another object.
+
+Create an empty `__mul__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `__mul__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__mul__")
+ `))
+})
+```
+
+Your `__mul__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__mul__").has_args("self, other")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
new file mode 100644
index 00000000000..0a18b8b69d1
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
@@ -0,0 +1,94 @@
+---
+id: 65faaed8f7a9772f023ea816
+title: Step 52
+challengeType: 20
+dashedName: step-52
+---
+
+# --description--
+
+Vectors can be multiplied by a *scalar*, i.e. a number that multiplies each single component. The result of scalar multiplication is a vector with the same orientation as the original vector but a different magnitude.
+
+Implement the scalar multiplication by checking if `other` is either an `int` or a `float`. If it is, return a new instance of the current class that has each component of the starting vector multiplied by `other`. This will be the vector resulting from the scalar multiplication.
+
+Make sure the methods can be applied to compute the scalar multiplication of vectors with any number of dimensions.
+
+# --hints--
+
+Your method should return a new instance of the current class only when the type of `other` is either `int` or `float`.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=0, y=0)
+v2 = R3Vector(x=0, y=0, z=0)
+types = ["", True, [], {}]
+assert all((v1 * i) is None for i in types)
+types = [1, 1.0]
+assert all(type(v1 * i) is type(v1) for i in types)
+assert all(type(v2 * i) is type(v2) for i in types)
+`) })
+```
+
+The vector resulting from the scalar multiplication should have each component of the starting vector multiplied by the scalar.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=1, y=1.5)
+v2 = R3Vector(x=2.2, y=3, z=-1)
+assert vars(v1 * 3) == vars(R2Vector(x=3, y=4.5))
+assert vars(v2 * (-2.0)) == vars(R3Vector(x=-4.4, y=-6.0, z=2.0))
+`) })
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
new file mode 100644
index 00000000000..bcf1d3d0b55
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
@@ -0,0 +1,79 @@
+---
+id: 65fc87e19930a503e5f05500
+title: Step 53
+challengeType: 20
+dashedName: step-53
+---
+
+# --description--
+
+A vector can be multiplied by another vector, too. This operation is called *dot product*, or *scalar product*.
+
+Create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+You are going to implement the dot product inside this block during the next step.
+
+# --hints--
+
+You should create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__mul__").find_ifs()[0].find_conditions()[1]
+node.is_equivalent("type(self) == type(other)") or node.is_equivalent("type(other) == type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
new file mode 100644
index 00000000000..c5edc6d9b45
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
@@ -0,0 +1,87 @@
+---
+id: 65fc899d77495504d6deeccc
+title: Step 54
+challengeType: 20
+dashedName: step-54
+---
+
+# --description--
+
+The scalar product between two vectors $\mathbf{a}$ and $\mathbf{b}$ is indicated as:
+
+\\( \mathbf{a} \cdot \mathbf{b} = a_1 \cdot b_1 + a_2 \cdot b_2 + \ldots + a_n \cdot b_n = \sum_{i=1}^{n} a_i \cdot b_i \\)
+
+Where each component of $\mathbf{a}$ is multiplied by the correspondent component of $\mathbf{b}$, and all the products are summed together, resulting in a number.
+
+Within the `elif` clause, implement the above formula to compute the result of a scalar product and return the result. Remember that your implementation must be valid for any vector, independently from the number of components, when the method is inherited.
+
+# --hints--
+
+You should implement the scalar product calculation and return the result inside the `elif` body of your `__mul__` method.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+v3 = R3Vector(x=2, y=3, z=1.5)
+v4 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1*v2 == 4.75 and v3*v4 == 7.0
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
new file mode 100644
index 00000000000..36b78391926
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
@@ -0,0 +1,78 @@
+---
+id: 65fc8e7c766ab1070213aadb
+title: Step 55
+challengeType: 20
+dashedName: step-55
+---
+
+# --description--
+
+In case `other` is not an integer, a floating point number, or another instance of the current class, no product can be computed.
+
+After the `elif` clause, return `NotImplemented`.
+
+# --hints--
+
+You should return `NotImplemented` after the `elif` clause.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__mul__").has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
new file mode 100644
index 00000000000..bf365bd4903
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
@@ -0,0 +1,82 @@
+---
+id: 65fc8fa7e7860407ab479bf0
+title: Step 56
+challengeType: 20
+dashedName: step-56
+---
+
+# --description--
+
+It's time to test the multiplication. Declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`. Then, call the `print` function and pass it the following f-string: `f'v1 * 3 = {v5}'`.
+
+# --hints--
+
+You should declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * 3")`)) })
+```
+
+You should print the f-string `f'v1 * 3 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * 3 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
new file mode 100644
index 00000000000..034109b8c53
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
@@ -0,0 +1,87 @@
+---
+id: 65fd681b20b7e45f55def415
+title: Step 57
+challengeType: 20
+dashedName: step-57
+---
+
+# --description--
+
+The scalar multiplication works fine. Now, modify the assignment of `v5` to be the dot product `v1 * v2`. Also, update the `print` call.
+
+Before doing that, feel free to experiment and multiply `v1` by an object of invalid type to see the error message printed on the console.
+
+
+# --hints--
+
+You should update the assignment of `v5` assigning it the scalar product `v1 * v2`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * v2")`)) })
+```
+
+You should update your `print` call to print the f-string `f'v1 * v2 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * v2 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * 3
+print(f'v1 * 3 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
new file mode 100644
index 00000000000..f6184775ca4
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9250db0d6b8198cf29ef
+title: Step 58
+challengeType: 20
+dashedName: step-58
+---
+
+# --description--
+
+The `__eq__` method can be implemented to specify what should happen in case the comparison operator (`==`) is used to compare an object with something else.
+
+Within the `R2Vector` class, create an `__eq__` method and give it two parameters: `self` and `other`.
+
+# --hints--
+
+You should define a `__eq__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__eq__")`)) })
+```
+
+Your `__eq__` method should take two parameters: `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
new file mode 100644
index 00000000000..5d2d8cfc678
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
@@ -0,0 +1,88 @@
+---
+id: 65fd95c23beef982af29004c
+title: Step 59
+challengeType: 20
+dashedName: step-59
+---
+
+# --description--
+
+You want to compare two vectors, only when they belong to the same class. For that create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented` in that case.
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
new file mode 100644
index 00000000000..c3bea995dc8
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
@@ -0,0 +1,91 @@
+---
+id: 65fd97f3c1b4c4839bdeb8d2
+title: Step 60
+challengeType: 20
+dashedName: step-60
+---
+
+# --description--
+
+To compare two vectors, you are going to check that each component of the first vector is equal to the same component of the second vector.
+
+After the `if` statement you created in the previous step, return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+# --hints--
+
+The `__eq__` method should return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1 == v2 and not v1 == v3 and v4 == v5 and not v5 == v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
new file mode 100644
index 00000000000..a7f5d701215
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
@@ -0,0 +1,102 @@
+---
+id: 65fd9aa649f6cc84631882a9
+title: Step 61
+challengeType: 20
+dashedName: step-61
+---
+
+# --description--
+
+The `__ne__` method is called under the hood when the `!=` operator is used. Define a `__ne__` method with two parameters `self` and `other`. From your new method, return the opposite of `self == other`.
+
+# --hints--
+
+You should define a `__ne__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ne__")`)) })
+```
+
+Your `__ne__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ne__").has_args("self, other")`)) })
+```
+
+The `__ne__` method should return `False` if each attribute of the current instance is equal to the same attribute of `other` and `True` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+not v1 != v2 and v1 != v3 and not v4 != v5 and v5 != v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
new file mode 100644
index 00000000000..c151f678d86
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
@@ -0,0 +1,86 @@
+---
+id: 65fd9c6e49d7cd8513ab1005
+title: Step 62
+challengeType: 20
+dashedName: step-62
+---
+
+# --description--
+
+At the end of your code, use the equality operator to compare `v1` and `R2Vector(x=2, y=3)` and print the result.
+
+# --hints--
+
+You should print the result of comparing `v1` and `R2Vector(x=2, y=3)` using the equality operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 == R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) == v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
new file mode 100644
index 00000000000..804d4947304
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9d6203afea85931094c9
+title: Step 63
+challengeType: 20
+dashedName: step-63
+---
+
+# --description--
+
+The comparison returns `True`, since the two vectors have the same components. Now, modify the argument of the `print` call you added in the previous step to use the inequality operator.
+
+# --hints--
+
+You should modify the `print` call you added in the previous step using the inequality operator to compare `v1` and `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) != v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 == R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
new file mode 100644
index 00000000000..9255b41f2c6
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
@@ -0,0 +1,97 @@
+---
+id: 65fd9e2c56ff19862dfb8cbb
+title: Step 64
+challengeType: 20
+dashedName: step-64
+---
+
+# --description--
+
+The `__lt__` method is called under the hood when the `<` operator is used to compare an object with something else.
+
+Add an empty `__lt__` method and give it two parameters: `self`, `other`.
+
+# --hints--
+
+You should define a `__lt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__lt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
new file mode 100644
index 00000000000..ee258ff8a2a
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
@@ -0,0 +1,100 @@
+---
+id: 65fdc3c8478ee70fc7966151
+title: Step 65
+challengeType: 20
+dashedName: step-65
+---
+
+# --description--
+
+In the same way you did before for the `__eq__` method, create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
new file mode 100644
index 00000000000..390babbb01f
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
@@ -0,0 +1,91 @@
+---
+id: 65fdc496f4440e1055a2ac1b
+title: Step 66
+challengeType: 20
+dashedName: step-66
+---
+
+# --description--
+
+After the `if` statement, return the result of comparing the norm of the current instance with the norm of `other` using the less than operator.
+
+# --hints--
+
+The `__lt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the `<` operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_return("self.norm() < other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
new file mode 100644
index 00000000000..7193db8cba2
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
@@ -0,0 +1,122 @@
+---
+id: 6601918b44a11b4a8c986c6a
+title: Step 67
+challengeType: 20
+dashedName: step-67
+---
+
+# --description--
+
+The `__gt__` method is called under the hood when the `>` operator is used to compare an object with something else.
+
+After the `__lt__` method, in the same way you did for `__lt__`, implement the `__gt__` method. Pay attention to use the appropriate operator.
+
+# --hints--
+
+You should define a `__gt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__gt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_args("self, other")`)) })
+```
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+The `__gt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the greater than operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_return("self.norm() > other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
new file mode 100644
index 00000000000..fd051c7fca6
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
@@ -0,0 +1,111 @@
+---
+id: 66019258a7c71d4ae50da42e
+title: Step 68
+challengeType: 20
+dashedName: step-68
+---
+
+# --description--
+
+There are still two possible comparisons to implement. The `__le__` method is called when the `<=` operator is used to compare two objects.
+
+Define a `__le__` method with `self` and `other` as the parameters and make it return the opposite of `self > other`.
+
+# --hints--
+
+You should define a `__le__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__le__")`)) })
+```
+
+Your `__le__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_args("self, other")`)) })
+```
+
+Your `__le__` method return the opposite of `self > other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_return("not self > other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
new file mode 100644
index 00000000000..542035862a5
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
@@ -0,0 +1,116 @@
+---
+id: 66019319edb1cb4b57d3a793
+title: Step 69
+challengeType: 20
+dashedName: step-69
+---
+
+# --description--
+
+The last method you need is `__ge__`, which is called when the `>=` is used to compare two objects.
+
+Define a `__ge__` method with `self` and `other` as the parameters and make it return the opposite of `self < other`.
+
+# --hints--
+
+You should define a `__ge__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ge__")`)) })
+```
+
+Your `__ge__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_args("self, other")`)) })
+```
+
+Your `__ge__` method should return the opposite of `self < other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_return("not self < other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
new file mode 100644
index 00000000000..fe9c0cfa362
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
@@ -0,0 +1,104 @@
+---
+id: 660193a2a71faa4bd8f10970
+title: Step 70
+challengeType: 20
+dashedName: step-70
+---
+
+# --description--
+
+Feel free to play around with the new comparison operations you implemented. Then, remove your last `print` call.
+
+
+# --hints--
+
+You should not have `print(v1 != R2Vector(x=2, y=3))` in your code.
+
+```js
+({test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
new file mode 100644
index 00000000000..2157c6b8a3b
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
@@ -0,0 +1,111 @@
+---
+id: 66019977710caa516276c0a8
+title: Step 71
+challengeType: 20
+dashedName: step-71
+---
+
+# --description--
+
+The *cross product*, or *vector product*, is defined between 3-dimensional vectors and results in a third vector perpendicular to both of them.
+
+The `R3Vector` class inherits from `R2Vector`, meaning it has access to all the methods and properties defined in `R2Vector`. A child class can implement additional features. You already saw a way to change the implementation of a method. Now, you are going to give the child class `R3Vector` a new method instead.
+
+Within the `R3Vector` class, define a `cross` method and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `cross` method within the `R3Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").has_function("cross")`)) })
+```
+
+Your `cross` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
new file mode 100644
index 00000000000..b7948eb83c6
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
@@ -0,0 +1,114 @@
+---
+id: 6601a7eb860fb8546516674d
+title: Step 72
+challengeType: 20
+dashedName: step-72
+---
+
+# --description--
+
+Create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
new file mode 100644
index 00000000000..7a7cb7ef03c
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
@@ -0,0 +1,105 @@
+---
+id: 6601a88a6e2ccc550d7d7208
+title: Step 73
+challengeType: 20
+dashedName: step-73
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_variable("kwargs").is_equivalent("kwargs = {}")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
new file mode 100644
index 00000000000..c9e2224dad3
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
@@ -0,0 +1,116 @@
+---
+id: 6601a8fb2e993b55912f9e9f
+title: Step 74
+challengeType: 20
+dashedName: step-74
+---
+
+# --description--
+
+The dot product between two 3D vectors \\( \mathbf{a} \\) and \\( \mathbf{b} \\) can be computed as it follows:
+
+\\[ \mathbf{a} \times \mathbf{b} = \begin{pmatrix} a_yb_z - a_zb_y \\\ a_zb_x - a_xb_z \\\ a_xb_y - a_yb_x \end{pmatrix} \\]
+
+Where the resulting vector is represented as a column vector.
+
+Implement the formula above to compute the dot product between two 3-dimensional vectors and return the resulting vector from the `cross()` method.
+
+# --hints--
+
+The `cross()` method should return a new `R3Vector` instance resulting from the dot product computation.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+v1.cross(v2) == R3Vector(x=4.75, y=-3.5, z=1.0) and v2.cross(v1) == R3Vector(x=-4.75, y=3.5, z=-1.0) and v1.cross(v1) == R3Vector(x=0, y=0, z=0)
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
new file mode 100644
index 00000000000..c1435330d56
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
@@ -0,0 +1,119 @@
+---
+id: 6601ab2809898f57591f2f7f
+title: Step 75
+challengeType: 20
+dashedName: step-75
+---
+
+# --description--
+
+Now, modify the assignments of `v1` and `v2`. Turn them into `R3Vector` instances and pass `z=1` and `z=2` to `v1` and `v2`, respectively.
+
+# --hints--
+
+You should modify the assignment of `v1` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R3Vector(x=2, y=3, z=1)")`)) })
+```
+
+You should modify the assignment of `v2` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=0.5, y=1.25, z=2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+--fcc-editable-region--
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
new file mode 100644
index 00000000000..6904f99b5e1
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
@@ -0,0 +1,113 @@
+---
+id: 6601ac48a2ee6b59e6a5060d
+title: Step 76
+challengeType: 20
+dashedName: step-76
+---
+
+# --description--
+
+Call `cross()` on `v1` and pass `v2` as the argument. Assign this call to a new variable `v6`.
+
+# --hints--
+
+You should declare a variable named `v6` and assign it a call to the `cross()` method on `v1` passing it `v2` as the `argument`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v6").is_equivalent("v6 = v1.cross(v2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
new file mode 100644
index 00000000000..47d13a7bd4d
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
@@ -0,0 +1,210 @@
+---
+id: 6601ad0fe415985a5c83f3cc
+title: Step 77
+challengeType: 20
+dashedName: step-77
+---
+
+# --description--
+
+As a final step, call the `print` function and pass it the f-string `f'v1 x v2 = {v6}'` to see the output of the dot product.
+
+With that, you have completed the vector space project. Well done!
+
+# --hints--
+
+You should print `f'v1 x v2 = {v6}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 x v2 = {v6}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+print(f'v1 x v2 = {v6}')
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
new file mode 100644
index 00000000000..d25b1a4c723
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
@@ -0,0 +1,53 @@
+---
+id: 6659875502b6d7765498f324
+title: Step 26
+challengeType: 20
+dashedName: step-26
+---
+
+# --description--
+
+Use f-strings to modify your `print` calls so that they result in the output `v1 = (2, 3)` and `v2 = (2, 2, 3)`, respectively.
+
+# --hints--
+
+You should use an f-string to interpolate `v1` and generate the output `v1 = (2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}')")`)) })
+```
+
+You should use an f-string to interpolate `v2` and generate the output `v2 = (2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
new file mode 100644
index 00000000000..bc5ffa5f75d
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
@@ -0,0 +1,51 @@
+---
+id: 66680ddfd0f8c76782923cb0
+title: Step 22
+challengeType: 20
+dashedName: step-22
+---
+
+# --description--
+
+The `norm()` method is returning the correct values, but there's still something you can improve: readability.
+
+The `vars()` built-in function takes an object as its argument and returns the `__dict__` attribute of that object.
+
+Instead of directly accessing the `__dict__` attribute of `self`, modify the `norm` method to use the `vars()` function.
+
+# --hints--
+
+You should modify your `norm` method to use `vars(self)` instead of `self.__dict__`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in vars(self).values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
new file mode 100644
index 00000000000..e0f1c196265
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
@@ -0,0 +1,61 @@
+---
+id: 66682150151af29efec9727d
+title: Step 33
+challengeType: 20
+dashedName: step-33
+---
+
+# --description--
+
+The `__getattribute__` method is called under the hood any time you try to access an instance attribute. If the attribute is not found at the instance level, the method will search for it at the class level, and eventually in parent classes.
+
+Inside your class, define a `__getattribute__` method with two parameters, `self` and `attr`, and make it return the string `'calling __getattribute__'`. You'll override momentarily the default implementation just to see how the attribute access works.
+
+# --hints--
+
+You should define a method named `__getattribute__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_args("self, attr")`)) })
+```
+
+Your `__getattribute__` method should return the string `'calling __getattribute__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_return("'calling __getattribute__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
new file mode 100644
index 00000000000..948a541cb76
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
@@ -0,0 +1,61 @@
+---
+id: 666826f258fda1ab3396a509
+title: Step 34
+challengeType: 20
+dashedName: step-34
+---
+
+# --description--
+
+Now, print the result of accessing the `x` attribute of `v1` both with the dot operator and the `getattr()` built-in function.
+
+You will see that `__getattribute__` is called in both cases.
+
+# --hints--
+
+You should print the `x` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.x)") and n.has_call("print(getattr(v1, 'x'))")) or n.has_call("print(v1.x, getattr(v1, 'x'))") or n.has_call("print(getattr(v1, 'x'), v1.x)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
new file mode 100644
index 00000000000..8c3a650010b
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
@@ -0,0 +1,69 @@
+---
+id: 666827a6fd0dbaafe8330ea6
+title: Step 35
+challengeType: 20
+dashedName: step-35
+---
+
+# --description--
+
+`__getattr__` is another special method that plays a role in accessing attributes.
+
+The default implementation of `__getattribute__` is to raise an `AttributeError` when the requested attribute is not an instance attribute or it is not present in the class tree.
+
+In that case, `__getattr__` is called if defined by the class. You can consider it as a sort of fallback when the usual attribute accessing procedure fails.
+
+Turn the `__getattribute__` method into `__getattr__` and modify the string returned by the method into `'calling __getattr__'`.
+
+# --hints--
+
+You should define a method named `__getattr__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_args("self, attr")`)) })
+```
+
+Your `__getattr__` method should return the string `'calling __getattr__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_return("'calling __getattr__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+print(v1.x)
+print(getattr(v1, 'x'))
+
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
new file mode 100644
index 00000000000..598c9822428
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
@@ -0,0 +1,62 @@
+---
+id: 666832e427d70bc5219dc62a
+title: Step 36
+challengeType: 20
+dashedName: step-36
+---
+
+# --description--
+
+As you can see from the output, although you defined `__getattr__` in your class, this method is not called yet. This happens because the default attribute access occurs through `__getattribute__`. Therefore, you can see the attribute value printed on the terminal.
+
+Now modify the last two lines of code to access the `z` attribute of `v1` in both your `print()` calls. This time, you are going to access an attribute that `v1` does not have. As a result, `__getattribute__` will raise an error and `__getattr__` will be called.
+
+# --hints--
+
+You should modify your code to print the `z` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.z)") and n.has_call("print(getattr(v1, 'z'))")) or n.has_call("print(v1.z, getattr(v1, 'z'))") or n.has_call("print(getattr(v1, 'z'), v1.z)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+print(v1.x)
+print(getattr(v1, 'x'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
new file mode 100644
index 00000000000..3f18e7c657c
--- /dev/null
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
@@ -0,0 +1,75 @@
+---
+id: 6668374ed18b7fce10259cb3
+title: Step 37
+challengeType: 20
+dashedName: step-37
+---
+
+# --description--
+
+Now that you have an idea of how the attribute access work, remove the last two lines of your code together with the `__getattr__` method.
+
+Then, restore the `print()` calls you commented out before and delete the second argument from both of them.
+
+# --hints--
+
+You should not have a `__getattr__` method.
+
+```js
+({ test: () => assert.isFalse(runPython(`_Node(_code).find_class("R2Vector").has_function("__getattr__")`)) })
+```
+
+You should not have `print(v1.z)`and `print(getattr(v1, 'z'))` in your code.
+
+```js
+({ test: () => assert.isFalse(runPython(`
+n = _Node(_code)
+n.has_call("print(v1.z)") or n.has_call("print(getattr(v1, 'z'))")
+`)) })
+```
+
+You should restore the `print()` calls you commented out before and remove the second argument from both of them.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).has_call("print(f'v1 = {v1}')") and _Node(_code).has_call("print(f'v2 = {v2}')")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+print(v1.z)
+print(getattr(v1, 'z'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551eebe6cbb2e6cadf9b468.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551eebe6cbb2e6cadf9b468.md
index a880a21a027..5fa7e5c131a 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551eebe6cbb2e6cadf9b468.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551eebe6cbb2e6cadf9b468.md
@@ -1,6 +1,6 @@
---
id: 6551eebe6cbb2e6cadf9b468
-title: Step 2
+title: Passo 2
challengeType: 20
dashedName: step-2
---
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f3bfed58796ebb1268dc.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f3bfed58796ebb1268dc.md
index e55d6fbfb37..7c28d74b6b7 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f3bfed58796ebb1268dc.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f3bfed58796ebb1268dc.md
@@ -7,7 +7,7 @@ dashedName: step-5
# --description--
-Each string character can be referenced by a numerical index. The index count starts at zero. So the first character of a string has an index of `0`. For example, in the string `'Hello World'`, `'H'` is at index `0`, `'e'` is at index `1`, and so on.
+Each string character can be referenced by a numerical index. The index count starts at zero. So the first character of a string has an index of `0`. For example, in the string `'Hello World'`, `'H'` is at index `0`, `'e'` is at index `1`, and so on.
Each character of a string can be accessed by using bracket notation. You need to write the variable name followed by square brackets and add the index of the character between the brackets:
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65521203d7165c7b84b22ad4.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65521203d7165c7b84b22ad4.md
index 871e2f11a1f..ee8916cfb04 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65521203d7165c7b84b22ad4.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65521203d7165c7b84b22ad4.md
@@ -37,14 +37,14 @@ const commentless_code = __helpers.python.removeComments(code);
assert.match(commentless_code, /^for\s+i/m)
```
-You should write the `in` keyword after `for i `. Make sure to leave a space around the `in` keyword.
+You should write the `in` keyword after `for i`. Make sure to leave a space around the `in` keyword.
```js
const commentless_code = __helpers.python.removeComments(code);
assert.match(commentless_code, /^for\s+i\s+in\s+/m)
```
-You should write `text` after `for i in `. Don't forget to add the final `:`.
+You should write `text` after `for i in`. Don't forget to add the final `:`.
```js
const commentless_code = __helpers.python.removeComments(code);
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
index 5efbe910d0e..ab8d95e137d 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
@@ -7,8 +7,7 @@ dashedName: step-60
# --description--
-Since your key is shorter than the text that you will have to encrypt, you will need to repeat it to generate the whole encrypted text.
-At the beginning of your function body, declare a `key_index` variable and set it to zero.
+Since your key is shorter than the text that you will have to encrypt, you will need to repeat it to generate the whole encrypted text. At the beginning of your function body, declare a `key_index` variable and set it to zero.
# --hints--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
index b8abcbb5788..839352832e3 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
@@ -37,7 +37,7 @@ def vigenere(message, key):
for char in message.lower():
--fcc-editable-region--
-
+
if char == ' ':
encrypted_text += char
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
index b58810881c4..921879d9acc 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
@@ -7,8 +7,7 @@ dashedName: step-63
# --description--
-You will need to increase the `key_index` count for the next iteration.
-To do this, after the line you just added and in the same code block, use the addition assignment operator to increment `key_index` by one.
+You will need to increase the `key_index` count for the next iteration. To do this, after the line you just added and in the same code block, use the addition assignment operator to increment `key_index` by one.
# --hints--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
index 0bd011f3056..139a3fea8db 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
@@ -37,7 +37,7 @@ def vigenere(message, key):
if char == ' ':
encrypted_text += char
else:
-
+
key_char = key[key_index % len(key)]
key_index += 1
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
index ad2d60bc565..b1c21af09e5 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
@@ -52,7 +52,7 @@ def vigenere(message, key):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -61,7 +61,7 @@ def vigenere(message, key):
# Find the right key character to encode
key_char = key[key_index % len(key)]
key_index += 1
-
+
--fcc-editable-region--
index = alphabet.find(char)
new_index = (index + offset) % len(alphabet)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
index 7457687ccd9..2bff453ec4b 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
@@ -32,7 +32,7 @@ def vigenere(message, key):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -41,7 +41,7 @@ def vigenere(message, key):
key_char = key[key_index % len(key)]
key_index += 1
--fcc-editable-region--
-
+
offset = alphabet.index(key_char)
index = alphabet.find(char)
new_index = (index + offset) % len(alphabet)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
index 38d7810807e..4c7bb7ab462 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
@@ -62,7 +62,7 @@ def vigenere(message, key):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
index 2405723afae..1eeeb3697b1 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
@@ -43,7 +43,7 @@ def vigenere(message, key):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -57,7 +57,7 @@ def vigenere(message, key):
index = alphabet.find(char)
new_index = (index + offset) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
index c4181e5c5d0..5f093f3df2c 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
@@ -31,7 +31,7 @@ def vigenere(message, key):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -45,7 +45,7 @@ def vigenere(message, key):
index = alphabet.find(char)
new_index = (index + offset) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
index 0d2791f2f50..65ac8f3f6c4 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
@@ -45,7 +45,7 @@ def vigenere(message, key):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -59,9 +59,9 @@ def vigenere(message, key):
index = alphabet.find(char)
new_index = (index + offset) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
-
+
encryption = vigenere(text, custom_key)
print(encryption)
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
index f8a74620872..2df3eb6fceb 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
@@ -31,7 +31,7 @@ def vigenere(message, key, direction):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -47,9 +47,9 @@ def vigenere(message, key, direction):
new_index = (index + offset) % len(alphabet)
--fcc-editable-region--
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
-
+
#encryption = vigenere(text, custom_key)
#print(encryption)
```
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
index 2a57a505732..5e52b90279e 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
@@ -31,7 +31,7 @@ def vigenere(message, key, direction):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -45,9 +45,9 @@ def vigenere(message, key, direction):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
-
+
--fcc-editable-region--
#encryption = vigenere(text, custom_key)
#print(encryption)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
index 72b7af3dadc..02e14d9019c 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
@@ -45,7 +45,7 @@ def vigenere(message, key, direction):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -59,7 +59,7 @@ def vigenere(message, key, direction):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
--fcc-editable-region--
encryption = vigenere(text, custom_key, 1)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
index 4ac59ba2ee4..7f91537aead 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
@@ -31,7 +31,7 @@ def vigenere(message, key, direction):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -45,7 +45,7 @@ def vigenere(message, key, direction):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
--fcc-editable-region--
encryption = vigenere(text, custom_key, 1)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
index f4745b80538..d5bdb7ff5d1 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
@@ -39,7 +39,7 @@ def vigenere(message, key, direction):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -53,7 +53,7 @@ def vigenere(message, key, direction):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
--fcc-editable-region--
encryption = vigenere(text, custom_key, 1)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
index 14d6aad3a62..a80c318bd1d 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
@@ -38,7 +38,7 @@ def vigenere(message, key, direction):
final_message = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
final_message += char
@@ -52,9 +52,9 @@ def vigenere(message, key, direction):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
-
+
encryption = vigenere(text, custom_key, 1)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
index 9298423269b..82e1790a7d8 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
@@ -40,7 +40,7 @@ def vigenere(message, key, direction=1):
final_message = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
final_message += char
@@ -54,9 +54,9 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
-
+
encryption = vigenere(text, custom_key)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
index 2cbbb0a082a..8603eb7e6d8 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
@@ -53,9 +53,9 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
-
+
encryption = vigenere(text, custom_key)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
index 37ab3631ee0..5c6c8181984 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
@@ -48,9 +48,9 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
-
+
encryption = vigenere(text, custom_key)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
index 0fc9fdd1938..db091c232cc 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
@@ -46,9 +46,9 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
-
+
encryption = vigenere(text, custom_key)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
index b5baba46613..9588d739f44 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
@@ -68,7 +68,7 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
index dbe2439e466..b8c910a3aa5 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
@@ -51,7 +51,7 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
--fcc-editable-region--
def encrypt(message, key):
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
index b713ce9b2af..28da95df2b0 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
@@ -71,12 +71,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
--fcc-editable-region--
def encrypt(message, key):
return vigenere(message, key)
-
+
encryption = vigenere(text, custom_key)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
index afc5580a630..4fcaff7b89c 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
@@ -51,15 +51,15 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
--fcc-editable-region--
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
-
+
encryption = vigenere(text, custom_key)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
index 920a8be3ade..f8ea2a67964 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
@@ -54,15 +54,15 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
-
+
encryption = encrypt(text, custom_key)
print(encryption)
decryption = decrypt(encryption, custom_key)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
index 10b4700ca86..6799724af14 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
@@ -45,7 +45,7 @@ def vigenere(message, key, direction):
final_message = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
final_message += char
@@ -59,9 +59,9 @@ def vigenere(message, key, direction):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
-
+
encryption = vigenere(text, custom_key, 1)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
index 38da1a0f062..97049b3b537 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
@@ -31,7 +31,7 @@ def vigenere(message, key, direction=1):
final_message = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
final_message += char
@@ -45,7 +45,7 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
--fcc-editable-region--
encryption = vigenere(text, custom_key, 1)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
index 7fae4626dfc..d310105bfe1 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
@@ -13,7 +13,7 @@ Call the `print()` function and use the `+` operator to concatenate the `text` v
# --hints--
-You should call `print()` and pass `'Encrypted text: ' + text` as the arguments.
+You should call `print()` and pass `'Encrypted text: ' + text` as the arguments.
```js
const commentless_code = __helpers.python.removeComments(code);
@@ -54,12 +54,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
index 09ea7a24978..3a91139cf33 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
@@ -52,12 +52,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
index dc9a8c24fc2..bc5788b45f8 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
@@ -7,7 +7,7 @@ dashedName: step-91
# --description--
-In Python, there's a way to easily format strings. *f-strings* enable you to interpolate values in your strings.
+In Python, there's a way to easily format strings. *f-strings* enable you to interpolate values in your strings.
Interpolation means writing placeholders that will be replaced by the specified values when the program runs. For example, you can get the same result of `'Encrypted text: ' + text` with `f'Encrypted text: {text}'`. You need to put an `f` before the quotes to create the f-string and write the variables or expressions you want to interpolate between curly braces.
@@ -49,12 +49,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
index e372c7bd573..4d7848b4be9 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
@@ -45,12 +45,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
index 2cb1b183b8b..e895a41b321 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
@@ -47,12 +47,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
index 7bdde40cd59..f878bb6c12b 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
@@ -50,12 +50,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
index 0a6a778d0e1..9b3df4758a0 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
@@ -54,12 +54,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
@@ -96,12 +96,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655a2a7210094920069b117c.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655a2a7210094920069b117c.md
index d085aa7fef7..dd943084519 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655a2a7210094920069b117c.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655a2a7210094920069b117c.md
@@ -7,8 +7,7 @@ dashedName: step-40
# --description--
-Comparison operators allow you to compare two objects based on their values. You can use a comparison operator by placing it between the objects you want to compare.
-They return a *Boolean* value — namely `True` or `False` — depending on the truthfulness of the expression.
+Comparison operators allow you to compare two objects based on their values. You can use a comparison operator by placing it between the objects you want to compare. They return a *Boolean* value — namely `True` or `False` — depending on the truthfulness of the expression.
Python has the following comparison operators:
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65687d2f8c7ee27b0446cef3.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65687d2f8c7ee27b0446cef3.md
index a7d50d62d26..c56d9150cc7 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65687d2f8c7ee27b0446cef3.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65687d2f8c7ee27b0446cef3.md
@@ -27,7 +27,7 @@ Give your `for` loop a body by adding a call to `print(i)`. Remember to indent t
# --hints--
-You should add `print(i)` to your `for` loop body. Pay attention to the indentation.
+You should add `print(i)` to your `for` loop body. Pay attention to the indentation.
```js
assert.match(code, /^for\s+i\s+in\s+text:\s+print\s*\(\s*i\s*\)/m)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/656886ec4e4d9b96ded3c565.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/656886ec4e4d9b96ded3c565.md
index b1b9f3d44b8..770607aaeac 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/656886ec4e4d9b96ded3c565.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/656886ec4e4d9b96ded3c565.md
@@ -13,7 +13,7 @@ Rename your `i` variable to `char`.
# --hints--
-You should replace `i` with `char`.
+You should replace `i` with `char`.
```js
assert.match(code, /^for\s+char\s+in\s+text:\s+print\s*\(\s*char\s*\)/m)
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
index 6b039444ed9..1bb2f8f1567 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
@@ -73,12 +73,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
index f66b75cbf83..29a960e8277 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
@@ -45,12 +45,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6624e0ec0bf47017eed84b1f.md b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6624e0ec0bf47017eed84b1f.md
index 6cc15944f29..c83fce2ec8d 100644
--- a/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6624e0ec0bf47017eed84b1f.md
+++ b/curriculum/challenges/italian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6624e0ec0bf47017eed84b1f.md
@@ -17,7 +17,7 @@ You should modify your existing `alphabet.find('z')` call passing `text[0]` to t
```js
assert.match(code, /^alphabet\.find\s*\(\s*text\s*\[\s*0\s*\]\s*\)/m)
-```
+```
# --seed--
diff --git a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md b/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
deleted file mode 100644
index f5d9f951369..00000000000
--- a/curriculum/challenges/italian/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
+++ /dev/null
@@ -1,344 +0,0 @@
----
-id: 62aa1fed3d4e873366ff3131
-title: Step 150
-challengeType: 0
-dashedName: step-150
----
-
-# --description--
-
-Nella funzione `attack`, sotto la variabile `health`, crea un'istruzione `if`. Imposta la condizione in modo che chiami la funzione `isMonsterHit`.
-
-# --hints--
-
-Dovresti aggiungere un'istruzione `if` che chiama `isMonsterHit` nella condizione.
-
-```js
-assert.match(attack.toString(), /if\s*\(\s*isMonsterHit\s*\(\s*\)/)
-```
-
-# --seed--
-
-## --seed-contents--
-
-```html
-
-
-
-
-
-
+
+Within the `Vector` class, create an `__init__` method and give it three parameters, `self`, `x`, and `y`.
+
+# --hints--
+
+You should define an `__init__` method inside the `Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").has_function("__init__")`)) })
+```
+
+Your `__init__` method should take three parameters: `self`, `x`, and `y`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").find_function("__init__").has_args("self, x, y")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ pass
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
new file mode 100644
index 00000000000..62ab349a8db
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
@@ -0,0 +1,38 @@
+---
+id: 65f055b9190fc41ca35549b8
+title: Step 3
+challengeType: 20
+dashedName: step-3
+---
+
+# --description--
+
+Python offers various methods that include both a leading and trailing double underscore in their names. You may already be familiar with some, such as `__init__` and `__str__`. These methods, which follow the `__
+
+So far, you created a 2-dimensional vector. You want to be able to represent vectors with a different number of dimensions without rewriting the necessary code for each specific case. For that, you will use inheritance.
+
+Start by renaming the `Vector` class into `R2Vector` to specify that this class is going to deal with 2-dimensional vectors. Remember to modify the instantiation of `v1`, too.
+
+# --hints--
+
+You should rename the `Vector` class into `R2Vector`. Remember to modify the instantiation of `v1`, too.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+v1 = Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
new file mode 100644
index 00000000000..e26a20b0730
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
@@ -0,0 +1,70 @@
+---
+id: 65f40051d6b09a139f253e8e
+title: Step 12
+challengeType: 20
+dashedName: step-12
+---
+
+# --description--
+
+Inheritance enables you to define a class from an existing one. The new class, called child, inherits all the methods and properties of the existing class, called parent.
+
+```py
+class Tree:
+ def sprout(self):
+ print('Making new leaves!')
+
+class Oak(Tree):
+ pass
+
+Oak().sprout() # Output: Making new leaves!
+```
+
+In the example above, the child class `Oak` inherits from `Tree` and inherits the `sprout` method from the parent class `Tree`.
+
+Create a new class named `R3Vector` and follow the example above to make it inherit from the `R2Vector` class.
+
+# --hints--
+
+You should define a new class `R3Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R3Vector")
+ `))
+})
+```
+
+Your new class `R3Vector` should inherit from `R2Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").inherits_from("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
new file mode 100644
index 00000000000..c50cbefeb4a
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
@@ -0,0 +1,56 @@
+---
+id: 65f40401e6ef53173c04e27d
+title: Step 13
+challengeType: 20
+dashedName: step-13
+---
+
+# --description--
+
+Within your new class, declare an `__init__` method. Give it `self`, `x`, `y`, and `z` as the parameters.
+
+# --hints--
+
+You should define an `__init__` method inside your `R3Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").has_function("__init__")
+ `))
+})
+```
+
+Your `__init__` method should have four parameters `self`, `x`, `y`, and `z`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, x, y, z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
new file mode 100644
index 00000000000..cb7a33c0eb1
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
@@ -0,0 +1,49 @@
+---
+id: 65f407ea37ad6e181b90462e
+title: Step 14
+challengeType: 20
+dashedName: step-14
+---
+
+# --description--
+
+You could assign each `i` parameter to `self.i` as you did before. Although in this case you have few lines to repeat, one way to avoid this repetition is using the `super()` function. `super()` enables you to refer implicitly to the parent class: `super().__init__(x, y)` calls the `__init__` method of the parent class.
+
+Add a `super().__init__(x, y)` call to your `__init__` method.
+
+# --hints--
+
+You should have a `super().__init__(x, y)` call in your `__init__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_stmt("super().__init__(x, y)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
new file mode 100644
index 00000000000..caf708394fc
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
@@ -0,0 +1,47 @@
+---
+id: 65f40f8af784751c613d638a
+title: Step 15
+challengeType: 20
+dashedName: step-15
+---
+
+# --description--
+
+Now, you need to assign `z` to the `z` attribute of your `R3Vector` object.
+
+# --hints--
+
+You should assign `z` to `self.z` after the `super` call.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").is_ordered("super().__init__(x, y)", "self.z = z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
new file mode 100644
index 00000000000..68340ee6c11
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
@@ -0,0 +1,47 @@
+---
+id: 65f40fdb3579aa1ced28b2eb
+title: Step 16
+challengeType: 20
+dashedName: step-16
+---
+
+# --description--
+
+Create an `R3Vector` instance with `2`, `2`, and `3` as the values of `x`, `y`, and `z`, respectively. Assign the new instance to `v2`.
+
+# --hints--
+
+You should declare a variable `v2` and assign it `R3Vector(2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(2, 2, 3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
new file mode 100644
index 00000000000..06b727e3b29
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
@@ -0,0 +1,72 @@
+---
+id: 65f412c208c3791fee305acf
+title: Step 17
+challengeType: 20
+dashedName: step-17
+---
+
+# --description--
+
+In Python, you can enforce the use of keyword-only arguments by adding a `*` as an additional argument to the function or method signature. Modify both `__init__` methods by adding a `*` as the second parameter (after `self`). Every parameter placed after that will require the use of a keyword argument in the function/method call.
+
+This means that you need to modify the `super().__init__(x, y)` call, too. Do it by giving `x` the value `x`, and `y` the value `y`.
+
+Finally, modify the instantiation of `v1` and `v2` by using keyword arguments.
+
+# --hints--
+
+You should enforce keyword arguments by adding a `*` as the second parameter in both your `__init__` methods.
+
+```js
+({ test: () => {
+ assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__init__").has_args("self, *, x, y")`));
+ assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, *, x, y, z")`));
+} })
+```
+
+You should modify your `super.__init__(x, y)` call to use keyword arguments.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").find_body().is_equivalent("super().__init__(x=x, y=y)\\nself.z = z")`)) })
+```
+
+You should modify the assignment of `v1` to be `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R2Vector(x=2, y=3)")`)) })
+```
+
+You should modify the assignment of `v2` to be `R3Vector(x=2, y=2, z=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=2, y=2, z=3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+v2 = R3Vector(2, 2, 3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
new file mode 100644
index 00000000000..ef31cdd6194
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
@@ -0,0 +1,64 @@
+---
+id: 65f4148dea0f802040225e0c
+title: Step 18
+challengeType: 20
+dashedName: step-18
+---
+
+# --description--
+
+Remove the existing `print` calls. Then, as you did before for `v1`, print `v2` and the value returned by `v2.norm()`.
+
+# --hints--
+
+You should not have `print(v1)` and `print(v1.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1.norm())")`));
+ }
+})
+```
+
+You should print `v2` and `v2.norm()`.
+
+```js
+({
+ test: () => {
+ assert(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+print(v1.norm())
+print(v1)
+
+v2 = R3Vector(x=2, y=2, z=3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
new file mode 100644
index 00000000000..1a83f17e994
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
@@ -0,0 +1,64 @@
+---
+id: 65f4520e363e2642f8112e33
+title: Step 19
+challengeType: 20
+dashedName: step-19
+---
+
+# --description--
+
+As you can see, something is not quite right. The `norm` and `__str__` methods inherited from `R2Vector` cannot adapt to a 3-dimensional vector. Their implementation has to be more flexible.
+
+Every object in Python has a special attribute named `__dict__`, which is a dictionary that stores the object attributes.
+
+Remove the existing `print` calls. Then, print the `__dict__` attribute of your `v1` and `v2` vectors to see what they look like.
+
+# --hints--
+
+You should not have `print(v2)` and `print(v2.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+You should print the `__dict__` attribute of `v1` and `v2`.
+
+```js
+({ test: () => assert(runPython(`
+(_Node(_code).has_call("print(v1.__dict__)") and _Node(_code).has_call("print(v2.__dict__)")) or _Node(_code).has_call("print(v1.__dict__, v2.__dict__)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v2.norm())
+print(v2)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
new file mode 100644
index 00000000000..2a2c8f28376
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
@@ -0,0 +1,49 @@
+---
+id: 65f4535bbdb28d436ff3ddc9
+title: Step 20
+challengeType: 20
+dashedName: step-20
+---
+
+# --description--
+
+As you can see from the output, `__dict__` contains the values of your instance attributes. Instead of explicitly adding the squares of `self.x` and `self.y`, you are going to iterate over the values stored in `__dict__` to calculate the value of the norm.
+
+Within the `norm` method body, replace the content of the parentheses with a generator expression that elevates each value `val` in `self.__dict__.values()` to the power of `2`. Also, pass that generator expression as the argument to the `sum` function, so that all the squares are added together before calculating the square root.
+
+# --hints--
+
+You should return `sum(val**2 for val in self.__dict__.values())**0.5` from `norm()` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in self.__dict__.values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
new file mode 100644
index 00000000000..bbb82436c52
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
@@ -0,0 +1,53 @@
+---
+id: 65f870003444fb1a2ad171f2
+title: Step 21
+challengeType: 20
+dashedName: step-21
+---
+
+# --description--
+
+Modify the two `print` calls to print the norm of your vectors and verify that the `norm()` method works fine.
+
+# --hints--
+
+You should print `v1.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1.norm())")`)) })
+```
+
+You should print `v2.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v2.norm())")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
new file mode 100644
index 00000000000..22e3cab792e
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
@@ -0,0 +1,61 @@
+---
+id: 65f8709620b2ce1a62608f5a
+title: Step 23
+challengeType: 20
+dashedName: step-23
+---
+
+# --description--
+
+When you need to dynamically access some attributes starting from a string input, the built-in `getattr()` function is what you need. It takes an object as its first argument, and a string containing the attribute name as its second attribute.
+
+Start to fix the `__str__` method by replacing the string returned by `__str__()` with a generator expression that iterates through the object attributes and calls `getattr()` for each attribute `i`.
+
+# --hints--
+
+You should return a generator expression that iterates over `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_iters()[0].is_equivalent("vars(self)")`)) })
+```
+
+You should return a generator expression that uses `i` as the iteration variable.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_targets()[0].is_equivalent("i")`)) })
+```
+
+You should return a generator expression that calls `getattr(self, i)` for each item `i` in `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_expr().is_equivalent("getattr(self, i)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
new file mode 100644
index 00000000000..668bd89de56
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
@@ -0,0 +1,47 @@
+---
+id: 65f8720685ec351abef26740
+title: Step 24
+challengeType: 20
+dashedName: step-24
+---
+
+# --description--
+
+To obtain a proper string representation, call the `tuple()` constructor and pass it the generator expression you wrote in the previous step as the argument.
+
+# --hints--
+
+You should pass the expression returned by the `__str__` method to the `tuple()` constructor.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("tuple(getattr(self, i) for i in vars(self))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return (getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
new file mode 100644
index 00000000000..789f37ee6fe
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
@@ -0,0 +1,47 @@
+---
+id: 65f872a0fe6aa21b456ad4fe
+title: Step 25
+challengeType: 20
+dashedName: step-25
+---
+
+# --description--
+
+Finally, pass the `tuple()` call as the argument to the `str()` function.
+
+# --hints--
+
+You should pass the `tuple()` call you are currently returning from the `__str__` method to the `str()` function.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("str(tuple(getattr(self, i) for i in vars(self)))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return tuple(getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
new file mode 100644
index 00000000000..6a2c44baef5
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
@@ -0,0 +1,56 @@
+---
+id: 65f8749b13774b1d2e4a7fba
+title: Step 27
+challengeType: 20
+dashedName: step-27
+---
+
+# --description--
+
+While the `__str__` method returns a human-readable string representation of an object, the `__repr__` method is supposed to return the string needed to instantiate the object.
+
+Add a `__repr__` method with a `self` parameter within the `R2Vector` class.
+
+# --hints--
+
+Your `R2Vector` class should have a `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__repr__")`)) })
+```
+
+Your `__repr__` method should have a `self` parameter.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_args("self")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
new file mode 100644
index 00000000000..7f5a3e0f9c9
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
@@ -0,0 +1,74 @@
+---
+id: 65f876d17832001e8e1abb05
+title: Step 28
+challengeType: 20
+dashedName: step-28
+---
+
+# --description--
+
+Declare a variable `arg_list`. Give it the value of a list comprehension that iterates over `key` and `val` for each key-value pair in `vars(self).items()` and computes the f-string `f'{key}={val}'` at each iteration.
+
+# --hints--
+
+You should declare a variable `arg_list`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_variable("arg_list")`)) })
+```
+
+You should assign a list comprehension that iterates over `vars(self).items()` to `arg_list`.
+
+```js
+({ test: () => runPython(`
+import ast
+var = _Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list")
+assert isinstance(var.tree.value, ast.ListComp), "Expected arg_list to be a list comprehension"
+assert (actual := var.find_comp_iters()[0].is_equivalent("vars(self).items()")), f"Expected vars(self).items(), got {actual}"
+`) })
+```
+
+The list comprehension assigned to `arg_list` should use `key` and `val` to iterate over `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_targets()[0].is_equivalent("key, val")
+`)) })
+```
+
+The list comprehension assigned to `arg_list` should compute the string `f'{key}={val}'` for each key-value pair in `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_expr().is_equivalent("f'{key}={val}'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
new file mode 100644
index 00000000000..0c56316394e
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
@@ -0,0 +1,50 @@
+---
+id: 65f93acbb514857003510e79
+title: Step 29
+challengeType: 20
+dashedName: step-29
+---
+
+# --description--
+
+Declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+# --hints--
+
+You should declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("args").is_equivalent("args = ', '.join(arg_list)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
new file mode 100644
index 00000000000..e826611fa57
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
@@ -0,0 +1,52 @@
+---
+id: 65f93b67169a9c703264458a
+title: Step 30
+challengeType: 20
+dashedName: step-30
+---
+
+# --description--
+
+Since the method should return the string to instantiate the object for `R2Vector` as well as `R3Vector` when inherited, you cannot build the string specifying the class name.
+
+You can access the name of a class with `__class__.__name__`. Add a `return` statement to the `__repr__` method and return the string necessary to instantiate the object.
+
+# --hints--
+
+You should use `__class__.__name__` to build the f-string needed to instantiate a vector object and return it from the `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_return("f'{self.__class__.__name__}({args})'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
new file mode 100644
index 00000000000..13682539c2c
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
@@ -0,0 +1,57 @@
+---
+id: 65f93d4647ce2670dc6f095c
+title: Step 31
+challengeType: 20
+dashedName: step-31
+---
+
+# --description--
+
+The `__repr__` method is called under the hood by the `repr` function. Verify that `__repr__` works properly by adding `f'\nrepr = {repr(v1)}'` and `f'\nrepr = {repr(v2)}'` as the second argument to your first and second `print` calls, respectively.
+
+# --hints--
+
+You should add `f'\nrepr = {repr(v1)}'` as the second argument to your `print(f'v1 = {v1}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}', f'\\\\nrepr = {repr(v1)}')")`)) })
+```
+
+You should add `f'\nrepr = {repr(v2)}'` as the second argument to your `print(f'v2 = {v2}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}', f'\\\\nrepr = {repr(v2)}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
new file mode 100644
index 00000000000..a25da243ba9
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
@@ -0,0 +1,56 @@
+---
+id: 65f93e54a9121571dcdd3e79
+title: Step 32
+challengeType: 20
+dashedName: step-32
+---
+
+# --description--
+
+The output is correct, `repr` is giving you the string required to instantiate the objects.
+
+Now comment out both your `print` calls.
+
+# --hints--
+
+You should comment out both your `print()` calls.
+
+```js
+({ test: () => {
+ assert.match(code, /#\s*print\s*\(\s*f('|")v1 = \{\s*v1\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v1\s*\)\s*\}\2\s*\)/);
+ assert.match(code, /#\s*print\s*\(\s*f('|")v2 = \{\s*v2\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v2\s*\)\s*\}\2\s*\)/);
+} })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
new file mode 100644
index 00000000000..127f701ba31
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
@@ -0,0 +1,62 @@
+---
+id: 65f9b17a638f0d0dcce8c354
+title: Step 38
+challengeType: 20
+dashedName: step-38
+---
+
+# --description--
+
+To create a vector space, you need to define how vectors should behave in several cases. Vectors can be added, forming a new vector.
+
+The special method `__add__` can be implemented to override what happens by default when two objects are added together using the `+` operator.
+
+Right now, trying to add two instances of `R2Vector` or `R3Vector` would raise an exception. Create an empty `__add__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define an `__add__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__add__")`)) })
+```
+
+Your `__add__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
new file mode 100644
index 00000000000..f90c14fe57b
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b486989cb90ff3e77ac8
+title: Step 39
+challengeType: 20
+dashedName: step-39
+---
+
+# --description--
+
+The `other` parameter of your `__add__` method represents the operand placed at the right side of the `+` operator in an addition operation.
+
+You want to verify that the right-hand operand is not an object of the same class as the left-hand operand (i.e. `self`). Create an `if` statement that verifies that by checking the type of the operands.
+
+# --hints--
+
+You should create an `if` statement that checks if `type(self)` and `type(other)` are different.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
new file mode 100644
index 00000000000..1fa83e0f9aa
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b9710cca621244d3bde1
+title: Step 40
+challengeType: 20
+dashedName: step-40
+---
+
+# --description--
+
+In Python, `NotImplemented` is a special value used to indicate that an operation is not implemented for a specific case.
+
+`NotImplemented` does not raise an exception immediately. Instead, it signals to ask to the other operand how to perform the operation. If the request cannot be satisfied, a `TypeError` is returned by default.
+
+Because you want to be able to sum two vectors only if they belong to the same class, return `NotImplemented` from the `if` statement you created in the previous step.
+
+# --hints--
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
new file mode 100644
index 00000000000..9df77e46895
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
@@ -0,0 +1,58 @@
+---
+id: 65f9bb7c0d524612b2a88a4b
+title: Step 41
+challengeType: 20
+dashedName: step-41
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_stmt("kwargs = {}")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
new file mode 100644
index 00000000000..f5d28e43bd6
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
@@ -0,0 +1,92 @@
+---
+id: 65f9bc10a9fb1612e066e9e8
+title: Step 42
+challengeType: 20
+dashedName: step-42
+---
+
+# --description--
+
+When adding two vectors, each component of one vector is added to the same component of the other vector. For example, adding `(1, 2)` and `(2, 4)` generates a third vector `(3, 6)`, where `3` is the sum of `1` and `2` and `6` is the sum of `2` and `4`.
+
+The `kwargs` dictionary will contain the key-value pairs needed to instantiate a new vector of the same class of the two vectors added together.
+
+Turn the empty dictionary into a dictionary comprehension that iterates through `vars(self)` and for each key (`i`) creates a key-value pair, where the key is the same key of the current iteration and its value is the sum of the values of the `i` attributes of the two operands.
+
+# --hints--
+
+You should turn the empty dictionary assigned to `kwargs` into a dictionary comprehension that iterates over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_iters()[0].is_equivalent("vars(self)")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_key().is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the sum of the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i` in `vars(self)`. Use the `getattr()` function for that.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) + getattr(other, i)") or node.is_equivalent("getattr(other, i) + getattr(self, i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
new file mode 100644
index 00000000000..d1cd1755778
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
@@ -0,0 +1,70 @@
+---
+id: 65f9c2c2006feb1428ad2d4c
+title: Step 43
+challengeType: 20
+dashedName: step-43
+---
+
+# --description--
+
+You can unpack a dictionary into keyword arguments by using the `**` operator:
+
+```py
+def spam(a, b):
+ return a + b
+
+my_dict = {a: 11, b: 4}
+
+spam(**my_dict) # 15
+```
+
+Return an instance of the current class by using `__class__` and passing `**kwargs` as the argument.
+
+# --hints--
+
+You should return `self.__class__(**kwargs)` from the `__add__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
new file mode 100644
index 00000000000..689ab778fe5
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
@@ -0,0 +1,90 @@
+---
+id: 65f9cb678070ca1668898c70
+title: Step 44
+challengeType: 20
+dashedName: step-44
+---
+
+# --description--
+
+In the same way `__add__` is called under the hood when two objects are added together, the `__sub__` method is called implicitly in case of subtraction.
+
+Now, define an empty `__sub__` method and give two parameters: `self`, and `other`. Inside your new method, create an if statement to check if `self` and `other` do not belong to the same class and return `NotImplemented`, as you did previously.
+
+# --hints--
+
+You should define a `__sub__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__sub__")
+ `))
+})
+```
+
+Your `__sub__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_args("self, other")
+ `))
+})
+```
+
+You should create an `if` statement that checks if `self` and `other` does not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+ `))
+})
+```
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
new file mode 100644
index 00000000000..2d452d2413e
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
@@ -0,0 +1,89 @@
+---
+id: 65f9dd6e5a08af19c196c2df
+title: Step 45
+challengeType: 20
+dashedName: step-45
+---
+
+# --description--
+
+The vector resulting from the subtraction of one vector from another is obtained by calculating the difference of each of their components. For example, subtracting `(2, 4)` from `(7, 3)` generates a third vector `(5, -1)`, where `5` is the difference between `7` and `2` and `-1` is the difference between `3` and `4`.
+
+As you did before inside the `__add__` method, declare a `kwargs` variable after the `if` statement. Assign it a dictionary comprehension that iterates through the object attributes and creates a key-value pair for each key `i`, where the key is the same key as the current iteration and its value is the difference between the values of the `i` attributes of two operands.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it a dictionary comprehension that iterates over the object attributes.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_iters()[0]
+node.is_equivalent("vars(self)") or node.is_equivalent("self.__dict__")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over the object attributes.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_key().is_equivalent("i")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the difference between the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i`.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) - getattr(other, i)") or node.is_equivalent("self.__getattribute__(i) - other.__getattribute__(i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
new file mode 100644
index 00000000000..095bce27c7c
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
@@ -0,0 +1,65 @@
+---
+id: 65f9dfd2e75e291a38695f13
+title: Step 46
+challengeType: 20
+dashedName: step-46
+---
+
+# --description--
+
+Finally, return a new vector object. Use `__class__` and unpack `kwargs` to instantiate the new vector.
+
+# --hints--
+
+You should return a new vector using `__class__` and unpacking `kwargs` from the `__sub__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
new file mode 100644
index 00000000000..c5cb7742541
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
@@ -0,0 +1,67 @@
+---
+id: 65f9e0a578b22c1a736f3d82
+title: Step 47
+challengeType: 20
+dashedName: step-47
+---
+
+# --description--
+
+Modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+# --hints--
+
+You should modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v2 = R2Vector(x=0.5, y=1.25)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
new file mode 100644
index 00000000000..1d277671da4
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
@@ -0,0 +1,67 @@
+---
+id: 65fa8d5cf0ef3b141010f5d8
+title: Step 48
+challengeType: 20
+dashedName: step-48
+---
+
+# --description--
+
+It's time to verify that the addition and subtraction operations work as expected. Declare another variable `v3` and assign it the sum of `v1` plus `v2`.
+
+# --hints--
+
+You should declare a variable `v3` and assign it the sum of `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v3 = v1 + v2") or _Node(_code).has_stmt("v3 = v2 + v1")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
new file mode 100644
index 00000000000..87ddac5ea5f
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
@@ -0,0 +1,64 @@
+---
+id: 65fa8df56a0e2c149b4d24fe
+title: Step 49
+challengeType: 20
+dashedName: step-49
+---
+
+# --description--
+
+Next, check the new vector by printing the following f-string `f'v1 + v2 = {v3}'`.
+
+# --hints--
+
+You should print `f'v1 + v2 = {v3}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 + v2 = {v3}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
new file mode 100644
index 00000000000..e526a9cd4cc
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
@@ -0,0 +1,77 @@
+---
+id: 65fa9402d1fb5516aa42159d
+title: Step 50
+challengeType: 20
+dashedName: step-50
+---
+
+# --description--
+
+Feel free to modify `v3` so that it sums an `R2Vector` instance with an object of a different type, such as an integer or a string. You will be able to see a `TypeError` message printed on the console.
+
+Then, restore the original line and create a new variable `v4`. Assign the difference between `v1` and `v2` to your new variable and print the result following the same structure as the previous f-string.
+
+# --hints--
+
+You should declare a variable `v4` and assign it the difference between `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v4 = v1 - v2")
+ `))
+})
+```
+
+You should print `f'v1 - v2 = {v4}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 - v2 = {v4}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
new file mode 100644
index 00000000000..d2df1c3038d
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
@@ -0,0 +1,85 @@
+---
+id: 65fa9e1b6c6db919385359ec
+title: Step 51
+challengeType: 20
+dashedName: step-51
+---
+
+# --description--
+
+The special method `__mul__` can be implemented to specify what should happen when the current instance is multiplied by another object.
+
+Create an empty `__mul__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `__mul__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__mul__")
+ `))
+})
+```
+
+Your `__mul__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__mul__").has_args("self, other")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
new file mode 100644
index 00000000000..0a18b8b69d1
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
@@ -0,0 +1,94 @@
+---
+id: 65faaed8f7a9772f023ea816
+title: Step 52
+challengeType: 20
+dashedName: step-52
+---
+
+# --description--
+
+Vectors can be multiplied by a *scalar*, i.e. a number that multiplies each single component. The result of scalar multiplication is a vector with the same orientation as the original vector but a different magnitude.
+
+Implement the scalar multiplication by checking if `other` is either an `int` or a `float`. If it is, return a new instance of the current class that has each component of the starting vector multiplied by `other`. This will be the vector resulting from the scalar multiplication.
+
+Make sure the methods can be applied to compute the scalar multiplication of vectors with any number of dimensions.
+
+# --hints--
+
+Your method should return a new instance of the current class only when the type of `other` is either `int` or `float`.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=0, y=0)
+v2 = R3Vector(x=0, y=0, z=0)
+types = ["", True, [], {}]
+assert all((v1 * i) is None for i in types)
+types = [1, 1.0]
+assert all(type(v1 * i) is type(v1) for i in types)
+assert all(type(v2 * i) is type(v2) for i in types)
+`) })
+```
+
+The vector resulting from the scalar multiplication should have each component of the starting vector multiplied by the scalar.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=1, y=1.5)
+v2 = R3Vector(x=2.2, y=3, z=-1)
+assert vars(v1 * 3) == vars(R2Vector(x=3, y=4.5))
+assert vars(v2 * (-2.0)) == vars(R3Vector(x=-4.4, y=-6.0, z=2.0))
+`) })
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
new file mode 100644
index 00000000000..bcf1d3d0b55
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
@@ -0,0 +1,79 @@
+---
+id: 65fc87e19930a503e5f05500
+title: Step 53
+challengeType: 20
+dashedName: step-53
+---
+
+# --description--
+
+A vector can be multiplied by another vector, too. This operation is called *dot product*, or *scalar product*.
+
+Create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+You are going to implement the dot product inside this block during the next step.
+
+# --hints--
+
+You should create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__mul__").find_ifs()[0].find_conditions()[1]
+node.is_equivalent("type(self) == type(other)") or node.is_equivalent("type(other) == type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
new file mode 100644
index 00000000000..c5edc6d9b45
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
@@ -0,0 +1,87 @@
+---
+id: 65fc899d77495504d6deeccc
+title: Step 54
+challengeType: 20
+dashedName: step-54
+---
+
+# --description--
+
+The scalar product between two vectors $\mathbf{a}$ and $\mathbf{b}$ is indicated as:
+
+\\( \mathbf{a} \cdot \mathbf{b} = a_1 \cdot b_1 + a_2 \cdot b_2 + \ldots + a_n \cdot b_n = \sum_{i=1}^{n} a_i \cdot b_i \\)
+
+Where each component of $\mathbf{a}$ is multiplied by the correspondent component of $\mathbf{b}$, and all the products are summed together, resulting in a number.
+
+Within the `elif` clause, implement the above formula to compute the result of a scalar product and return the result. Remember that your implementation must be valid for any vector, independently from the number of components, when the method is inherited.
+
+# --hints--
+
+You should implement the scalar product calculation and return the result inside the `elif` body of your `__mul__` method.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+v3 = R3Vector(x=2, y=3, z=1.5)
+v4 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1*v2 == 4.75 and v3*v4 == 7.0
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
new file mode 100644
index 00000000000..36b78391926
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
@@ -0,0 +1,78 @@
+---
+id: 65fc8e7c766ab1070213aadb
+title: Step 55
+challengeType: 20
+dashedName: step-55
+---
+
+# --description--
+
+In case `other` is not an integer, a floating point number, or another instance of the current class, no product can be computed.
+
+After the `elif` clause, return `NotImplemented`.
+
+# --hints--
+
+You should return `NotImplemented` after the `elif` clause.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__mul__").has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
new file mode 100644
index 00000000000..bf365bd4903
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
@@ -0,0 +1,82 @@
+---
+id: 65fc8fa7e7860407ab479bf0
+title: Step 56
+challengeType: 20
+dashedName: step-56
+---
+
+# --description--
+
+It's time to test the multiplication. Declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`. Then, call the `print` function and pass it the following f-string: `f'v1 * 3 = {v5}'`.
+
+# --hints--
+
+You should declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * 3")`)) })
+```
+
+You should print the f-string `f'v1 * 3 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * 3 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
new file mode 100644
index 00000000000..034109b8c53
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
@@ -0,0 +1,87 @@
+---
+id: 65fd681b20b7e45f55def415
+title: Step 57
+challengeType: 20
+dashedName: step-57
+---
+
+# --description--
+
+The scalar multiplication works fine. Now, modify the assignment of `v5` to be the dot product `v1 * v2`. Also, update the `print` call.
+
+Before doing that, feel free to experiment and multiply `v1` by an object of invalid type to see the error message printed on the console.
+
+
+# --hints--
+
+You should update the assignment of `v5` assigning it the scalar product `v1 * v2`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * v2")`)) })
+```
+
+You should update your `print` call to print the f-string `f'v1 * v2 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * v2 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * 3
+print(f'v1 * 3 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
new file mode 100644
index 00000000000..f6184775ca4
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9250db0d6b8198cf29ef
+title: Step 58
+challengeType: 20
+dashedName: step-58
+---
+
+# --description--
+
+The `__eq__` method can be implemented to specify what should happen in case the comparison operator (`==`) is used to compare an object with something else.
+
+Within the `R2Vector` class, create an `__eq__` method and give it two parameters: `self` and `other`.
+
+# --hints--
+
+You should define a `__eq__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__eq__")`)) })
+```
+
+Your `__eq__` method should take two parameters: `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
new file mode 100644
index 00000000000..5d2d8cfc678
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
@@ -0,0 +1,88 @@
+---
+id: 65fd95c23beef982af29004c
+title: Step 59
+challengeType: 20
+dashedName: step-59
+---
+
+# --description--
+
+You want to compare two vectors, only when they belong to the same class. For that create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented` in that case.
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
new file mode 100644
index 00000000000..c3bea995dc8
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
@@ -0,0 +1,91 @@
+---
+id: 65fd97f3c1b4c4839bdeb8d2
+title: Step 60
+challengeType: 20
+dashedName: step-60
+---
+
+# --description--
+
+To compare two vectors, you are going to check that each component of the first vector is equal to the same component of the second vector.
+
+After the `if` statement you created in the previous step, return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+# --hints--
+
+The `__eq__` method should return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1 == v2 and not v1 == v3 and v4 == v5 and not v5 == v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
new file mode 100644
index 00000000000..a7f5d701215
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
@@ -0,0 +1,102 @@
+---
+id: 65fd9aa649f6cc84631882a9
+title: Step 61
+challengeType: 20
+dashedName: step-61
+---
+
+# --description--
+
+The `__ne__` method is called under the hood when the `!=` operator is used. Define a `__ne__` method with two parameters `self` and `other`. From your new method, return the opposite of `self == other`.
+
+# --hints--
+
+You should define a `__ne__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ne__")`)) })
+```
+
+Your `__ne__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ne__").has_args("self, other")`)) })
+```
+
+The `__ne__` method should return `False` if each attribute of the current instance is equal to the same attribute of `other` and `True` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+not v1 != v2 and v1 != v3 and not v4 != v5 and v5 != v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
new file mode 100644
index 00000000000..c151f678d86
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
@@ -0,0 +1,86 @@
+---
+id: 65fd9c6e49d7cd8513ab1005
+title: Step 62
+challengeType: 20
+dashedName: step-62
+---
+
+# --description--
+
+At the end of your code, use the equality operator to compare `v1` and `R2Vector(x=2, y=3)` and print the result.
+
+# --hints--
+
+You should print the result of comparing `v1` and `R2Vector(x=2, y=3)` using the equality operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 == R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) == v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
new file mode 100644
index 00000000000..804d4947304
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9d6203afea85931094c9
+title: Step 63
+challengeType: 20
+dashedName: step-63
+---
+
+# --description--
+
+The comparison returns `True`, since the two vectors have the same components. Now, modify the argument of the `print` call you added in the previous step to use the inequality operator.
+
+# --hints--
+
+You should modify the `print` call you added in the previous step using the inequality operator to compare `v1` and `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) != v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 == R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
new file mode 100644
index 00000000000..9255b41f2c6
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
@@ -0,0 +1,97 @@
+---
+id: 65fd9e2c56ff19862dfb8cbb
+title: Step 64
+challengeType: 20
+dashedName: step-64
+---
+
+# --description--
+
+The `__lt__` method is called under the hood when the `<` operator is used to compare an object with something else.
+
+Add an empty `__lt__` method and give it two parameters: `self`, `other`.
+
+# --hints--
+
+You should define a `__lt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__lt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
new file mode 100644
index 00000000000..ee258ff8a2a
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
@@ -0,0 +1,100 @@
+---
+id: 65fdc3c8478ee70fc7966151
+title: Step 65
+challengeType: 20
+dashedName: step-65
+---
+
+# --description--
+
+In the same way you did before for the `__eq__` method, create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
new file mode 100644
index 00000000000..390babbb01f
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
@@ -0,0 +1,91 @@
+---
+id: 65fdc496f4440e1055a2ac1b
+title: Step 66
+challengeType: 20
+dashedName: step-66
+---
+
+# --description--
+
+After the `if` statement, return the result of comparing the norm of the current instance with the norm of `other` using the less than operator.
+
+# --hints--
+
+The `__lt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the `<` operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_return("self.norm() < other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
new file mode 100644
index 00000000000..7193db8cba2
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
@@ -0,0 +1,122 @@
+---
+id: 6601918b44a11b4a8c986c6a
+title: Step 67
+challengeType: 20
+dashedName: step-67
+---
+
+# --description--
+
+The `__gt__` method is called under the hood when the `>` operator is used to compare an object with something else.
+
+After the `__lt__` method, in the same way you did for `__lt__`, implement the `__gt__` method. Pay attention to use the appropriate operator.
+
+# --hints--
+
+You should define a `__gt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__gt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_args("self, other")`)) })
+```
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+The `__gt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the greater than operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_return("self.norm() > other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
new file mode 100644
index 00000000000..fd051c7fca6
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
@@ -0,0 +1,111 @@
+---
+id: 66019258a7c71d4ae50da42e
+title: Step 68
+challengeType: 20
+dashedName: step-68
+---
+
+# --description--
+
+There are still two possible comparisons to implement. The `__le__` method is called when the `<=` operator is used to compare two objects.
+
+Define a `__le__` method with `self` and `other` as the parameters and make it return the opposite of `self > other`.
+
+# --hints--
+
+You should define a `__le__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__le__")`)) })
+```
+
+Your `__le__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_args("self, other")`)) })
+```
+
+Your `__le__` method return the opposite of `self > other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_return("not self > other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
new file mode 100644
index 00000000000..542035862a5
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
@@ -0,0 +1,116 @@
+---
+id: 66019319edb1cb4b57d3a793
+title: Step 69
+challengeType: 20
+dashedName: step-69
+---
+
+# --description--
+
+The last method you need is `__ge__`, which is called when the `>=` is used to compare two objects.
+
+Define a `__ge__` method with `self` and `other` as the parameters and make it return the opposite of `self < other`.
+
+# --hints--
+
+You should define a `__ge__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ge__")`)) })
+```
+
+Your `__ge__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_args("self, other")`)) })
+```
+
+Your `__ge__` method should return the opposite of `self < other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_return("not self < other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
new file mode 100644
index 00000000000..fe9c0cfa362
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
@@ -0,0 +1,104 @@
+---
+id: 660193a2a71faa4bd8f10970
+title: Step 70
+challengeType: 20
+dashedName: step-70
+---
+
+# --description--
+
+Feel free to play around with the new comparison operations you implemented. Then, remove your last `print` call.
+
+
+# --hints--
+
+You should not have `print(v1 != R2Vector(x=2, y=3))` in your code.
+
+```js
+({test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
new file mode 100644
index 00000000000..2157c6b8a3b
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
@@ -0,0 +1,111 @@
+---
+id: 66019977710caa516276c0a8
+title: Step 71
+challengeType: 20
+dashedName: step-71
+---
+
+# --description--
+
+The *cross product*, or *vector product*, is defined between 3-dimensional vectors and results in a third vector perpendicular to both of them.
+
+The `R3Vector` class inherits from `R2Vector`, meaning it has access to all the methods and properties defined in `R2Vector`. A child class can implement additional features. You already saw a way to change the implementation of a method. Now, you are going to give the child class `R3Vector` a new method instead.
+
+Within the `R3Vector` class, define a `cross` method and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `cross` method within the `R3Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").has_function("cross")`)) })
+```
+
+Your `cross` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
new file mode 100644
index 00000000000..b7948eb83c6
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
@@ -0,0 +1,114 @@
+---
+id: 6601a7eb860fb8546516674d
+title: Step 72
+challengeType: 20
+dashedName: step-72
+---
+
+# --description--
+
+Create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
new file mode 100644
index 00000000000..7a7cb7ef03c
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
@@ -0,0 +1,105 @@
+---
+id: 6601a88a6e2ccc550d7d7208
+title: Step 73
+challengeType: 20
+dashedName: step-73
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_variable("kwargs").is_equivalent("kwargs = {}")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
new file mode 100644
index 00000000000..c9e2224dad3
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
@@ -0,0 +1,116 @@
+---
+id: 6601a8fb2e993b55912f9e9f
+title: Step 74
+challengeType: 20
+dashedName: step-74
+---
+
+# --description--
+
+The dot product between two 3D vectors \\( \mathbf{a} \\) and \\( \mathbf{b} \\) can be computed as it follows:
+
+\\[ \mathbf{a} \times \mathbf{b} = \begin{pmatrix} a_yb_z - a_zb_y \\\ a_zb_x - a_xb_z \\\ a_xb_y - a_yb_x \end{pmatrix} \\]
+
+Where the resulting vector is represented as a column vector.
+
+Implement the formula above to compute the dot product between two 3-dimensional vectors and return the resulting vector from the `cross()` method.
+
+# --hints--
+
+The `cross()` method should return a new `R3Vector` instance resulting from the dot product computation.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+v1.cross(v2) == R3Vector(x=4.75, y=-3.5, z=1.0) and v2.cross(v1) == R3Vector(x=-4.75, y=3.5, z=-1.0) and v1.cross(v1) == R3Vector(x=0, y=0, z=0)
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
new file mode 100644
index 00000000000..c1435330d56
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
@@ -0,0 +1,119 @@
+---
+id: 6601ab2809898f57591f2f7f
+title: Step 75
+challengeType: 20
+dashedName: step-75
+---
+
+# --description--
+
+Now, modify the assignments of `v1` and `v2`. Turn them into `R3Vector` instances and pass `z=1` and `z=2` to `v1` and `v2`, respectively.
+
+# --hints--
+
+You should modify the assignment of `v1` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R3Vector(x=2, y=3, z=1)")`)) })
+```
+
+You should modify the assignment of `v2` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=0.5, y=1.25, z=2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+--fcc-editable-region--
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
new file mode 100644
index 00000000000..6904f99b5e1
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
@@ -0,0 +1,113 @@
+---
+id: 6601ac48a2ee6b59e6a5060d
+title: Step 76
+challengeType: 20
+dashedName: step-76
+---
+
+# --description--
+
+Call `cross()` on `v1` and pass `v2` as the argument. Assign this call to a new variable `v6`.
+
+# --hints--
+
+You should declare a variable named `v6` and assign it a call to the `cross()` method on `v1` passing it `v2` as the `argument`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v6").is_equivalent("v6 = v1.cross(v2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
new file mode 100644
index 00000000000..47d13a7bd4d
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
@@ -0,0 +1,210 @@
+---
+id: 6601ad0fe415985a5c83f3cc
+title: Step 77
+challengeType: 20
+dashedName: step-77
+---
+
+# --description--
+
+As a final step, call the `print` function and pass it the f-string `f'v1 x v2 = {v6}'` to see the output of the dot product.
+
+With that, you have completed the vector space project. Well done!
+
+# --hints--
+
+You should print `f'v1 x v2 = {v6}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 x v2 = {v6}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+print(f'v1 x v2 = {v6}')
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
new file mode 100644
index 00000000000..d25b1a4c723
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
@@ -0,0 +1,53 @@
+---
+id: 6659875502b6d7765498f324
+title: Step 26
+challengeType: 20
+dashedName: step-26
+---
+
+# --description--
+
+Use f-strings to modify your `print` calls so that they result in the output `v1 = (2, 3)` and `v2 = (2, 2, 3)`, respectively.
+
+# --hints--
+
+You should use an f-string to interpolate `v1` and generate the output `v1 = (2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}')")`)) })
+```
+
+You should use an f-string to interpolate `v2` and generate the output `v2 = (2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
new file mode 100644
index 00000000000..bc5ffa5f75d
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
@@ -0,0 +1,51 @@
+---
+id: 66680ddfd0f8c76782923cb0
+title: Step 22
+challengeType: 20
+dashedName: step-22
+---
+
+# --description--
+
+The `norm()` method is returning the correct values, but there's still something you can improve: readability.
+
+The `vars()` built-in function takes an object as its argument and returns the `__dict__` attribute of that object.
+
+Instead of directly accessing the `__dict__` attribute of `self`, modify the `norm` method to use the `vars()` function.
+
+# --hints--
+
+You should modify your `norm` method to use `vars(self)` instead of `self.__dict__`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in vars(self).values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
new file mode 100644
index 00000000000..e0f1c196265
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
@@ -0,0 +1,61 @@
+---
+id: 66682150151af29efec9727d
+title: Step 33
+challengeType: 20
+dashedName: step-33
+---
+
+# --description--
+
+The `__getattribute__` method is called under the hood any time you try to access an instance attribute. If the attribute is not found at the instance level, the method will search for it at the class level, and eventually in parent classes.
+
+Inside your class, define a `__getattribute__` method with two parameters, `self` and `attr`, and make it return the string `'calling __getattribute__'`. You'll override momentarily the default implementation just to see how the attribute access works.
+
+# --hints--
+
+You should define a method named `__getattribute__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_args("self, attr")`)) })
+```
+
+Your `__getattribute__` method should return the string `'calling __getattribute__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_return("'calling __getattribute__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
new file mode 100644
index 00000000000..948a541cb76
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
@@ -0,0 +1,61 @@
+---
+id: 666826f258fda1ab3396a509
+title: Step 34
+challengeType: 20
+dashedName: step-34
+---
+
+# --description--
+
+Now, print the result of accessing the `x` attribute of `v1` both with the dot operator and the `getattr()` built-in function.
+
+You will see that `__getattribute__` is called in both cases.
+
+# --hints--
+
+You should print the `x` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.x)") and n.has_call("print(getattr(v1, 'x'))")) or n.has_call("print(v1.x, getattr(v1, 'x'))") or n.has_call("print(getattr(v1, 'x'), v1.x)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
new file mode 100644
index 00000000000..8c3a650010b
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
@@ -0,0 +1,69 @@
+---
+id: 666827a6fd0dbaafe8330ea6
+title: Step 35
+challengeType: 20
+dashedName: step-35
+---
+
+# --description--
+
+`__getattr__` is another special method that plays a role in accessing attributes.
+
+The default implementation of `__getattribute__` is to raise an `AttributeError` when the requested attribute is not an instance attribute or it is not present in the class tree.
+
+In that case, `__getattr__` is called if defined by the class. You can consider it as a sort of fallback when the usual attribute accessing procedure fails.
+
+Turn the `__getattribute__` method into `__getattr__` and modify the string returned by the method into `'calling __getattr__'`.
+
+# --hints--
+
+You should define a method named `__getattr__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_args("self, attr")`)) })
+```
+
+Your `__getattr__` method should return the string `'calling __getattr__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_return("'calling __getattr__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+print(v1.x)
+print(getattr(v1, 'x'))
+
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
new file mode 100644
index 00000000000..598c9822428
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
@@ -0,0 +1,62 @@
+---
+id: 666832e427d70bc5219dc62a
+title: Step 36
+challengeType: 20
+dashedName: step-36
+---
+
+# --description--
+
+As you can see from the output, although you defined `__getattr__` in your class, this method is not called yet. This happens because the default attribute access occurs through `__getattribute__`. Therefore, you can see the attribute value printed on the terminal.
+
+Now modify the last two lines of code to access the `z` attribute of `v1` in both your `print()` calls. This time, you are going to access an attribute that `v1` does not have. As a result, `__getattribute__` will raise an error and `__getattr__` will be called.
+
+# --hints--
+
+You should modify your code to print the `z` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.z)") and n.has_call("print(getattr(v1, 'z'))")) or n.has_call("print(v1.z, getattr(v1, 'z'))") or n.has_call("print(getattr(v1, 'z'), v1.z)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+print(v1.x)
+print(getattr(v1, 'x'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
new file mode 100644
index 00000000000..3f18e7c657c
--- /dev/null
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
@@ -0,0 +1,75 @@
+---
+id: 6668374ed18b7fce10259cb3
+title: Step 37
+challengeType: 20
+dashedName: step-37
+---
+
+# --description--
+
+Now that you have an idea of how the attribute access work, remove the last two lines of your code together with the `__getattr__` method.
+
+Then, restore the `print()` calls you commented out before and delete the second argument from both of them.
+
+# --hints--
+
+You should not have a `__getattr__` method.
+
+```js
+({ test: () => assert.isFalse(runPython(`_Node(_code).find_class("R2Vector").has_function("__getattr__")`)) })
+```
+
+You should not have `print(v1.z)`and `print(getattr(v1, 'z'))` in your code.
+
+```js
+({ test: () => assert.isFalse(runPython(`
+n = _Node(_code)
+n.has_call("print(v1.z)") or n.has_call("print(getattr(v1, 'z'))")
+`)) })
+```
+
+You should restore the `print()` calls you commented out before and remove the second argument from both of them.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).has_call("print(f'v1 = {v1}')") and _Node(_code).has_call("print(f'v2 = {v2}')")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+print(v1.z)
+print(getattr(v1, 'z'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
index f84624b42de..e9870c4826a 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
@@ -1,6 +1,6 @@
---
id: 6553ed69ece88d29594748aa
-title: Step 50
+title: Step 52
challengeType: 20
dashedName: step-52
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
index bf46d6f32ca..36913664567 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
@@ -1,6 +1,6 @@
---
id: 6553efd6ada3f42aa2d75448
-title: Step 51
+title: Step 53
challengeType: 20
dashedName: step-53
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
index 2688363421c..bdc61a56deb 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
@@ -1,6 +1,6 @@
---
id: 6553f3fc92741c2bf8ded140
-title: Step 52
+title: Step 54
challengeType: 20
dashedName: step-54
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
index 16b2b7a8c78..c54923b4ea2 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
@@ -1,6 +1,6 @@
---
id: 6553f4f66099802c6ae94613
-title: Step 53
+title: Step 55
challengeType: 20
dashedName: step-55
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
index bcae9e4c2a5..92734e07289 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
@@ -1,6 +1,6 @@
---
id: 6553f6086add4b2cbb99fd78
-title: Step 54
+title: Step 56
challengeType: 20
dashedName: step-56
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
index 2f0fc79d3ff..1355edcf141 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
@@ -1,6 +1,6 @@
---
id: 6553f8c570f9982e013a8886
-title: Step 55
+title: Step 57
challengeType: 20
dashedName: step-57
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
index 51c7c51620d..5b984de7d3b 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
@@ -1,6 +1,6 @@
---
id: 655491bd5b98b813fa5bedca
-title: Step 56
+title: Step 58
challengeType: 20
dashedName: step-58
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
index 64bef622b35..b6a7f0aa9c6 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
@@ -1,6 +1,6 @@
---
id: 6554930320d70414e7b6acc6
-title: Step 57
+title: Step 59
challengeType: 20
dashedName: step-59
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
index c2b67a816d2..ab8d95e137d 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
@@ -1,6 +1,6 @@
---
id: 65549561463f0016876e852c
-title: Step 58
+title: Step 60
challengeType: 20
dashedName: step-60
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
index 5d4a37a2fe9..839352832e3 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
@@ -1,6 +1,6 @@
---
id: 65549f90cf78131c96ebcf28
-title: Step 59
+title: Step 61
challengeType: 20
dashedName: step-61
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
index 4c05b0584c4..01181c37df7 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
@@ -1,6 +1,6 @@
---
id: 6554a334a40edb1fb4eff827
-title: Step 60
+title: Step 62
challengeType: 20
dashedName: step-62
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
index 63e5be90540..921879d9acc 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
@@ -1,6 +1,6 @@
---
id: 6554a49a4f782f208abcc87e
-title: Step 61
+title: Step 63
challengeType: 20
dashedName: step-63
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
index c8c045af50c..139a3fea8db 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
@@ -1,6 +1,6 @@
---
id: 6554a57ec0a2c52106e7ee50
-title: Step 62
+title: Step 64
challengeType: 20
dashedName: step-64
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
index f8aec7c6f01..b1c21af09e5 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
@@ -1,6 +1,6 @@
---
id: 6554a88d5af937226f4a9121
-title: Step 63
+title: Step 65
challengeType: 20
dashedName: step-65
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
index 9f67d3e0905..2bff453ec4b 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
@@ -1,6 +1,6 @@
---
id: 6554ac937a49be2701af4f2f
-title: Step 64
+title: Step 66
challengeType: 20
dashedName: step-66
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
index d9b8dbfc283..4c7bb7ab462 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
@@ -1,6 +1,6 @@
---
id: 6554ad2463b8892748f8efdd
-title: Step 65
+title: Step 67
challengeType: 20
dashedName: step-67
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
index e2ed67b3ab6..1eeeb3697b1 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
@@ -1,6 +1,6 @@
---
id: 6554d0332949b133a0b35eaa
-title: Step 66
+title: Step 68
challengeType: 20
dashedName: step-68
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
index 863de41bbc0..5f093f3df2c 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
@@ -1,6 +1,6 @@
---
id: 6554d15c8acb5f34499ad789
-title: Step 67
+title: Step 69
challengeType: 20
dashedName: step-69
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
index c24fa10d6c6..65ac8f3f6c4 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
@@ -1,6 +1,6 @@
---
id: 6554d25dc5ceaa354307a77e
-title: Step 68
+title: Step 70
challengeType: 20
dashedName: step-70
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
index 076f1a41e91..2df3eb6fceb 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
@@ -1,6 +1,6 @@
---
id: 6554de295ade563a069936a1
-title: Step 69
+title: Step 71
challengeType: 20
dashedName: step-71
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
index 9793f1023c3..5e52b90279e 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
@@ -1,6 +1,6 @@
---
id: 6554dfce1683be3c0c9609a6
-title: Step 70
+title: Step 72
challengeType: 20
dashedName: step-72
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
index 9454a27cb5e..02e14d9019c 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
@@ -1,6 +1,6 @@
---
id: 6554e0adc7bb193cbfdb36d5
-title: Step 71
+title: Step 73
challengeType: 20
dashedName: step-73
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
index 182346eca82..7f91537aead 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
@@ -1,6 +1,6 @@
---
id: 6554e2ee23bfd93f2c83640f
-title: Step 72
+title: Step 74
challengeType: 20
dashedName: step-74
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
index 48ececac1ab..d5bdb7ff5d1 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
@@ -1,6 +1,6 @@
---
id: 6554e343caea913ffba7bec6
-title: Step 73
+title: Step 75
challengeType: 20
dashedName: step-75
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
index 368cf69b225..a80c318bd1d 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
@@ -1,6 +1,6 @@
---
id: 655516e410b8e30fb4fb64e8
-title: Step 74
+title: Step 76
challengeType: 20
dashedName: step-76
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
index 22de7de4fa0..82e1790a7d8 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
@@ -1,6 +1,6 @@
---
id: 65551a628bcb7e121e32d04b
-title: Step 77
+title: Step 79
challengeType: 20
dashedName: step-79
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
index 7f0ec8191b3..8603eb7e6d8 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
@@ -1,6 +1,6 @@
---
id: 6555201d9b7fc917399f9f0b
-title: Step 78
+title: Step 80
challengeType: 20
dashedName: step-80
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
index 01549558a4b..5c6c8181984 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
@@ -1,6 +1,6 @@
---
id: 655520c20cb1e6177b0641d6
-title: Step 79
+title: Step 81
challengeType: 20
dashedName: step-81
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
index cc4f4eacee1..db091c232cc 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
@@ -1,6 +1,6 @@
---
id: 655522883e66f618e03a9411
-title: Step 80
+title: Step 82
challengeType: 20
dashedName: step-82
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
index cd29fc36bb4..9588d739f44 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
@@ -1,6 +1,6 @@
---
id: 6555231eac4d9f19bd3d44b5
-title: Step 81
+title: Step 83
challengeType: 20
dashedName: step-83
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
index c02b037de64..b8c910a3aa5 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
@@ -1,6 +1,6 @@
---
id: 65552a111190e11f0963949e
-title: Step 82
+title: Step 84
challengeType: 20
dashedName: step-84
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
index eb0c5d14c63..28da95df2b0 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
@@ -1,6 +1,6 @@
---
id: 65552a9593755e1fb2f5ab50
-title: Step 83
+title: Step 85
challengeType: 20
dashedName: step-85
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
index aa1a050cf04..4fcaff7b89c 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
@@ -1,6 +1,6 @@
---
id: 65552b14e803731fe3c1e4ca
-title: Step 84
+title: Step 86
challengeType: 20
dashedName: step-86
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
index 3b6cc0579a3..f8ea2a67964 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
@@ -1,6 +1,6 @@
---
id: 65553159615a8123b190ee43
-title: Step 85
+title: Step 87
challengeType: 20
dashedName: step-87
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
index 1e3ad3dfb8a..6799724af14 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
@@ -1,6 +1,6 @@
---
id: 6555d6e12c95701172b55709
-title: Step 75
+title: Step 77
challengeType: 20
dashedName: step-77
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
index f3c3b93e0c6..97049b3b537 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
@@ -1,6 +1,6 @@
---
id: 6555d8b0b3d20b128bdadd37
-title: Step 76
+title: Step 78
challengeType: 20
dashedName: step-78
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
index 866b80d387b..d310105bfe1 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
@@ -1,6 +1,6 @@
---
id: 6555db4a7b788e15795674e5
-title: Step 87
+title: Step 89
challengeType: 20
dashedName: step-89
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
index 2cf86f2dd96..3a91139cf33 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
@@ -1,6 +1,6 @@
---
id: 6555df0c81300b175308557d
-title: Step 88
+title: Step 90
challengeType: 20
dashedName: step-90
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
index 959034b7875..bc5788b45f8 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
@@ -1,6 +1,6 @@
---
id: 6555e1bfcd374e18c6be8e58
-title: Step 89
+title: Step 91
challengeType: 20
dashedName: step-91
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
index 791d9bdbd6d..4d7848b4be9 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
@@ -1,6 +1,6 @@
---
id: 6555e3f387381a19d5e00333
-title: Step 90
+title: Step 92
challengeType: 20
dashedName: step-92
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
index 20f69b6bd24..e895a41b321 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
@@ -1,6 +1,6 @@
---
id: 6555e43e783ed31a0532b1b2
-title: Step 91
+title: Step 93
challengeType: 20
dashedName: step-93
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
index 9acf44cfdc2..f878bb6c12b 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
@@ -1,6 +1,6 @@
---
id: 6555e547c18a2b1a7b795bd8
-title: Step 93
+title: Step 95
challengeType: 20
dashedName: step-95
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
index 312d322e32f..9b3df4758a0 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
@@ -1,6 +1,6 @@
---
id: 6555e5991af57d1ae0e35f0a
-title: Step 94
+title: Step 96
challengeType: 20
dashedName: step-96
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
index 3493c823d5d..1bb2f8f1567 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
@@ -1,6 +1,6 @@
---
id: 65a450e8fb2c9d75c7378d28
-title: Step 86
+title: Step 88
challengeType: 20
dashedName: step-88
---
diff --git a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
index a15a486b7eb..29a960e8277 100644
--- a/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
+++ b/curriculum/challenges/japanese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
@@ -1,6 +1,6 @@
---
id: 65a51c9e000b660122b8b29e
-title: Step 92
+title: Step 94
challengeType: 20
dashedName: step-94
---
diff --git a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md b/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
deleted file mode 100644
index 632abe728dd..00000000000
--- a/curriculum/challenges/japanese/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
+++ /dev/null
@@ -1,344 +0,0 @@
----
-id: 62aa1fed3d4e873366ff3131
-title: Step 150
-challengeType: 0
-dashedName: step-150
----
-
-# --description--
-
-In your `attack` function, below the `health` variable, create an `if` statement. Set the condition to call the `isMonsterHit` function.
-
-# --hints--
-
-You should add an `if` statement which calls `isMonsterHit` in the condition.
-
-```js
-assert.match(attack.toString(), /if\s*\(\s*isMonsterHit\s*\(\s*\)/)
-```
-
-# --seed--
-
-## --seed-contents--
-
-```html
-
-
-
-
-
-
+
+Within the `Vector` class, create an `__init__` method and give it three parameters, `self`, `x`, and `y`.
+
+# --hints--
+
+You should define an `__init__` method inside the `Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").has_function("__init__")`)) })
+```
+
+Your `__init__` method should take three parameters: `self`, `x`, and `y`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").find_function("__init__").has_args("self, x, y")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ pass
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
new file mode 100644
index 00000000000..62ab349a8db
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
@@ -0,0 +1,38 @@
+---
+id: 65f055b9190fc41ca35549b8
+title: Step 3
+challengeType: 20
+dashedName: step-3
+---
+
+# --description--
+
+Python offers various methods that include both a leading and trailing double underscore in their names. You may already be familiar with some, such as `__init__` and `__str__`. These methods, which follow the `__
+
+So far, you created a 2-dimensional vector. You want to be able to represent vectors with a different number of dimensions without rewriting the necessary code for each specific case. For that, you will use inheritance.
+
+Start by renaming the `Vector` class into `R2Vector` to specify that this class is going to deal with 2-dimensional vectors. Remember to modify the instantiation of `v1`, too.
+
+# --hints--
+
+You should rename the `Vector` class into `R2Vector`. Remember to modify the instantiation of `v1`, too.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+v1 = Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
new file mode 100644
index 00000000000..e26a20b0730
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
@@ -0,0 +1,70 @@
+---
+id: 65f40051d6b09a139f253e8e
+title: Step 12
+challengeType: 20
+dashedName: step-12
+---
+
+# --description--
+
+Inheritance enables you to define a class from an existing one. The new class, called child, inherits all the methods and properties of the existing class, called parent.
+
+```py
+class Tree:
+ def sprout(self):
+ print('Making new leaves!')
+
+class Oak(Tree):
+ pass
+
+Oak().sprout() # Output: Making new leaves!
+```
+
+In the example above, the child class `Oak` inherits from `Tree` and inherits the `sprout` method from the parent class `Tree`.
+
+Create a new class named `R3Vector` and follow the example above to make it inherit from the `R2Vector` class.
+
+# --hints--
+
+You should define a new class `R3Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R3Vector")
+ `))
+})
+```
+
+Your new class `R3Vector` should inherit from `R2Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").inherits_from("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
new file mode 100644
index 00000000000..c50cbefeb4a
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
@@ -0,0 +1,56 @@
+---
+id: 65f40401e6ef53173c04e27d
+title: Step 13
+challengeType: 20
+dashedName: step-13
+---
+
+# --description--
+
+Within your new class, declare an `__init__` method. Give it `self`, `x`, `y`, and `z` as the parameters.
+
+# --hints--
+
+You should define an `__init__` method inside your `R3Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").has_function("__init__")
+ `))
+})
+```
+
+Your `__init__` method should have four parameters `self`, `x`, `y`, and `z`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, x, y, z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
new file mode 100644
index 00000000000..cb7a33c0eb1
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
@@ -0,0 +1,49 @@
+---
+id: 65f407ea37ad6e181b90462e
+title: Step 14
+challengeType: 20
+dashedName: step-14
+---
+
+# --description--
+
+You could assign each `i` parameter to `self.i` as you did before. Although in this case you have few lines to repeat, one way to avoid this repetition is using the `super()` function. `super()` enables you to refer implicitly to the parent class: `super().__init__(x, y)` calls the `__init__` method of the parent class.
+
+Add a `super().__init__(x, y)` call to your `__init__` method.
+
+# --hints--
+
+You should have a `super().__init__(x, y)` call in your `__init__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_stmt("super().__init__(x, y)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
new file mode 100644
index 00000000000..caf708394fc
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
@@ -0,0 +1,47 @@
+---
+id: 65f40f8af784751c613d638a
+title: Step 15
+challengeType: 20
+dashedName: step-15
+---
+
+# --description--
+
+Now, you need to assign `z` to the `z` attribute of your `R3Vector` object.
+
+# --hints--
+
+You should assign `z` to `self.z` after the `super` call.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").is_ordered("super().__init__(x, y)", "self.z = z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
new file mode 100644
index 00000000000..68340ee6c11
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
@@ -0,0 +1,47 @@
+---
+id: 65f40fdb3579aa1ced28b2eb
+title: Step 16
+challengeType: 20
+dashedName: step-16
+---
+
+# --description--
+
+Create an `R3Vector` instance with `2`, `2`, and `3` as the values of `x`, `y`, and `z`, respectively. Assign the new instance to `v2`.
+
+# --hints--
+
+You should declare a variable `v2` and assign it `R3Vector(2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(2, 2, 3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
new file mode 100644
index 00000000000..06b727e3b29
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
@@ -0,0 +1,72 @@
+---
+id: 65f412c208c3791fee305acf
+title: Step 17
+challengeType: 20
+dashedName: step-17
+---
+
+# --description--
+
+In Python, you can enforce the use of keyword-only arguments by adding a `*` as an additional argument to the function or method signature. Modify both `__init__` methods by adding a `*` as the second parameter (after `self`). Every parameter placed after that will require the use of a keyword argument in the function/method call.
+
+This means that you need to modify the `super().__init__(x, y)` call, too. Do it by giving `x` the value `x`, and `y` the value `y`.
+
+Finally, modify the instantiation of `v1` and `v2` by using keyword arguments.
+
+# --hints--
+
+You should enforce keyword arguments by adding a `*` as the second parameter in both your `__init__` methods.
+
+```js
+({ test: () => {
+ assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__init__").has_args("self, *, x, y")`));
+ assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, *, x, y, z")`));
+} })
+```
+
+You should modify your `super.__init__(x, y)` call to use keyword arguments.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").find_body().is_equivalent("super().__init__(x=x, y=y)\\nself.z = z")`)) })
+```
+
+You should modify the assignment of `v1` to be `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R2Vector(x=2, y=3)")`)) })
+```
+
+You should modify the assignment of `v2` to be `R3Vector(x=2, y=2, z=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=2, y=2, z=3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+v2 = R3Vector(2, 2, 3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
new file mode 100644
index 00000000000..ef31cdd6194
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
@@ -0,0 +1,64 @@
+---
+id: 65f4148dea0f802040225e0c
+title: Step 18
+challengeType: 20
+dashedName: step-18
+---
+
+# --description--
+
+Remove the existing `print` calls. Then, as you did before for `v1`, print `v2` and the value returned by `v2.norm()`.
+
+# --hints--
+
+You should not have `print(v1)` and `print(v1.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1.norm())")`));
+ }
+})
+```
+
+You should print `v2` and `v2.norm()`.
+
+```js
+({
+ test: () => {
+ assert(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+print(v1.norm())
+print(v1)
+
+v2 = R3Vector(x=2, y=2, z=3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
new file mode 100644
index 00000000000..1a83f17e994
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
@@ -0,0 +1,64 @@
+---
+id: 65f4520e363e2642f8112e33
+title: Step 19
+challengeType: 20
+dashedName: step-19
+---
+
+# --description--
+
+As you can see, something is not quite right. The `norm` and `__str__` methods inherited from `R2Vector` cannot adapt to a 3-dimensional vector. Their implementation has to be more flexible.
+
+Every object in Python has a special attribute named `__dict__`, which is a dictionary that stores the object attributes.
+
+Remove the existing `print` calls. Then, print the `__dict__` attribute of your `v1` and `v2` vectors to see what they look like.
+
+# --hints--
+
+You should not have `print(v2)` and `print(v2.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+You should print the `__dict__` attribute of `v1` and `v2`.
+
+```js
+({ test: () => assert(runPython(`
+(_Node(_code).has_call("print(v1.__dict__)") and _Node(_code).has_call("print(v2.__dict__)")) or _Node(_code).has_call("print(v1.__dict__, v2.__dict__)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v2.norm())
+print(v2)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
new file mode 100644
index 00000000000..2a2c8f28376
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
@@ -0,0 +1,49 @@
+---
+id: 65f4535bbdb28d436ff3ddc9
+title: Step 20
+challengeType: 20
+dashedName: step-20
+---
+
+# --description--
+
+As you can see from the output, `__dict__` contains the values of your instance attributes. Instead of explicitly adding the squares of `self.x` and `self.y`, you are going to iterate over the values stored in `__dict__` to calculate the value of the norm.
+
+Within the `norm` method body, replace the content of the parentheses with a generator expression that elevates each value `val` in `self.__dict__.values()` to the power of `2`. Also, pass that generator expression as the argument to the `sum` function, so that all the squares are added together before calculating the square root.
+
+# --hints--
+
+You should return `sum(val**2 for val in self.__dict__.values())**0.5` from `norm()` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in self.__dict__.values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
new file mode 100644
index 00000000000..bbb82436c52
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
@@ -0,0 +1,53 @@
+---
+id: 65f870003444fb1a2ad171f2
+title: Step 21
+challengeType: 20
+dashedName: step-21
+---
+
+# --description--
+
+Modify the two `print` calls to print the norm of your vectors and verify that the `norm()` method works fine.
+
+# --hints--
+
+You should print `v1.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1.norm())")`)) })
+```
+
+You should print `v2.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v2.norm())")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
new file mode 100644
index 00000000000..22e3cab792e
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
@@ -0,0 +1,61 @@
+---
+id: 65f8709620b2ce1a62608f5a
+title: Step 23
+challengeType: 20
+dashedName: step-23
+---
+
+# --description--
+
+When you need to dynamically access some attributes starting from a string input, the built-in `getattr()` function is what you need. It takes an object as its first argument, and a string containing the attribute name as its second attribute.
+
+Start to fix the `__str__` method by replacing the string returned by `__str__()` with a generator expression that iterates through the object attributes and calls `getattr()` for each attribute `i`.
+
+# --hints--
+
+You should return a generator expression that iterates over `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_iters()[0].is_equivalent("vars(self)")`)) })
+```
+
+You should return a generator expression that uses `i` as the iteration variable.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_targets()[0].is_equivalent("i")`)) })
+```
+
+You should return a generator expression that calls `getattr(self, i)` for each item `i` in `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_expr().is_equivalent("getattr(self, i)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
new file mode 100644
index 00000000000..668bd89de56
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
@@ -0,0 +1,47 @@
+---
+id: 65f8720685ec351abef26740
+title: Step 24
+challengeType: 20
+dashedName: step-24
+---
+
+# --description--
+
+To obtain a proper string representation, call the `tuple()` constructor and pass it the generator expression you wrote in the previous step as the argument.
+
+# --hints--
+
+You should pass the expression returned by the `__str__` method to the `tuple()` constructor.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("tuple(getattr(self, i) for i in vars(self))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return (getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
new file mode 100644
index 00000000000..789f37ee6fe
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
@@ -0,0 +1,47 @@
+---
+id: 65f872a0fe6aa21b456ad4fe
+title: Step 25
+challengeType: 20
+dashedName: step-25
+---
+
+# --description--
+
+Finally, pass the `tuple()` call as the argument to the `str()` function.
+
+# --hints--
+
+You should pass the `tuple()` call you are currently returning from the `__str__` method to the `str()` function.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("str(tuple(getattr(self, i) for i in vars(self)))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return tuple(getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
new file mode 100644
index 00000000000..6a2c44baef5
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
@@ -0,0 +1,56 @@
+---
+id: 65f8749b13774b1d2e4a7fba
+title: Step 27
+challengeType: 20
+dashedName: step-27
+---
+
+# --description--
+
+While the `__str__` method returns a human-readable string representation of an object, the `__repr__` method is supposed to return the string needed to instantiate the object.
+
+Add a `__repr__` method with a `self` parameter within the `R2Vector` class.
+
+# --hints--
+
+Your `R2Vector` class should have a `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__repr__")`)) })
+```
+
+Your `__repr__` method should have a `self` parameter.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_args("self")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
new file mode 100644
index 00000000000..7f5a3e0f9c9
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
@@ -0,0 +1,74 @@
+---
+id: 65f876d17832001e8e1abb05
+title: Step 28
+challengeType: 20
+dashedName: step-28
+---
+
+# --description--
+
+Declare a variable `arg_list`. Give it the value of a list comprehension that iterates over `key` and `val` for each key-value pair in `vars(self).items()` and computes the f-string `f'{key}={val}'` at each iteration.
+
+# --hints--
+
+You should declare a variable `arg_list`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_variable("arg_list")`)) })
+```
+
+You should assign a list comprehension that iterates over `vars(self).items()` to `arg_list`.
+
+```js
+({ test: () => runPython(`
+import ast
+var = _Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list")
+assert isinstance(var.tree.value, ast.ListComp), "Expected arg_list to be a list comprehension"
+assert (actual := var.find_comp_iters()[0].is_equivalent("vars(self).items()")), f"Expected vars(self).items(), got {actual}"
+`) })
+```
+
+The list comprehension assigned to `arg_list` should use `key` and `val` to iterate over `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_targets()[0].is_equivalent("key, val")
+`)) })
+```
+
+The list comprehension assigned to `arg_list` should compute the string `f'{key}={val}'` for each key-value pair in `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_expr().is_equivalent("f'{key}={val}'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
new file mode 100644
index 00000000000..0c56316394e
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
@@ -0,0 +1,50 @@
+---
+id: 65f93acbb514857003510e79
+title: Step 29
+challengeType: 20
+dashedName: step-29
+---
+
+# --description--
+
+Declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+# --hints--
+
+You should declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("args").is_equivalent("args = ', '.join(arg_list)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
new file mode 100644
index 00000000000..e826611fa57
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
@@ -0,0 +1,52 @@
+---
+id: 65f93b67169a9c703264458a
+title: Step 30
+challengeType: 20
+dashedName: step-30
+---
+
+# --description--
+
+Since the method should return the string to instantiate the object for `R2Vector` as well as `R3Vector` when inherited, you cannot build the string specifying the class name.
+
+You can access the name of a class with `__class__.__name__`. Add a `return` statement to the `__repr__` method and return the string necessary to instantiate the object.
+
+# --hints--
+
+You should use `__class__.__name__` to build the f-string needed to instantiate a vector object and return it from the `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_return("f'{self.__class__.__name__}({args})'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
new file mode 100644
index 00000000000..13682539c2c
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
@@ -0,0 +1,57 @@
+---
+id: 65f93d4647ce2670dc6f095c
+title: Step 31
+challengeType: 20
+dashedName: step-31
+---
+
+# --description--
+
+The `__repr__` method is called under the hood by the `repr` function. Verify that `__repr__` works properly by adding `f'\nrepr = {repr(v1)}'` and `f'\nrepr = {repr(v2)}'` as the second argument to your first and second `print` calls, respectively.
+
+# --hints--
+
+You should add `f'\nrepr = {repr(v1)}'` as the second argument to your `print(f'v1 = {v1}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}', f'\\\\nrepr = {repr(v1)}')")`)) })
+```
+
+You should add `f'\nrepr = {repr(v2)}'` as the second argument to your `print(f'v2 = {v2}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}', f'\\\\nrepr = {repr(v2)}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
new file mode 100644
index 00000000000..a25da243ba9
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
@@ -0,0 +1,56 @@
+---
+id: 65f93e54a9121571dcdd3e79
+title: Step 32
+challengeType: 20
+dashedName: step-32
+---
+
+# --description--
+
+The output is correct, `repr` is giving you the string required to instantiate the objects.
+
+Now comment out both your `print` calls.
+
+# --hints--
+
+You should comment out both your `print()` calls.
+
+```js
+({ test: () => {
+ assert.match(code, /#\s*print\s*\(\s*f('|")v1 = \{\s*v1\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v1\s*\)\s*\}\2\s*\)/);
+ assert.match(code, /#\s*print\s*\(\s*f('|")v2 = \{\s*v2\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v2\s*\)\s*\}\2\s*\)/);
+} })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
new file mode 100644
index 00000000000..127f701ba31
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
@@ -0,0 +1,62 @@
+---
+id: 65f9b17a638f0d0dcce8c354
+title: Step 38
+challengeType: 20
+dashedName: step-38
+---
+
+# --description--
+
+To create a vector space, you need to define how vectors should behave in several cases. Vectors can be added, forming a new vector.
+
+The special method `__add__` can be implemented to override what happens by default when two objects are added together using the `+` operator.
+
+Right now, trying to add two instances of `R2Vector` or `R3Vector` would raise an exception. Create an empty `__add__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define an `__add__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__add__")`)) })
+```
+
+Your `__add__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
new file mode 100644
index 00000000000..f90c14fe57b
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b486989cb90ff3e77ac8
+title: Step 39
+challengeType: 20
+dashedName: step-39
+---
+
+# --description--
+
+The `other` parameter of your `__add__` method represents the operand placed at the right side of the `+` operator in an addition operation.
+
+You want to verify that the right-hand operand is not an object of the same class as the left-hand operand (i.e. `self`). Create an `if` statement that verifies that by checking the type of the operands.
+
+# --hints--
+
+You should create an `if` statement that checks if `type(self)` and `type(other)` are different.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
new file mode 100644
index 00000000000..1fa83e0f9aa
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b9710cca621244d3bde1
+title: Step 40
+challengeType: 20
+dashedName: step-40
+---
+
+# --description--
+
+In Python, `NotImplemented` is a special value used to indicate that an operation is not implemented for a specific case.
+
+`NotImplemented` does not raise an exception immediately. Instead, it signals to ask to the other operand how to perform the operation. If the request cannot be satisfied, a `TypeError` is returned by default.
+
+Because you want to be able to sum two vectors only if they belong to the same class, return `NotImplemented` from the `if` statement you created in the previous step.
+
+# --hints--
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
new file mode 100644
index 00000000000..9df77e46895
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
@@ -0,0 +1,58 @@
+---
+id: 65f9bb7c0d524612b2a88a4b
+title: Step 41
+challengeType: 20
+dashedName: step-41
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_stmt("kwargs = {}")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
new file mode 100644
index 00000000000..f5d28e43bd6
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
@@ -0,0 +1,92 @@
+---
+id: 65f9bc10a9fb1612e066e9e8
+title: Step 42
+challengeType: 20
+dashedName: step-42
+---
+
+# --description--
+
+When adding two vectors, each component of one vector is added to the same component of the other vector. For example, adding `(1, 2)` and `(2, 4)` generates a third vector `(3, 6)`, where `3` is the sum of `1` and `2` and `6` is the sum of `2` and `4`.
+
+The `kwargs` dictionary will contain the key-value pairs needed to instantiate a new vector of the same class of the two vectors added together.
+
+Turn the empty dictionary into a dictionary comprehension that iterates through `vars(self)` and for each key (`i`) creates a key-value pair, where the key is the same key of the current iteration and its value is the sum of the values of the `i` attributes of the two operands.
+
+# --hints--
+
+You should turn the empty dictionary assigned to `kwargs` into a dictionary comprehension that iterates over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_iters()[0].is_equivalent("vars(self)")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_key().is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the sum of the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i` in `vars(self)`. Use the `getattr()` function for that.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) + getattr(other, i)") or node.is_equivalent("getattr(other, i) + getattr(self, i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
new file mode 100644
index 00000000000..d1cd1755778
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
@@ -0,0 +1,70 @@
+---
+id: 65f9c2c2006feb1428ad2d4c
+title: Step 43
+challengeType: 20
+dashedName: step-43
+---
+
+# --description--
+
+You can unpack a dictionary into keyword arguments by using the `**` operator:
+
+```py
+def spam(a, b):
+ return a + b
+
+my_dict = {a: 11, b: 4}
+
+spam(**my_dict) # 15
+```
+
+Return an instance of the current class by using `__class__` and passing `**kwargs` as the argument.
+
+# --hints--
+
+You should return `self.__class__(**kwargs)` from the `__add__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
new file mode 100644
index 00000000000..689ab778fe5
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
@@ -0,0 +1,90 @@
+---
+id: 65f9cb678070ca1668898c70
+title: Step 44
+challengeType: 20
+dashedName: step-44
+---
+
+# --description--
+
+In the same way `__add__` is called under the hood when two objects are added together, the `__sub__` method is called implicitly in case of subtraction.
+
+Now, define an empty `__sub__` method and give two parameters: `self`, and `other`. Inside your new method, create an if statement to check if `self` and `other` do not belong to the same class and return `NotImplemented`, as you did previously.
+
+# --hints--
+
+You should define a `__sub__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__sub__")
+ `))
+})
+```
+
+Your `__sub__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_args("self, other")
+ `))
+})
+```
+
+You should create an `if` statement that checks if `self` and `other` does not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+ `))
+})
+```
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
new file mode 100644
index 00000000000..2d452d2413e
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
@@ -0,0 +1,89 @@
+---
+id: 65f9dd6e5a08af19c196c2df
+title: Step 45
+challengeType: 20
+dashedName: step-45
+---
+
+# --description--
+
+The vector resulting from the subtraction of one vector from another is obtained by calculating the difference of each of their components. For example, subtracting `(2, 4)` from `(7, 3)` generates a third vector `(5, -1)`, where `5` is the difference between `7` and `2` and `-1` is the difference between `3` and `4`.
+
+As you did before inside the `__add__` method, declare a `kwargs` variable after the `if` statement. Assign it a dictionary comprehension that iterates through the object attributes and creates a key-value pair for each key `i`, where the key is the same key as the current iteration and its value is the difference between the values of the `i` attributes of two operands.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it a dictionary comprehension that iterates over the object attributes.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_iters()[0]
+node.is_equivalent("vars(self)") or node.is_equivalent("self.__dict__")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over the object attributes.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_key().is_equivalent("i")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the difference between the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i`.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) - getattr(other, i)") or node.is_equivalent("self.__getattribute__(i) - other.__getattribute__(i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
new file mode 100644
index 00000000000..095bce27c7c
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
@@ -0,0 +1,65 @@
+---
+id: 65f9dfd2e75e291a38695f13
+title: Step 46
+challengeType: 20
+dashedName: step-46
+---
+
+# --description--
+
+Finally, return a new vector object. Use `__class__` and unpack `kwargs` to instantiate the new vector.
+
+# --hints--
+
+You should return a new vector using `__class__` and unpacking `kwargs` from the `__sub__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
new file mode 100644
index 00000000000..c5cb7742541
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
@@ -0,0 +1,67 @@
+---
+id: 65f9e0a578b22c1a736f3d82
+title: Step 47
+challengeType: 20
+dashedName: step-47
+---
+
+# --description--
+
+Modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+# --hints--
+
+You should modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v2 = R2Vector(x=0.5, y=1.25)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
new file mode 100644
index 00000000000..1d277671da4
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
@@ -0,0 +1,67 @@
+---
+id: 65fa8d5cf0ef3b141010f5d8
+title: Step 48
+challengeType: 20
+dashedName: step-48
+---
+
+# --description--
+
+It's time to verify that the addition and subtraction operations work as expected. Declare another variable `v3` and assign it the sum of `v1` plus `v2`.
+
+# --hints--
+
+You should declare a variable `v3` and assign it the sum of `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v3 = v1 + v2") or _Node(_code).has_stmt("v3 = v2 + v1")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
new file mode 100644
index 00000000000..87ddac5ea5f
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
@@ -0,0 +1,64 @@
+---
+id: 65fa8df56a0e2c149b4d24fe
+title: Step 49
+challengeType: 20
+dashedName: step-49
+---
+
+# --description--
+
+Next, check the new vector by printing the following f-string `f'v1 + v2 = {v3}'`.
+
+# --hints--
+
+You should print `f'v1 + v2 = {v3}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 + v2 = {v3}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
new file mode 100644
index 00000000000..e526a9cd4cc
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
@@ -0,0 +1,77 @@
+---
+id: 65fa9402d1fb5516aa42159d
+title: Step 50
+challengeType: 20
+dashedName: step-50
+---
+
+# --description--
+
+Feel free to modify `v3` so that it sums an `R2Vector` instance with an object of a different type, such as an integer or a string. You will be able to see a `TypeError` message printed on the console.
+
+Then, restore the original line and create a new variable `v4`. Assign the difference between `v1` and `v2` to your new variable and print the result following the same structure as the previous f-string.
+
+# --hints--
+
+You should declare a variable `v4` and assign it the difference between `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v4 = v1 - v2")
+ `))
+})
+```
+
+You should print `f'v1 - v2 = {v4}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 - v2 = {v4}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
new file mode 100644
index 00000000000..d2df1c3038d
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
@@ -0,0 +1,85 @@
+---
+id: 65fa9e1b6c6db919385359ec
+title: Step 51
+challengeType: 20
+dashedName: step-51
+---
+
+# --description--
+
+The special method `__mul__` can be implemented to specify what should happen when the current instance is multiplied by another object.
+
+Create an empty `__mul__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `__mul__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__mul__")
+ `))
+})
+```
+
+Your `__mul__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__mul__").has_args("self, other")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
new file mode 100644
index 00000000000..0a18b8b69d1
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
@@ -0,0 +1,94 @@
+---
+id: 65faaed8f7a9772f023ea816
+title: Step 52
+challengeType: 20
+dashedName: step-52
+---
+
+# --description--
+
+Vectors can be multiplied by a *scalar*, i.e. a number that multiplies each single component. The result of scalar multiplication is a vector with the same orientation as the original vector but a different magnitude.
+
+Implement the scalar multiplication by checking if `other` is either an `int` or a `float`. If it is, return a new instance of the current class that has each component of the starting vector multiplied by `other`. This will be the vector resulting from the scalar multiplication.
+
+Make sure the methods can be applied to compute the scalar multiplication of vectors with any number of dimensions.
+
+# --hints--
+
+Your method should return a new instance of the current class only when the type of `other` is either `int` or `float`.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=0, y=0)
+v2 = R3Vector(x=0, y=0, z=0)
+types = ["", True, [], {}]
+assert all((v1 * i) is None for i in types)
+types = [1, 1.0]
+assert all(type(v1 * i) is type(v1) for i in types)
+assert all(type(v2 * i) is type(v2) for i in types)
+`) })
+```
+
+The vector resulting from the scalar multiplication should have each component of the starting vector multiplied by the scalar.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=1, y=1.5)
+v2 = R3Vector(x=2.2, y=3, z=-1)
+assert vars(v1 * 3) == vars(R2Vector(x=3, y=4.5))
+assert vars(v2 * (-2.0)) == vars(R3Vector(x=-4.4, y=-6.0, z=2.0))
+`) })
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
new file mode 100644
index 00000000000..bcf1d3d0b55
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
@@ -0,0 +1,79 @@
+---
+id: 65fc87e19930a503e5f05500
+title: Step 53
+challengeType: 20
+dashedName: step-53
+---
+
+# --description--
+
+A vector can be multiplied by another vector, too. This operation is called *dot product*, or *scalar product*.
+
+Create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+You are going to implement the dot product inside this block during the next step.
+
+# --hints--
+
+You should create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__mul__").find_ifs()[0].find_conditions()[1]
+node.is_equivalent("type(self) == type(other)") or node.is_equivalent("type(other) == type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
new file mode 100644
index 00000000000..c5edc6d9b45
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
@@ -0,0 +1,87 @@
+---
+id: 65fc899d77495504d6deeccc
+title: Step 54
+challengeType: 20
+dashedName: step-54
+---
+
+# --description--
+
+The scalar product between two vectors $\mathbf{a}$ and $\mathbf{b}$ is indicated as:
+
+\\( \mathbf{a} \cdot \mathbf{b} = a_1 \cdot b_1 + a_2 \cdot b_2 + \ldots + a_n \cdot b_n = \sum_{i=1}^{n} a_i \cdot b_i \\)
+
+Where each component of $\mathbf{a}$ is multiplied by the correspondent component of $\mathbf{b}$, and all the products are summed together, resulting in a number.
+
+Within the `elif` clause, implement the above formula to compute the result of a scalar product and return the result. Remember that your implementation must be valid for any vector, independently from the number of components, when the method is inherited.
+
+# --hints--
+
+You should implement the scalar product calculation and return the result inside the `elif` body of your `__mul__` method.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+v3 = R3Vector(x=2, y=3, z=1.5)
+v4 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1*v2 == 4.75 and v3*v4 == 7.0
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
new file mode 100644
index 00000000000..36b78391926
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
@@ -0,0 +1,78 @@
+---
+id: 65fc8e7c766ab1070213aadb
+title: Step 55
+challengeType: 20
+dashedName: step-55
+---
+
+# --description--
+
+In case `other` is not an integer, a floating point number, or another instance of the current class, no product can be computed.
+
+After the `elif` clause, return `NotImplemented`.
+
+# --hints--
+
+You should return `NotImplemented` after the `elif` clause.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__mul__").has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
new file mode 100644
index 00000000000..bf365bd4903
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
@@ -0,0 +1,82 @@
+---
+id: 65fc8fa7e7860407ab479bf0
+title: Step 56
+challengeType: 20
+dashedName: step-56
+---
+
+# --description--
+
+It's time to test the multiplication. Declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`. Then, call the `print` function and pass it the following f-string: `f'v1 * 3 = {v5}'`.
+
+# --hints--
+
+You should declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * 3")`)) })
+```
+
+You should print the f-string `f'v1 * 3 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * 3 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
new file mode 100644
index 00000000000..034109b8c53
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
@@ -0,0 +1,87 @@
+---
+id: 65fd681b20b7e45f55def415
+title: Step 57
+challengeType: 20
+dashedName: step-57
+---
+
+# --description--
+
+The scalar multiplication works fine. Now, modify the assignment of `v5` to be the dot product `v1 * v2`. Also, update the `print` call.
+
+Before doing that, feel free to experiment and multiply `v1` by an object of invalid type to see the error message printed on the console.
+
+
+# --hints--
+
+You should update the assignment of `v5` assigning it the scalar product `v1 * v2`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * v2")`)) })
+```
+
+You should update your `print` call to print the f-string `f'v1 * v2 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * v2 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * 3
+print(f'v1 * 3 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
new file mode 100644
index 00000000000..f6184775ca4
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9250db0d6b8198cf29ef
+title: Step 58
+challengeType: 20
+dashedName: step-58
+---
+
+# --description--
+
+The `__eq__` method can be implemented to specify what should happen in case the comparison operator (`==`) is used to compare an object with something else.
+
+Within the `R2Vector` class, create an `__eq__` method and give it two parameters: `self` and `other`.
+
+# --hints--
+
+You should define a `__eq__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__eq__")`)) })
+```
+
+Your `__eq__` method should take two parameters: `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
new file mode 100644
index 00000000000..5d2d8cfc678
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
@@ -0,0 +1,88 @@
+---
+id: 65fd95c23beef982af29004c
+title: Step 59
+challengeType: 20
+dashedName: step-59
+---
+
+# --description--
+
+You want to compare two vectors, only when they belong to the same class. For that create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented` in that case.
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
new file mode 100644
index 00000000000..c3bea995dc8
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
@@ -0,0 +1,91 @@
+---
+id: 65fd97f3c1b4c4839bdeb8d2
+title: Step 60
+challengeType: 20
+dashedName: step-60
+---
+
+# --description--
+
+To compare two vectors, you are going to check that each component of the first vector is equal to the same component of the second vector.
+
+After the `if` statement you created in the previous step, return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+# --hints--
+
+The `__eq__` method should return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1 == v2 and not v1 == v3 and v4 == v5 and not v5 == v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
new file mode 100644
index 00000000000..a7f5d701215
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
@@ -0,0 +1,102 @@
+---
+id: 65fd9aa649f6cc84631882a9
+title: Step 61
+challengeType: 20
+dashedName: step-61
+---
+
+# --description--
+
+The `__ne__` method is called under the hood when the `!=` operator is used. Define a `__ne__` method with two parameters `self` and `other`. From your new method, return the opposite of `self == other`.
+
+# --hints--
+
+You should define a `__ne__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ne__")`)) })
+```
+
+Your `__ne__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ne__").has_args("self, other")`)) })
+```
+
+The `__ne__` method should return `False` if each attribute of the current instance is equal to the same attribute of `other` and `True` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+not v1 != v2 and v1 != v3 and not v4 != v5 and v5 != v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
new file mode 100644
index 00000000000..c151f678d86
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
@@ -0,0 +1,86 @@
+---
+id: 65fd9c6e49d7cd8513ab1005
+title: Step 62
+challengeType: 20
+dashedName: step-62
+---
+
+# --description--
+
+At the end of your code, use the equality operator to compare `v1` and `R2Vector(x=2, y=3)` and print the result.
+
+# --hints--
+
+You should print the result of comparing `v1` and `R2Vector(x=2, y=3)` using the equality operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 == R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) == v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
new file mode 100644
index 00000000000..804d4947304
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9d6203afea85931094c9
+title: Step 63
+challengeType: 20
+dashedName: step-63
+---
+
+# --description--
+
+The comparison returns `True`, since the two vectors have the same components. Now, modify the argument of the `print` call you added in the previous step to use the inequality operator.
+
+# --hints--
+
+You should modify the `print` call you added in the previous step using the inequality operator to compare `v1` and `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) != v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 == R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
new file mode 100644
index 00000000000..9255b41f2c6
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
@@ -0,0 +1,97 @@
+---
+id: 65fd9e2c56ff19862dfb8cbb
+title: Step 64
+challengeType: 20
+dashedName: step-64
+---
+
+# --description--
+
+The `__lt__` method is called under the hood when the `<` operator is used to compare an object with something else.
+
+Add an empty `__lt__` method and give it two parameters: `self`, `other`.
+
+# --hints--
+
+You should define a `__lt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__lt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
new file mode 100644
index 00000000000..ee258ff8a2a
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
@@ -0,0 +1,100 @@
+---
+id: 65fdc3c8478ee70fc7966151
+title: Step 65
+challengeType: 20
+dashedName: step-65
+---
+
+# --description--
+
+In the same way you did before for the `__eq__` method, create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
new file mode 100644
index 00000000000..390babbb01f
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
@@ -0,0 +1,91 @@
+---
+id: 65fdc496f4440e1055a2ac1b
+title: Step 66
+challengeType: 20
+dashedName: step-66
+---
+
+# --description--
+
+After the `if` statement, return the result of comparing the norm of the current instance with the norm of `other` using the less than operator.
+
+# --hints--
+
+The `__lt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the `<` operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_return("self.norm() < other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
new file mode 100644
index 00000000000..7193db8cba2
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
@@ -0,0 +1,122 @@
+---
+id: 6601918b44a11b4a8c986c6a
+title: Step 67
+challengeType: 20
+dashedName: step-67
+---
+
+# --description--
+
+The `__gt__` method is called under the hood when the `>` operator is used to compare an object with something else.
+
+After the `__lt__` method, in the same way you did for `__lt__`, implement the `__gt__` method. Pay attention to use the appropriate operator.
+
+# --hints--
+
+You should define a `__gt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__gt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_args("self, other")`)) })
+```
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+The `__gt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the greater than operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_return("self.norm() > other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
new file mode 100644
index 00000000000..fd051c7fca6
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
@@ -0,0 +1,111 @@
+---
+id: 66019258a7c71d4ae50da42e
+title: Step 68
+challengeType: 20
+dashedName: step-68
+---
+
+# --description--
+
+There are still two possible comparisons to implement. The `__le__` method is called when the `<=` operator is used to compare two objects.
+
+Define a `__le__` method with `self` and `other` as the parameters and make it return the opposite of `self > other`.
+
+# --hints--
+
+You should define a `__le__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__le__")`)) })
+```
+
+Your `__le__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_args("self, other")`)) })
+```
+
+Your `__le__` method return the opposite of `self > other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_return("not self > other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
new file mode 100644
index 00000000000..542035862a5
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
@@ -0,0 +1,116 @@
+---
+id: 66019319edb1cb4b57d3a793
+title: Step 69
+challengeType: 20
+dashedName: step-69
+---
+
+# --description--
+
+The last method you need is `__ge__`, which is called when the `>=` is used to compare two objects.
+
+Define a `__ge__` method with `self` and `other` as the parameters and make it return the opposite of `self < other`.
+
+# --hints--
+
+You should define a `__ge__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ge__")`)) })
+```
+
+Your `__ge__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_args("self, other")`)) })
+```
+
+Your `__ge__` method should return the opposite of `self < other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_return("not self < other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
new file mode 100644
index 00000000000..fe9c0cfa362
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
@@ -0,0 +1,104 @@
+---
+id: 660193a2a71faa4bd8f10970
+title: Step 70
+challengeType: 20
+dashedName: step-70
+---
+
+# --description--
+
+Feel free to play around with the new comparison operations you implemented. Then, remove your last `print` call.
+
+
+# --hints--
+
+You should not have `print(v1 != R2Vector(x=2, y=3))` in your code.
+
+```js
+({test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
new file mode 100644
index 00000000000..2157c6b8a3b
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
@@ -0,0 +1,111 @@
+---
+id: 66019977710caa516276c0a8
+title: Step 71
+challengeType: 20
+dashedName: step-71
+---
+
+# --description--
+
+The *cross product*, or *vector product*, is defined between 3-dimensional vectors and results in a third vector perpendicular to both of them.
+
+The `R3Vector` class inherits from `R2Vector`, meaning it has access to all the methods and properties defined in `R2Vector`. A child class can implement additional features. You already saw a way to change the implementation of a method. Now, you are going to give the child class `R3Vector` a new method instead.
+
+Within the `R3Vector` class, define a `cross` method and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `cross` method within the `R3Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").has_function("cross")`)) })
+```
+
+Your `cross` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
new file mode 100644
index 00000000000..b7948eb83c6
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
@@ -0,0 +1,114 @@
+---
+id: 6601a7eb860fb8546516674d
+title: Step 72
+challengeType: 20
+dashedName: step-72
+---
+
+# --description--
+
+Create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
new file mode 100644
index 00000000000..7a7cb7ef03c
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
@@ -0,0 +1,105 @@
+---
+id: 6601a88a6e2ccc550d7d7208
+title: Step 73
+challengeType: 20
+dashedName: step-73
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_variable("kwargs").is_equivalent("kwargs = {}")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
new file mode 100644
index 00000000000..c9e2224dad3
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
@@ -0,0 +1,116 @@
+---
+id: 6601a8fb2e993b55912f9e9f
+title: Step 74
+challengeType: 20
+dashedName: step-74
+---
+
+# --description--
+
+The dot product between two 3D vectors \\( \mathbf{a} \\) and \\( \mathbf{b} \\) can be computed as it follows:
+
+\\[ \mathbf{a} \times \mathbf{b} = \begin{pmatrix} a_yb_z - a_zb_y \\\ a_zb_x - a_xb_z \\\ a_xb_y - a_yb_x \end{pmatrix} \\]
+
+Where the resulting vector is represented as a column vector.
+
+Implement the formula above to compute the dot product between two 3-dimensional vectors and return the resulting vector from the `cross()` method.
+
+# --hints--
+
+The `cross()` method should return a new `R3Vector` instance resulting from the dot product computation.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+v1.cross(v2) == R3Vector(x=4.75, y=-3.5, z=1.0) and v2.cross(v1) == R3Vector(x=-4.75, y=3.5, z=-1.0) and v1.cross(v1) == R3Vector(x=0, y=0, z=0)
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
new file mode 100644
index 00000000000..c1435330d56
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
@@ -0,0 +1,119 @@
+---
+id: 6601ab2809898f57591f2f7f
+title: Step 75
+challengeType: 20
+dashedName: step-75
+---
+
+# --description--
+
+Now, modify the assignments of `v1` and `v2`. Turn them into `R3Vector` instances and pass `z=1` and `z=2` to `v1` and `v2`, respectively.
+
+# --hints--
+
+You should modify the assignment of `v1` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R3Vector(x=2, y=3, z=1)")`)) })
+```
+
+You should modify the assignment of `v2` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=0.5, y=1.25, z=2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+--fcc-editable-region--
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
new file mode 100644
index 00000000000..6904f99b5e1
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
@@ -0,0 +1,113 @@
+---
+id: 6601ac48a2ee6b59e6a5060d
+title: Step 76
+challengeType: 20
+dashedName: step-76
+---
+
+# --description--
+
+Call `cross()` on `v1` and pass `v2` as the argument. Assign this call to a new variable `v6`.
+
+# --hints--
+
+You should declare a variable named `v6` and assign it a call to the `cross()` method on `v1` passing it `v2` as the `argument`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v6").is_equivalent("v6 = v1.cross(v2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
new file mode 100644
index 00000000000..47d13a7bd4d
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
@@ -0,0 +1,210 @@
+---
+id: 6601ad0fe415985a5c83f3cc
+title: Step 77
+challengeType: 20
+dashedName: step-77
+---
+
+# --description--
+
+As a final step, call the `print` function and pass it the f-string `f'v1 x v2 = {v6}'` to see the output of the dot product.
+
+With that, you have completed the vector space project. Well done!
+
+# --hints--
+
+You should print `f'v1 x v2 = {v6}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 x v2 = {v6}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+print(f'v1 x v2 = {v6}')
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
new file mode 100644
index 00000000000..d25b1a4c723
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
@@ -0,0 +1,53 @@
+---
+id: 6659875502b6d7765498f324
+title: Step 26
+challengeType: 20
+dashedName: step-26
+---
+
+# --description--
+
+Use f-strings to modify your `print` calls so that they result in the output `v1 = (2, 3)` and `v2 = (2, 2, 3)`, respectively.
+
+# --hints--
+
+You should use an f-string to interpolate `v1` and generate the output `v1 = (2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}')")`)) })
+```
+
+You should use an f-string to interpolate `v2` and generate the output `v2 = (2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
new file mode 100644
index 00000000000..bc5ffa5f75d
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
@@ -0,0 +1,51 @@
+---
+id: 66680ddfd0f8c76782923cb0
+title: Step 22
+challengeType: 20
+dashedName: step-22
+---
+
+# --description--
+
+The `norm()` method is returning the correct values, but there's still something you can improve: readability.
+
+The `vars()` built-in function takes an object as its argument and returns the `__dict__` attribute of that object.
+
+Instead of directly accessing the `__dict__` attribute of `self`, modify the `norm` method to use the `vars()` function.
+
+# --hints--
+
+You should modify your `norm` method to use `vars(self)` instead of `self.__dict__`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in vars(self).values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
new file mode 100644
index 00000000000..e0f1c196265
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
@@ -0,0 +1,61 @@
+---
+id: 66682150151af29efec9727d
+title: Step 33
+challengeType: 20
+dashedName: step-33
+---
+
+# --description--
+
+The `__getattribute__` method is called under the hood any time you try to access an instance attribute. If the attribute is not found at the instance level, the method will search for it at the class level, and eventually in parent classes.
+
+Inside your class, define a `__getattribute__` method with two parameters, `self` and `attr`, and make it return the string `'calling __getattribute__'`. You'll override momentarily the default implementation just to see how the attribute access works.
+
+# --hints--
+
+You should define a method named `__getattribute__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_args("self, attr")`)) })
+```
+
+Your `__getattribute__` method should return the string `'calling __getattribute__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_return("'calling __getattribute__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
new file mode 100644
index 00000000000..948a541cb76
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
@@ -0,0 +1,61 @@
+---
+id: 666826f258fda1ab3396a509
+title: Step 34
+challengeType: 20
+dashedName: step-34
+---
+
+# --description--
+
+Now, print the result of accessing the `x` attribute of `v1` both with the dot operator and the `getattr()` built-in function.
+
+You will see that `__getattribute__` is called in both cases.
+
+# --hints--
+
+You should print the `x` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.x)") and n.has_call("print(getattr(v1, 'x'))")) or n.has_call("print(v1.x, getattr(v1, 'x'))") or n.has_call("print(getattr(v1, 'x'), v1.x)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
new file mode 100644
index 00000000000..8c3a650010b
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
@@ -0,0 +1,69 @@
+---
+id: 666827a6fd0dbaafe8330ea6
+title: Step 35
+challengeType: 20
+dashedName: step-35
+---
+
+# --description--
+
+`__getattr__` is another special method that plays a role in accessing attributes.
+
+The default implementation of `__getattribute__` is to raise an `AttributeError` when the requested attribute is not an instance attribute or it is not present in the class tree.
+
+In that case, `__getattr__` is called if defined by the class. You can consider it as a sort of fallback when the usual attribute accessing procedure fails.
+
+Turn the `__getattribute__` method into `__getattr__` and modify the string returned by the method into `'calling __getattr__'`.
+
+# --hints--
+
+You should define a method named `__getattr__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_args("self, attr")`)) })
+```
+
+Your `__getattr__` method should return the string `'calling __getattr__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_return("'calling __getattr__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+print(v1.x)
+print(getattr(v1, 'x'))
+
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
new file mode 100644
index 00000000000..598c9822428
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
@@ -0,0 +1,62 @@
+---
+id: 666832e427d70bc5219dc62a
+title: Step 36
+challengeType: 20
+dashedName: step-36
+---
+
+# --description--
+
+As you can see from the output, although you defined `__getattr__` in your class, this method is not called yet. This happens because the default attribute access occurs through `__getattribute__`. Therefore, you can see the attribute value printed on the terminal.
+
+Now modify the last two lines of code to access the `z` attribute of `v1` in both your `print()` calls. This time, you are going to access an attribute that `v1` does not have. As a result, `__getattribute__` will raise an error and `__getattr__` will be called.
+
+# --hints--
+
+You should modify your code to print the `z` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.z)") and n.has_call("print(getattr(v1, 'z'))")) or n.has_call("print(v1.z, getattr(v1, 'z'))") or n.has_call("print(getattr(v1, 'z'), v1.z)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+print(v1.x)
+print(getattr(v1, 'x'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
new file mode 100644
index 00000000000..3f18e7c657c
--- /dev/null
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
@@ -0,0 +1,75 @@
+---
+id: 6668374ed18b7fce10259cb3
+title: Step 37
+challengeType: 20
+dashedName: step-37
+---
+
+# --description--
+
+Now that you have an idea of how the attribute access work, remove the last two lines of your code together with the `__getattr__` method.
+
+Then, restore the `print()` calls you commented out before and delete the second argument from both of them.
+
+# --hints--
+
+You should not have a `__getattr__` method.
+
+```js
+({ test: () => assert.isFalse(runPython(`_Node(_code).find_class("R2Vector").has_function("__getattr__")`)) })
+```
+
+You should not have `print(v1.z)`and `print(getattr(v1, 'z'))` in your code.
+
+```js
+({ test: () => assert.isFalse(runPython(`
+n = _Node(_code)
+n.has_call("print(v1.z)") or n.has_call("print(getattr(v1, 'z'))")
+`)) })
+```
+
+You should restore the `print()` calls you commented out before and remove the second argument from both of them.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).has_call("print(f'v1 = {v1}')") and _Node(_code).has_call("print(f'v2 = {v2}')")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+print(v1.z)
+print(getattr(v1, 'z'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
index f84624b42de..e9870c4826a 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
@@ -1,6 +1,6 @@
---
id: 6553ed69ece88d29594748aa
-title: Step 50
+title: Step 52
challengeType: 20
dashedName: step-52
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
index bf46d6f32ca..36913664567 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
@@ -1,6 +1,6 @@
---
id: 6553efd6ada3f42aa2d75448
-title: Step 51
+title: Step 53
challengeType: 20
dashedName: step-53
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
index 2688363421c..bdc61a56deb 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
@@ -1,6 +1,6 @@
---
id: 6553f3fc92741c2bf8ded140
-title: Step 52
+title: Step 54
challengeType: 20
dashedName: step-54
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
index 16b2b7a8c78..c54923b4ea2 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
@@ -1,6 +1,6 @@
---
id: 6553f4f66099802c6ae94613
-title: Step 53
+title: Step 55
challengeType: 20
dashedName: step-55
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
index bcae9e4c2a5..92734e07289 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
@@ -1,6 +1,6 @@
---
id: 6553f6086add4b2cbb99fd78
-title: Step 54
+title: Step 56
challengeType: 20
dashedName: step-56
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
index 2f0fc79d3ff..1355edcf141 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
@@ -1,6 +1,6 @@
---
id: 6553f8c570f9982e013a8886
-title: Step 55
+title: Step 57
challengeType: 20
dashedName: step-57
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
index 51c7c51620d..5b984de7d3b 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
@@ -1,6 +1,6 @@
---
id: 655491bd5b98b813fa5bedca
-title: Step 56
+title: Step 58
challengeType: 20
dashedName: step-58
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
index 64bef622b35..b6a7f0aa9c6 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
@@ -1,6 +1,6 @@
---
id: 6554930320d70414e7b6acc6
-title: Step 57
+title: Step 59
challengeType: 20
dashedName: step-59
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
index c2b67a816d2..ab8d95e137d 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
@@ -1,6 +1,6 @@
---
id: 65549561463f0016876e852c
-title: Step 58
+title: Step 60
challengeType: 20
dashedName: step-60
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
index 5d4a37a2fe9..839352832e3 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
@@ -1,6 +1,6 @@
---
id: 65549f90cf78131c96ebcf28
-title: Step 59
+title: Step 61
challengeType: 20
dashedName: step-61
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
index 4c05b0584c4..01181c37df7 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
@@ -1,6 +1,6 @@
---
id: 6554a334a40edb1fb4eff827
-title: Step 60
+title: Step 62
challengeType: 20
dashedName: step-62
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
index 63e5be90540..921879d9acc 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
@@ -1,6 +1,6 @@
---
id: 6554a49a4f782f208abcc87e
-title: Step 61
+title: Step 63
challengeType: 20
dashedName: step-63
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
index c8c045af50c..139a3fea8db 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
@@ -1,6 +1,6 @@
---
id: 6554a57ec0a2c52106e7ee50
-title: Step 62
+title: Step 64
challengeType: 20
dashedName: step-64
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
index f8aec7c6f01..b1c21af09e5 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
@@ -1,6 +1,6 @@
---
id: 6554a88d5af937226f4a9121
-title: Step 63
+title: Step 65
challengeType: 20
dashedName: step-65
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
index 9f67d3e0905..2bff453ec4b 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
@@ -1,6 +1,6 @@
---
id: 6554ac937a49be2701af4f2f
-title: Step 64
+title: Step 66
challengeType: 20
dashedName: step-66
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
index d9b8dbfc283..4c7bb7ab462 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
@@ -1,6 +1,6 @@
---
id: 6554ad2463b8892748f8efdd
-title: Step 65
+title: Step 67
challengeType: 20
dashedName: step-67
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
index e2ed67b3ab6..1eeeb3697b1 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
@@ -1,6 +1,6 @@
---
id: 6554d0332949b133a0b35eaa
-title: Step 66
+title: Step 68
challengeType: 20
dashedName: step-68
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
index 863de41bbc0..5f093f3df2c 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
@@ -1,6 +1,6 @@
---
id: 6554d15c8acb5f34499ad789
-title: Step 67
+title: Step 69
challengeType: 20
dashedName: step-69
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
index c24fa10d6c6..65ac8f3f6c4 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
@@ -1,6 +1,6 @@
---
id: 6554d25dc5ceaa354307a77e
-title: Step 68
+title: Step 70
challengeType: 20
dashedName: step-70
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
index 076f1a41e91..2df3eb6fceb 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
@@ -1,6 +1,6 @@
---
id: 6554de295ade563a069936a1
-title: Step 69
+title: Step 71
challengeType: 20
dashedName: step-71
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
index 9793f1023c3..5e52b90279e 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
@@ -1,6 +1,6 @@
---
id: 6554dfce1683be3c0c9609a6
-title: Step 70
+title: Step 72
challengeType: 20
dashedName: step-72
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
index 9454a27cb5e..02e14d9019c 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
@@ -1,6 +1,6 @@
---
id: 6554e0adc7bb193cbfdb36d5
-title: Step 71
+title: Step 73
challengeType: 20
dashedName: step-73
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
index 182346eca82..7f91537aead 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
@@ -1,6 +1,6 @@
---
id: 6554e2ee23bfd93f2c83640f
-title: Step 72
+title: Step 74
challengeType: 20
dashedName: step-74
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
index 48ececac1ab..d5bdb7ff5d1 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
@@ -1,6 +1,6 @@
---
id: 6554e343caea913ffba7bec6
-title: Step 73
+title: Step 75
challengeType: 20
dashedName: step-75
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
index 368cf69b225..a80c318bd1d 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
@@ -1,6 +1,6 @@
---
id: 655516e410b8e30fb4fb64e8
-title: Step 74
+title: Step 76
challengeType: 20
dashedName: step-76
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
index 22de7de4fa0..82e1790a7d8 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
@@ -1,6 +1,6 @@
---
id: 65551a628bcb7e121e32d04b
-title: Step 77
+title: Step 79
challengeType: 20
dashedName: step-79
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
index 7f0ec8191b3..8603eb7e6d8 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
@@ -1,6 +1,6 @@
---
id: 6555201d9b7fc917399f9f0b
-title: Step 78
+title: Step 80
challengeType: 20
dashedName: step-80
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
index 01549558a4b..5c6c8181984 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
@@ -1,6 +1,6 @@
---
id: 655520c20cb1e6177b0641d6
-title: Step 79
+title: Step 81
challengeType: 20
dashedName: step-81
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
index cc4f4eacee1..db091c232cc 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
@@ -1,6 +1,6 @@
---
id: 655522883e66f618e03a9411
-title: Step 80
+title: Step 82
challengeType: 20
dashedName: step-82
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
index cd29fc36bb4..9588d739f44 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
@@ -1,6 +1,6 @@
---
id: 6555231eac4d9f19bd3d44b5
-title: Step 81
+title: Step 83
challengeType: 20
dashedName: step-83
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
index c02b037de64..b8c910a3aa5 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
@@ -1,6 +1,6 @@
---
id: 65552a111190e11f0963949e
-title: Step 82
+title: Step 84
challengeType: 20
dashedName: step-84
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
index eb0c5d14c63..28da95df2b0 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
@@ -1,6 +1,6 @@
---
id: 65552a9593755e1fb2f5ab50
-title: Step 83
+title: Step 85
challengeType: 20
dashedName: step-85
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
index aa1a050cf04..4fcaff7b89c 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
@@ -1,6 +1,6 @@
---
id: 65552b14e803731fe3c1e4ca
-title: Step 84
+title: Step 86
challengeType: 20
dashedName: step-86
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
index 3b6cc0579a3..f8ea2a67964 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
@@ -1,6 +1,6 @@
---
id: 65553159615a8123b190ee43
-title: Step 85
+title: Step 87
challengeType: 20
dashedName: step-87
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
index 1e3ad3dfb8a..6799724af14 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
@@ -1,6 +1,6 @@
---
id: 6555d6e12c95701172b55709
-title: Step 75
+title: Step 77
challengeType: 20
dashedName: step-77
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
index f3c3b93e0c6..97049b3b537 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
@@ -1,6 +1,6 @@
---
id: 6555d8b0b3d20b128bdadd37
-title: Step 76
+title: Step 78
challengeType: 20
dashedName: step-78
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
index 866b80d387b..d310105bfe1 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
@@ -1,6 +1,6 @@
---
id: 6555db4a7b788e15795674e5
-title: Step 87
+title: Step 89
challengeType: 20
dashedName: step-89
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
index 2cf86f2dd96..3a91139cf33 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
@@ -1,6 +1,6 @@
---
id: 6555df0c81300b175308557d
-title: Step 88
+title: Step 90
challengeType: 20
dashedName: step-90
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
index 959034b7875..bc5788b45f8 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
@@ -1,6 +1,6 @@
---
id: 6555e1bfcd374e18c6be8e58
-title: Step 89
+title: Step 91
challengeType: 20
dashedName: step-91
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
index 791d9bdbd6d..4d7848b4be9 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
@@ -1,6 +1,6 @@
---
id: 6555e3f387381a19d5e00333
-title: Step 90
+title: Step 92
challengeType: 20
dashedName: step-92
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
index 20f69b6bd24..e895a41b321 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
@@ -1,6 +1,6 @@
---
id: 6555e43e783ed31a0532b1b2
-title: Step 91
+title: Step 93
challengeType: 20
dashedName: step-93
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
index 9acf44cfdc2..f878bb6c12b 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
@@ -1,6 +1,6 @@
---
id: 6555e547c18a2b1a7b795bd8
-title: Step 93
+title: Step 95
challengeType: 20
dashedName: step-95
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
index 312d322e32f..9b3df4758a0 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
@@ -1,6 +1,6 @@
---
id: 6555e5991af57d1ae0e35f0a
-title: Step 94
+title: Step 96
challengeType: 20
dashedName: step-96
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
index 3493c823d5d..1bb2f8f1567 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
@@ -1,6 +1,6 @@
---
id: 65a450e8fb2c9d75c7378d28
-title: Step 86
+title: Step 88
challengeType: 20
dashedName: step-88
---
diff --git a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
index a15a486b7eb..29a960e8277 100644
--- a/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
+++ b/curriculum/challenges/korean/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
@@ -1,6 +1,6 @@
---
id: 65a51c9e000b660122b8b29e
-title: Step 92
+title: Step 94
challengeType: 20
dashedName: step-94
---
diff --git a/curriculum/challenges/korean/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md b/curriculum/challenges/korean/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
deleted file mode 100644
index 632abe728dd..00000000000
--- a/curriculum/challenges/korean/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
+++ /dev/null
@@ -1,344 +0,0 @@
----
-id: 62aa1fed3d4e873366ff3131
-title: Step 150
-challengeType: 0
-dashedName: step-150
----
-
-# --description--
-
-In your `attack` function, below the `health` variable, create an `if` statement. Set the condition to call the `isMonsterHit` function.
-
-# --hints--
-
-You should add an `if` statement which calls `isMonsterHit` in the condition.
-
-```js
-assert.match(attack.toString(), /if\s*\(\s*isMonsterHit\s*\(\s*\)/)
-```
-
-# --seed--
-
-## --seed-contents--
-
-```html
-
-
-
-
-
-
+
+Within the `Vector` class, create an `__init__` method and give it three parameters, `self`, `x`, and `y`.
+
+# --hints--
+
+You should define an `__init__` method inside the `Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").has_function("__init__")`)) })
+```
+
+Your `__init__` method should take three parameters: `self`, `x`, and `y`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").find_function("__init__").has_args("self, x, y")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ pass
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
new file mode 100644
index 00000000000..62ab349a8db
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
@@ -0,0 +1,38 @@
+---
+id: 65f055b9190fc41ca35549b8
+title: Step 3
+challengeType: 20
+dashedName: step-3
+---
+
+# --description--
+
+Python offers various methods that include both a leading and trailing double underscore in their names. You may already be familiar with some, such as `__init__` and `__str__`. These methods, which follow the `__
+
+So far, you created a 2-dimensional vector. You want to be able to represent vectors with a different number of dimensions without rewriting the necessary code for each specific case. For that, you will use inheritance.
+
+Start by renaming the `Vector` class into `R2Vector` to specify that this class is going to deal with 2-dimensional vectors. Remember to modify the instantiation of `v1`, too.
+
+# --hints--
+
+You should rename the `Vector` class into `R2Vector`. Remember to modify the instantiation of `v1`, too.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+v1 = Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
new file mode 100644
index 00000000000..e26a20b0730
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
@@ -0,0 +1,70 @@
+---
+id: 65f40051d6b09a139f253e8e
+title: Step 12
+challengeType: 20
+dashedName: step-12
+---
+
+# --description--
+
+Inheritance enables you to define a class from an existing one. The new class, called child, inherits all the methods and properties of the existing class, called parent.
+
+```py
+class Tree:
+ def sprout(self):
+ print('Making new leaves!')
+
+class Oak(Tree):
+ pass
+
+Oak().sprout() # Output: Making new leaves!
+```
+
+In the example above, the child class `Oak` inherits from `Tree` and inherits the `sprout` method from the parent class `Tree`.
+
+Create a new class named `R3Vector` and follow the example above to make it inherit from the `R2Vector` class.
+
+# --hints--
+
+You should define a new class `R3Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R3Vector")
+ `))
+})
+```
+
+Your new class `R3Vector` should inherit from `R2Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").inherits_from("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
new file mode 100644
index 00000000000..c50cbefeb4a
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
@@ -0,0 +1,56 @@
+---
+id: 65f40401e6ef53173c04e27d
+title: Step 13
+challengeType: 20
+dashedName: step-13
+---
+
+# --description--
+
+Within your new class, declare an `__init__` method. Give it `self`, `x`, `y`, and `z` as the parameters.
+
+# --hints--
+
+You should define an `__init__` method inside your `R3Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").has_function("__init__")
+ `))
+})
+```
+
+Your `__init__` method should have four parameters `self`, `x`, `y`, and `z`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, x, y, z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
new file mode 100644
index 00000000000..cb7a33c0eb1
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
@@ -0,0 +1,49 @@
+---
+id: 65f407ea37ad6e181b90462e
+title: Step 14
+challengeType: 20
+dashedName: step-14
+---
+
+# --description--
+
+You could assign each `i` parameter to `self.i` as you did before. Although in this case you have few lines to repeat, one way to avoid this repetition is using the `super()` function. `super()` enables you to refer implicitly to the parent class: `super().__init__(x, y)` calls the `__init__` method of the parent class.
+
+Add a `super().__init__(x, y)` call to your `__init__` method.
+
+# --hints--
+
+You should have a `super().__init__(x, y)` call in your `__init__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_stmt("super().__init__(x, y)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
new file mode 100644
index 00000000000..caf708394fc
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
@@ -0,0 +1,47 @@
+---
+id: 65f40f8af784751c613d638a
+title: Step 15
+challengeType: 20
+dashedName: step-15
+---
+
+# --description--
+
+Now, you need to assign `z` to the `z` attribute of your `R3Vector` object.
+
+# --hints--
+
+You should assign `z` to `self.z` after the `super` call.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").is_ordered("super().__init__(x, y)", "self.z = z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
new file mode 100644
index 00000000000..68340ee6c11
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
@@ -0,0 +1,47 @@
+---
+id: 65f40fdb3579aa1ced28b2eb
+title: Step 16
+challengeType: 20
+dashedName: step-16
+---
+
+# --description--
+
+Create an `R3Vector` instance with `2`, `2`, and `3` as the values of `x`, `y`, and `z`, respectively. Assign the new instance to `v2`.
+
+# --hints--
+
+You should declare a variable `v2` and assign it `R3Vector(2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(2, 2, 3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
new file mode 100644
index 00000000000..06b727e3b29
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
@@ -0,0 +1,72 @@
+---
+id: 65f412c208c3791fee305acf
+title: Step 17
+challengeType: 20
+dashedName: step-17
+---
+
+# --description--
+
+In Python, you can enforce the use of keyword-only arguments by adding a `*` as an additional argument to the function or method signature. Modify both `__init__` methods by adding a `*` as the second parameter (after `self`). Every parameter placed after that will require the use of a keyword argument in the function/method call.
+
+This means that you need to modify the `super().__init__(x, y)` call, too. Do it by giving `x` the value `x`, and `y` the value `y`.
+
+Finally, modify the instantiation of `v1` and `v2` by using keyword arguments.
+
+# --hints--
+
+You should enforce keyword arguments by adding a `*` as the second parameter in both your `__init__` methods.
+
+```js
+({ test: () => {
+ assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__init__").has_args("self, *, x, y")`));
+ assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, *, x, y, z")`));
+} })
+```
+
+You should modify your `super.__init__(x, y)` call to use keyword arguments.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").find_body().is_equivalent("super().__init__(x=x, y=y)\\nself.z = z")`)) })
+```
+
+You should modify the assignment of `v1` to be `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R2Vector(x=2, y=3)")`)) })
+```
+
+You should modify the assignment of `v2` to be `R3Vector(x=2, y=2, z=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=2, y=2, z=3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+v2 = R3Vector(2, 2, 3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
new file mode 100644
index 00000000000..ef31cdd6194
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
@@ -0,0 +1,64 @@
+---
+id: 65f4148dea0f802040225e0c
+title: Step 18
+challengeType: 20
+dashedName: step-18
+---
+
+# --description--
+
+Remove the existing `print` calls. Then, as you did before for `v1`, print `v2` and the value returned by `v2.norm()`.
+
+# --hints--
+
+You should not have `print(v1)` and `print(v1.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1.norm())")`));
+ }
+})
+```
+
+You should print `v2` and `v2.norm()`.
+
+```js
+({
+ test: () => {
+ assert(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+print(v1.norm())
+print(v1)
+
+v2 = R3Vector(x=2, y=2, z=3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
new file mode 100644
index 00000000000..1a83f17e994
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
@@ -0,0 +1,64 @@
+---
+id: 65f4520e363e2642f8112e33
+title: Step 19
+challengeType: 20
+dashedName: step-19
+---
+
+# --description--
+
+As you can see, something is not quite right. The `norm` and `__str__` methods inherited from `R2Vector` cannot adapt to a 3-dimensional vector. Their implementation has to be more flexible.
+
+Every object in Python has a special attribute named `__dict__`, which is a dictionary that stores the object attributes.
+
+Remove the existing `print` calls. Then, print the `__dict__` attribute of your `v1` and `v2` vectors to see what they look like.
+
+# --hints--
+
+You should not have `print(v2)` and `print(v2.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+You should print the `__dict__` attribute of `v1` and `v2`.
+
+```js
+({ test: () => assert(runPython(`
+(_Node(_code).has_call("print(v1.__dict__)") and _Node(_code).has_call("print(v2.__dict__)")) or _Node(_code).has_call("print(v1.__dict__, v2.__dict__)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v2.norm())
+print(v2)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
new file mode 100644
index 00000000000..2a2c8f28376
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
@@ -0,0 +1,49 @@
+---
+id: 65f4535bbdb28d436ff3ddc9
+title: Step 20
+challengeType: 20
+dashedName: step-20
+---
+
+# --description--
+
+As you can see from the output, `__dict__` contains the values of your instance attributes. Instead of explicitly adding the squares of `self.x` and `self.y`, you are going to iterate over the values stored in `__dict__` to calculate the value of the norm.
+
+Within the `norm` method body, replace the content of the parentheses with a generator expression that elevates each value `val` in `self.__dict__.values()` to the power of `2`. Also, pass that generator expression as the argument to the `sum` function, so that all the squares are added together before calculating the square root.
+
+# --hints--
+
+You should return `sum(val**2 for val in self.__dict__.values())**0.5` from `norm()` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in self.__dict__.values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
new file mode 100644
index 00000000000..bbb82436c52
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
@@ -0,0 +1,53 @@
+---
+id: 65f870003444fb1a2ad171f2
+title: Step 21
+challengeType: 20
+dashedName: step-21
+---
+
+# --description--
+
+Modify the two `print` calls to print the norm of your vectors and verify that the `norm()` method works fine.
+
+# --hints--
+
+You should print `v1.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1.norm())")`)) })
+```
+
+You should print `v2.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v2.norm())")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
new file mode 100644
index 00000000000..22e3cab792e
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
@@ -0,0 +1,61 @@
+---
+id: 65f8709620b2ce1a62608f5a
+title: Step 23
+challengeType: 20
+dashedName: step-23
+---
+
+# --description--
+
+When you need to dynamically access some attributes starting from a string input, the built-in `getattr()` function is what you need. It takes an object as its first argument, and a string containing the attribute name as its second attribute.
+
+Start to fix the `__str__` method by replacing the string returned by `__str__()` with a generator expression that iterates through the object attributes and calls `getattr()` for each attribute `i`.
+
+# --hints--
+
+You should return a generator expression that iterates over `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_iters()[0].is_equivalent("vars(self)")`)) })
+```
+
+You should return a generator expression that uses `i` as the iteration variable.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_targets()[0].is_equivalent("i")`)) })
+```
+
+You should return a generator expression that calls `getattr(self, i)` for each item `i` in `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_expr().is_equivalent("getattr(self, i)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
new file mode 100644
index 00000000000..668bd89de56
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
@@ -0,0 +1,47 @@
+---
+id: 65f8720685ec351abef26740
+title: Step 24
+challengeType: 20
+dashedName: step-24
+---
+
+# --description--
+
+To obtain a proper string representation, call the `tuple()` constructor and pass it the generator expression you wrote in the previous step as the argument.
+
+# --hints--
+
+You should pass the expression returned by the `__str__` method to the `tuple()` constructor.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("tuple(getattr(self, i) for i in vars(self))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return (getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
new file mode 100644
index 00000000000..789f37ee6fe
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
@@ -0,0 +1,47 @@
+---
+id: 65f872a0fe6aa21b456ad4fe
+title: Step 25
+challengeType: 20
+dashedName: step-25
+---
+
+# --description--
+
+Finally, pass the `tuple()` call as the argument to the `str()` function.
+
+# --hints--
+
+You should pass the `tuple()` call you are currently returning from the `__str__` method to the `str()` function.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("str(tuple(getattr(self, i) for i in vars(self)))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return tuple(getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
new file mode 100644
index 00000000000..6a2c44baef5
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
@@ -0,0 +1,56 @@
+---
+id: 65f8749b13774b1d2e4a7fba
+title: Step 27
+challengeType: 20
+dashedName: step-27
+---
+
+# --description--
+
+While the `__str__` method returns a human-readable string representation of an object, the `__repr__` method is supposed to return the string needed to instantiate the object.
+
+Add a `__repr__` method with a `self` parameter within the `R2Vector` class.
+
+# --hints--
+
+Your `R2Vector` class should have a `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__repr__")`)) })
+```
+
+Your `__repr__` method should have a `self` parameter.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_args("self")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
new file mode 100644
index 00000000000..7f5a3e0f9c9
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
@@ -0,0 +1,74 @@
+---
+id: 65f876d17832001e8e1abb05
+title: Step 28
+challengeType: 20
+dashedName: step-28
+---
+
+# --description--
+
+Declare a variable `arg_list`. Give it the value of a list comprehension that iterates over `key` and `val` for each key-value pair in `vars(self).items()` and computes the f-string `f'{key}={val}'` at each iteration.
+
+# --hints--
+
+You should declare a variable `arg_list`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_variable("arg_list")`)) })
+```
+
+You should assign a list comprehension that iterates over `vars(self).items()` to `arg_list`.
+
+```js
+({ test: () => runPython(`
+import ast
+var = _Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list")
+assert isinstance(var.tree.value, ast.ListComp), "Expected arg_list to be a list comprehension"
+assert (actual := var.find_comp_iters()[0].is_equivalent("vars(self).items()")), f"Expected vars(self).items(), got {actual}"
+`) })
+```
+
+The list comprehension assigned to `arg_list` should use `key` and `val` to iterate over `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_targets()[0].is_equivalent("key, val")
+`)) })
+```
+
+The list comprehension assigned to `arg_list` should compute the string `f'{key}={val}'` for each key-value pair in `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_expr().is_equivalent("f'{key}={val}'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
new file mode 100644
index 00000000000..0c56316394e
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
@@ -0,0 +1,50 @@
+---
+id: 65f93acbb514857003510e79
+title: Step 29
+challengeType: 20
+dashedName: step-29
+---
+
+# --description--
+
+Declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+# --hints--
+
+You should declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("args").is_equivalent("args = ', '.join(arg_list)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
new file mode 100644
index 00000000000..e826611fa57
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
@@ -0,0 +1,52 @@
+---
+id: 65f93b67169a9c703264458a
+title: Step 30
+challengeType: 20
+dashedName: step-30
+---
+
+# --description--
+
+Since the method should return the string to instantiate the object for `R2Vector` as well as `R3Vector` when inherited, you cannot build the string specifying the class name.
+
+You can access the name of a class with `__class__.__name__`. Add a `return` statement to the `__repr__` method and return the string necessary to instantiate the object.
+
+# --hints--
+
+You should use `__class__.__name__` to build the f-string needed to instantiate a vector object and return it from the `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_return("f'{self.__class__.__name__}({args})'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
new file mode 100644
index 00000000000..13682539c2c
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
@@ -0,0 +1,57 @@
+---
+id: 65f93d4647ce2670dc6f095c
+title: Step 31
+challengeType: 20
+dashedName: step-31
+---
+
+# --description--
+
+The `__repr__` method is called under the hood by the `repr` function. Verify that `__repr__` works properly by adding `f'\nrepr = {repr(v1)}'` and `f'\nrepr = {repr(v2)}'` as the second argument to your first and second `print` calls, respectively.
+
+# --hints--
+
+You should add `f'\nrepr = {repr(v1)}'` as the second argument to your `print(f'v1 = {v1}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}', f'\\\\nrepr = {repr(v1)}')")`)) })
+```
+
+You should add `f'\nrepr = {repr(v2)}'` as the second argument to your `print(f'v2 = {v2}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}', f'\\\\nrepr = {repr(v2)}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
new file mode 100644
index 00000000000..a25da243ba9
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
@@ -0,0 +1,56 @@
+---
+id: 65f93e54a9121571dcdd3e79
+title: Step 32
+challengeType: 20
+dashedName: step-32
+---
+
+# --description--
+
+The output is correct, `repr` is giving you the string required to instantiate the objects.
+
+Now comment out both your `print` calls.
+
+# --hints--
+
+You should comment out both your `print()` calls.
+
+```js
+({ test: () => {
+ assert.match(code, /#\s*print\s*\(\s*f('|")v1 = \{\s*v1\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v1\s*\)\s*\}\2\s*\)/);
+ assert.match(code, /#\s*print\s*\(\s*f('|")v2 = \{\s*v2\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v2\s*\)\s*\}\2\s*\)/);
+} })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
new file mode 100644
index 00000000000..127f701ba31
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
@@ -0,0 +1,62 @@
+---
+id: 65f9b17a638f0d0dcce8c354
+title: Step 38
+challengeType: 20
+dashedName: step-38
+---
+
+# --description--
+
+To create a vector space, you need to define how vectors should behave in several cases. Vectors can be added, forming a new vector.
+
+The special method `__add__` can be implemented to override what happens by default when two objects are added together using the `+` operator.
+
+Right now, trying to add two instances of `R2Vector` or `R3Vector` would raise an exception. Create an empty `__add__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define an `__add__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__add__")`)) })
+```
+
+Your `__add__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
new file mode 100644
index 00000000000..f90c14fe57b
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b486989cb90ff3e77ac8
+title: Step 39
+challengeType: 20
+dashedName: step-39
+---
+
+# --description--
+
+The `other` parameter of your `__add__` method represents the operand placed at the right side of the `+` operator in an addition operation.
+
+You want to verify that the right-hand operand is not an object of the same class as the left-hand operand (i.e. `self`). Create an `if` statement that verifies that by checking the type of the operands.
+
+# --hints--
+
+You should create an `if` statement that checks if `type(self)` and `type(other)` are different.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
new file mode 100644
index 00000000000..1fa83e0f9aa
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b9710cca621244d3bde1
+title: Step 40
+challengeType: 20
+dashedName: step-40
+---
+
+# --description--
+
+In Python, `NotImplemented` is a special value used to indicate that an operation is not implemented for a specific case.
+
+`NotImplemented` does not raise an exception immediately. Instead, it signals to ask to the other operand how to perform the operation. If the request cannot be satisfied, a `TypeError` is returned by default.
+
+Because you want to be able to sum two vectors only if they belong to the same class, return `NotImplemented` from the `if` statement you created in the previous step.
+
+# --hints--
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
new file mode 100644
index 00000000000..9df77e46895
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
@@ -0,0 +1,58 @@
+---
+id: 65f9bb7c0d524612b2a88a4b
+title: Step 41
+challengeType: 20
+dashedName: step-41
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_stmt("kwargs = {}")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
new file mode 100644
index 00000000000..f5d28e43bd6
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
@@ -0,0 +1,92 @@
+---
+id: 65f9bc10a9fb1612e066e9e8
+title: Step 42
+challengeType: 20
+dashedName: step-42
+---
+
+# --description--
+
+When adding two vectors, each component of one vector is added to the same component of the other vector. For example, adding `(1, 2)` and `(2, 4)` generates a third vector `(3, 6)`, where `3` is the sum of `1` and `2` and `6` is the sum of `2` and `4`.
+
+The `kwargs` dictionary will contain the key-value pairs needed to instantiate a new vector of the same class of the two vectors added together.
+
+Turn the empty dictionary into a dictionary comprehension that iterates through `vars(self)` and for each key (`i`) creates a key-value pair, where the key is the same key of the current iteration and its value is the sum of the values of the `i` attributes of the two operands.
+
+# --hints--
+
+You should turn the empty dictionary assigned to `kwargs` into a dictionary comprehension that iterates over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_iters()[0].is_equivalent("vars(self)")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_key().is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the sum of the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i` in `vars(self)`. Use the `getattr()` function for that.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) + getattr(other, i)") or node.is_equivalent("getattr(other, i) + getattr(self, i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
new file mode 100644
index 00000000000..d1cd1755778
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
@@ -0,0 +1,70 @@
+---
+id: 65f9c2c2006feb1428ad2d4c
+title: Step 43
+challengeType: 20
+dashedName: step-43
+---
+
+# --description--
+
+You can unpack a dictionary into keyword arguments by using the `**` operator:
+
+```py
+def spam(a, b):
+ return a + b
+
+my_dict = {a: 11, b: 4}
+
+spam(**my_dict) # 15
+```
+
+Return an instance of the current class by using `__class__` and passing `**kwargs` as the argument.
+
+# --hints--
+
+You should return `self.__class__(**kwargs)` from the `__add__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
new file mode 100644
index 00000000000..689ab778fe5
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
@@ -0,0 +1,90 @@
+---
+id: 65f9cb678070ca1668898c70
+title: Step 44
+challengeType: 20
+dashedName: step-44
+---
+
+# --description--
+
+In the same way `__add__` is called under the hood when two objects are added together, the `__sub__` method is called implicitly in case of subtraction.
+
+Now, define an empty `__sub__` method and give two parameters: `self`, and `other`. Inside your new method, create an if statement to check if `self` and `other` do not belong to the same class and return `NotImplemented`, as you did previously.
+
+# --hints--
+
+You should define a `__sub__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__sub__")
+ `))
+})
+```
+
+Your `__sub__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_args("self, other")
+ `))
+})
+```
+
+You should create an `if` statement that checks if `self` and `other` does not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+ `))
+})
+```
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
new file mode 100644
index 00000000000..2d452d2413e
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
@@ -0,0 +1,89 @@
+---
+id: 65f9dd6e5a08af19c196c2df
+title: Step 45
+challengeType: 20
+dashedName: step-45
+---
+
+# --description--
+
+The vector resulting from the subtraction of one vector from another is obtained by calculating the difference of each of their components. For example, subtracting `(2, 4)` from `(7, 3)` generates a third vector `(5, -1)`, where `5` is the difference between `7` and `2` and `-1` is the difference between `3` and `4`.
+
+As you did before inside the `__add__` method, declare a `kwargs` variable after the `if` statement. Assign it a dictionary comprehension that iterates through the object attributes and creates a key-value pair for each key `i`, where the key is the same key as the current iteration and its value is the difference between the values of the `i` attributes of two operands.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it a dictionary comprehension that iterates over the object attributes.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_iters()[0]
+node.is_equivalent("vars(self)") or node.is_equivalent("self.__dict__")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over the object attributes.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_key().is_equivalent("i")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the difference between the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i`.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) - getattr(other, i)") or node.is_equivalent("self.__getattribute__(i) - other.__getattribute__(i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
new file mode 100644
index 00000000000..095bce27c7c
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
@@ -0,0 +1,65 @@
+---
+id: 65f9dfd2e75e291a38695f13
+title: Step 46
+challengeType: 20
+dashedName: step-46
+---
+
+# --description--
+
+Finally, return a new vector object. Use `__class__` and unpack `kwargs` to instantiate the new vector.
+
+# --hints--
+
+You should return a new vector using `__class__` and unpacking `kwargs` from the `__sub__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
new file mode 100644
index 00000000000..c5cb7742541
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
@@ -0,0 +1,67 @@
+---
+id: 65f9e0a578b22c1a736f3d82
+title: Step 47
+challengeType: 20
+dashedName: step-47
+---
+
+# --description--
+
+Modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+# --hints--
+
+You should modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v2 = R2Vector(x=0.5, y=1.25)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
new file mode 100644
index 00000000000..1d277671da4
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
@@ -0,0 +1,67 @@
+---
+id: 65fa8d5cf0ef3b141010f5d8
+title: Step 48
+challengeType: 20
+dashedName: step-48
+---
+
+# --description--
+
+It's time to verify that the addition and subtraction operations work as expected. Declare another variable `v3` and assign it the sum of `v1` plus `v2`.
+
+# --hints--
+
+You should declare a variable `v3` and assign it the sum of `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v3 = v1 + v2") or _Node(_code).has_stmt("v3 = v2 + v1")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
new file mode 100644
index 00000000000..87ddac5ea5f
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
@@ -0,0 +1,64 @@
+---
+id: 65fa8df56a0e2c149b4d24fe
+title: Step 49
+challengeType: 20
+dashedName: step-49
+---
+
+# --description--
+
+Next, check the new vector by printing the following f-string `f'v1 + v2 = {v3}'`.
+
+# --hints--
+
+You should print `f'v1 + v2 = {v3}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 + v2 = {v3}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
new file mode 100644
index 00000000000..e526a9cd4cc
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
@@ -0,0 +1,77 @@
+---
+id: 65fa9402d1fb5516aa42159d
+title: Step 50
+challengeType: 20
+dashedName: step-50
+---
+
+# --description--
+
+Feel free to modify `v3` so that it sums an `R2Vector` instance with an object of a different type, such as an integer or a string. You will be able to see a `TypeError` message printed on the console.
+
+Then, restore the original line and create a new variable `v4`. Assign the difference between `v1` and `v2` to your new variable and print the result following the same structure as the previous f-string.
+
+# --hints--
+
+You should declare a variable `v4` and assign it the difference between `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v4 = v1 - v2")
+ `))
+})
+```
+
+You should print `f'v1 - v2 = {v4}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 - v2 = {v4}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
new file mode 100644
index 00000000000..d2df1c3038d
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
@@ -0,0 +1,85 @@
+---
+id: 65fa9e1b6c6db919385359ec
+title: Step 51
+challengeType: 20
+dashedName: step-51
+---
+
+# --description--
+
+The special method `__mul__` can be implemented to specify what should happen when the current instance is multiplied by another object.
+
+Create an empty `__mul__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `__mul__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__mul__")
+ `))
+})
+```
+
+Your `__mul__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__mul__").has_args("self, other")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
new file mode 100644
index 00000000000..0a18b8b69d1
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
@@ -0,0 +1,94 @@
+---
+id: 65faaed8f7a9772f023ea816
+title: Step 52
+challengeType: 20
+dashedName: step-52
+---
+
+# --description--
+
+Vectors can be multiplied by a *scalar*, i.e. a number that multiplies each single component. The result of scalar multiplication is a vector with the same orientation as the original vector but a different magnitude.
+
+Implement the scalar multiplication by checking if `other` is either an `int` or a `float`. If it is, return a new instance of the current class that has each component of the starting vector multiplied by `other`. This will be the vector resulting from the scalar multiplication.
+
+Make sure the methods can be applied to compute the scalar multiplication of vectors with any number of dimensions.
+
+# --hints--
+
+Your method should return a new instance of the current class only when the type of `other` is either `int` or `float`.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=0, y=0)
+v2 = R3Vector(x=0, y=0, z=0)
+types = ["", True, [], {}]
+assert all((v1 * i) is None for i in types)
+types = [1, 1.0]
+assert all(type(v1 * i) is type(v1) for i in types)
+assert all(type(v2 * i) is type(v2) for i in types)
+`) })
+```
+
+The vector resulting from the scalar multiplication should have each component of the starting vector multiplied by the scalar.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=1, y=1.5)
+v2 = R3Vector(x=2.2, y=3, z=-1)
+assert vars(v1 * 3) == vars(R2Vector(x=3, y=4.5))
+assert vars(v2 * (-2.0)) == vars(R3Vector(x=-4.4, y=-6.0, z=2.0))
+`) })
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
new file mode 100644
index 00000000000..bcf1d3d0b55
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
@@ -0,0 +1,79 @@
+---
+id: 65fc87e19930a503e5f05500
+title: Step 53
+challengeType: 20
+dashedName: step-53
+---
+
+# --description--
+
+A vector can be multiplied by another vector, too. This operation is called *dot product*, or *scalar product*.
+
+Create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+You are going to implement the dot product inside this block during the next step.
+
+# --hints--
+
+You should create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__mul__").find_ifs()[0].find_conditions()[1]
+node.is_equivalent("type(self) == type(other)") or node.is_equivalent("type(other) == type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
new file mode 100644
index 00000000000..c5edc6d9b45
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
@@ -0,0 +1,87 @@
+---
+id: 65fc899d77495504d6deeccc
+title: Step 54
+challengeType: 20
+dashedName: step-54
+---
+
+# --description--
+
+The scalar product between two vectors $\mathbf{a}$ and $\mathbf{b}$ is indicated as:
+
+\\( \mathbf{a} \cdot \mathbf{b} = a_1 \cdot b_1 + a_2 \cdot b_2 + \ldots + a_n \cdot b_n = \sum_{i=1}^{n} a_i \cdot b_i \\)
+
+Where each component of $\mathbf{a}$ is multiplied by the correspondent component of $\mathbf{b}$, and all the products are summed together, resulting in a number.
+
+Within the `elif` clause, implement the above formula to compute the result of a scalar product and return the result. Remember that your implementation must be valid for any vector, independently from the number of components, when the method is inherited.
+
+# --hints--
+
+You should implement the scalar product calculation and return the result inside the `elif` body of your `__mul__` method.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+v3 = R3Vector(x=2, y=3, z=1.5)
+v4 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1*v2 == 4.75 and v3*v4 == 7.0
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
new file mode 100644
index 00000000000..36b78391926
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
@@ -0,0 +1,78 @@
+---
+id: 65fc8e7c766ab1070213aadb
+title: Step 55
+challengeType: 20
+dashedName: step-55
+---
+
+# --description--
+
+In case `other` is not an integer, a floating point number, or another instance of the current class, no product can be computed.
+
+After the `elif` clause, return `NotImplemented`.
+
+# --hints--
+
+You should return `NotImplemented` after the `elif` clause.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__mul__").has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
new file mode 100644
index 00000000000..bf365bd4903
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
@@ -0,0 +1,82 @@
+---
+id: 65fc8fa7e7860407ab479bf0
+title: Step 56
+challengeType: 20
+dashedName: step-56
+---
+
+# --description--
+
+It's time to test the multiplication. Declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`. Then, call the `print` function and pass it the following f-string: `f'v1 * 3 = {v5}'`.
+
+# --hints--
+
+You should declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * 3")`)) })
+```
+
+You should print the f-string `f'v1 * 3 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * 3 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
new file mode 100644
index 00000000000..034109b8c53
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
@@ -0,0 +1,87 @@
+---
+id: 65fd681b20b7e45f55def415
+title: Step 57
+challengeType: 20
+dashedName: step-57
+---
+
+# --description--
+
+The scalar multiplication works fine. Now, modify the assignment of `v5` to be the dot product `v1 * v2`. Also, update the `print` call.
+
+Before doing that, feel free to experiment and multiply `v1` by an object of invalid type to see the error message printed on the console.
+
+
+# --hints--
+
+You should update the assignment of `v5` assigning it the scalar product `v1 * v2`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * v2")`)) })
+```
+
+You should update your `print` call to print the f-string `f'v1 * v2 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * v2 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * 3
+print(f'v1 * 3 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
new file mode 100644
index 00000000000..f6184775ca4
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9250db0d6b8198cf29ef
+title: Step 58
+challengeType: 20
+dashedName: step-58
+---
+
+# --description--
+
+The `__eq__` method can be implemented to specify what should happen in case the comparison operator (`==`) is used to compare an object with something else.
+
+Within the `R2Vector` class, create an `__eq__` method and give it two parameters: `self` and `other`.
+
+# --hints--
+
+You should define a `__eq__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__eq__")`)) })
+```
+
+Your `__eq__` method should take two parameters: `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
new file mode 100644
index 00000000000..5d2d8cfc678
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
@@ -0,0 +1,88 @@
+---
+id: 65fd95c23beef982af29004c
+title: Step 59
+challengeType: 20
+dashedName: step-59
+---
+
+# --description--
+
+You want to compare two vectors, only when they belong to the same class. For that create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented` in that case.
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
new file mode 100644
index 00000000000..c3bea995dc8
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
@@ -0,0 +1,91 @@
+---
+id: 65fd97f3c1b4c4839bdeb8d2
+title: Step 60
+challengeType: 20
+dashedName: step-60
+---
+
+# --description--
+
+To compare two vectors, you are going to check that each component of the first vector is equal to the same component of the second vector.
+
+After the `if` statement you created in the previous step, return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+# --hints--
+
+The `__eq__` method should return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1 == v2 and not v1 == v3 and v4 == v5 and not v5 == v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
new file mode 100644
index 00000000000..a7f5d701215
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
@@ -0,0 +1,102 @@
+---
+id: 65fd9aa649f6cc84631882a9
+title: Step 61
+challengeType: 20
+dashedName: step-61
+---
+
+# --description--
+
+The `__ne__` method is called under the hood when the `!=` operator is used. Define a `__ne__` method with two parameters `self` and `other`. From your new method, return the opposite of `self == other`.
+
+# --hints--
+
+You should define a `__ne__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ne__")`)) })
+```
+
+Your `__ne__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ne__").has_args("self, other")`)) })
+```
+
+The `__ne__` method should return `False` if each attribute of the current instance is equal to the same attribute of `other` and `True` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+not v1 != v2 and v1 != v3 and not v4 != v5 and v5 != v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
new file mode 100644
index 00000000000..c151f678d86
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
@@ -0,0 +1,86 @@
+---
+id: 65fd9c6e49d7cd8513ab1005
+title: Step 62
+challengeType: 20
+dashedName: step-62
+---
+
+# --description--
+
+At the end of your code, use the equality operator to compare `v1` and `R2Vector(x=2, y=3)` and print the result.
+
+# --hints--
+
+You should print the result of comparing `v1` and `R2Vector(x=2, y=3)` using the equality operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 == R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) == v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
new file mode 100644
index 00000000000..804d4947304
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9d6203afea85931094c9
+title: Step 63
+challengeType: 20
+dashedName: step-63
+---
+
+# --description--
+
+The comparison returns `True`, since the two vectors have the same components. Now, modify the argument of the `print` call you added in the previous step to use the inequality operator.
+
+# --hints--
+
+You should modify the `print` call you added in the previous step using the inequality operator to compare `v1` and `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) != v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 == R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
new file mode 100644
index 00000000000..9255b41f2c6
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
@@ -0,0 +1,97 @@
+---
+id: 65fd9e2c56ff19862dfb8cbb
+title: Step 64
+challengeType: 20
+dashedName: step-64
+---
+
+# --description--
+
+The `__lt__` method is called under the hood when the `<` operator is used to compare an object with something else.
+
+Add an empty `__lt__` method and give it two parameters: `self`, `other`.
+
+# --hints--
+
+You should define a `__lt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__lt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
new file mode 100644
index 00000000000..ee258ff8a2a
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
@@ -0,0 +1,100 @@
+---
+id: 65fdc3c8478ee70fc7966151
+title: Step 65
+challengeType: 20
+dashedName: step-65
+---
+
+# --description--
+
+In the same way you did before for the `__eq__` method, create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
new file mode 100644
index 00000000000..390babbb01f
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
@@ -0,0 +1,91 @@
+---
+id: 65fdc496f4440e1055a2ac1b
+title: Step 66
+challengeType: 20
+dashedName: step-66
+---
+
+# --description--
+
+After the `if` statement, return the result of comparing the norm of the current instance with the norm of `other` using the less than operator.
+
+# --hints--
+
+The `__lt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the `<` operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_return("self.norm() < other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
new file mode 100644
index 00000000000..7193db8cba2
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
@@ -0,0 +1,122 @@
+---
+id: 6601918b44a11b4a8c986c6a
+title: Step 67
+challengeType: 20
+dashedName: step-67
+---
+
+# --description--
+
+The `__gt__` method is called under the hood when the `>` operator is used to compare an object with something else.
+
+After the `__lt__` method, in the same way you did for `__lt__`, implement the `__gt__` method. Pay attention to use the appropriate operator.
+
+# --hints--
+
+You should define a `__gt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__gt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_args("self, other")`)) })
+```
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+The `__gt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the greater than operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_return("self.norm() > other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
new file mode 100644
index 00000000000..fd051c7fca6
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
@@ -0,0 +1,111 @@
+---
+id: 66019258a7c71d4ae50da42e
+title: Step 68
+challengeType: 20
+dashedName: step-68
+---
+
+# --description--
+
+There are still two possible comparisons to implement. The `__le__` method is called when the `<=` operator is used to compare two objects.
+
+Define a `__le__` method with `self` and `other` as the parameters and make it return the opposite of `self > other`.
+
+# --hints--
+
+You should define a `__le__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__le__")`)) })
+```
+
+Your `__le__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_args("self, other")`)) })
+```
+
+Your `__le__` method return the opposite of `self > other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_return("not self > other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
new file mode 100644
index 00000000000..542035862a5
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
@@ -0,0 +1,116 @@
+---
+id: 66019319edb1cb4b57d3a793
+title: Step 69
+challengeType: 20
+dashedName: step-69
+---
+
+# --description--
+
+The last method you need is `__ge__`, which is called when the `>=` is used to compare two objects.
+
+Define a `__ge__` method with `self` and `other` as the parameters and make it return the opposite of `self < other`.
+
+# --hints--
+
+You should define a `__ge__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ge__")`)) })
+```
+
+Your `__ge__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_args("self, other")`)) })
+```
+
+Your `__ge__` method should return the opposite of `self < other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_return("not self < other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
new file mode 100644
index 00000000000..fe9c0cfa362
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
@@ -0,0 +1,104 @@
+---
+id: 660193a2a71faa4bd8f10970
+title: Step 70
+challengeType: 20
+dashedName: step-70
+---
+
+# --description--
+
+Feel free to play around with the new comparison operations you implemented. Then, remove your last `print` call.
+
+
+# --hints--
+
+You should not have `print(v1 != R2Vector(x=2, y=3))` in your code.
+
+```js
+({test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
new file mode 100644
index 00000000000..2157c6b8a3b
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
@@ -0,0 +1,111 @@
+---
+id: 66019977710caa516276c0a8
+title: Step 71
+challengeType: 20
+dashedName: step-71
+---
+
+# --description--
+
+The *cross product*, or *vector product*, is defined between 3-dimensional vectors and results in a third vector perpendicular to both of them.
+
+The `R3Vector` class inherits from `R2Vector`, meaning it has access to all the methods and properties defined in `R2Vector`. A child class can implement additional features. You already saw a way to change the implementation of a method. Now, you are going to give the child class `R3Vector` a new method instead.
+
+Within the `R3Vector` class, define a `cross` method and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `cross` method within the `R3Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").has_function("cross")`)) })
+```
+
+Your `cross` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
new file mode 100644
index 00000000000..b7948eb83c6
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
@@ -0,0 +1,114 @@
+---
+id: 6601a7eb860fb8546516674d
+title: Step 72
+challengeType: 20
+dashedName: step-72
+---
+
+# --description--
+
+Create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
new file mode 100644
index 00000000000..7a7cb7ef03c
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
@@ -0,0 +1,105 @@
+---
+id: 6601a88a6e2ccc550d7d7208
+title: Step 73
+challengeType: 20
+dashedName: step-73
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_variable("kwargs").is_equivalent("kwargs = {}")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
new file mode 100644
index 00000000000..c9e2224dad3
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
@@ -0,0 +1,116 @@
+---
+id: 6601a8fb2e993b55912f9e9f
+title: Step 74
+challengeType: 20
+dashedName: step-74
+---
+
+# --description--
+
+The dot product between two 3D vectors \\( \mathbf{a} \\) and \\( \mathbf{b} \\) can be computed as it follows:
+
+\\[ \mathbf{a} \times \mathbf{b} = \begin{pmatrix} a_yb_z - a_zb_y \\\ a_zb_x - a_xb_z \\\ a_xb_y - a_yb_x \end{pmatrix} \\]
+
+Where the resulting vector is represented as a column vector.
+
+Implement the formula above to compute the dot product between two 3-dimensional vectors and return the resulting vector from the `cross()` method.
+
+# --hints--
+
+The `cross()` method should return a new `R3Vector` instance resulting from the dot product computation.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+v1.cross(v2) == R3Vector(x=4.75, y=-3.5, z=1.0) and v2.cross(v1) == R3Vector(x=-4.75, y=3.5, z=-1.0) and v1.cross(v1) == R3Vector(x=0, y=0, z=0)
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
new file mode 100644
index 00000000000..c1435330d56
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
@@ -0,0 +1,119 @@
+---
+id: 6601ab2809898f57591f2f7f
+title: Step 75
+challengeType: 20
+dashedName: step-75
+---
+
+# --description--
+
+Now, modify the assignments of `v1` and `v2`. Turn them into `R3Vector` instances and pass `z=1` and `z=2` to `v1` and `v2`, respectively.
+
+# --hints--
+
+You should modify the assignment of `v1` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R3Vector(x=2, y=3, z=1)")`)) })
+```
+
+You should modify the assignment of `v2` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=0.5, y=1.25, z=2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+--fcc-editable-region--
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
new file mode 100644
index 00000000000..6904f99b5e1
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
@@ -0,0 +1,113 @@
+---
+id: 6601ac48a2ee6b59e6a5060d
+title: Step 76
+challengeType: 20
+dashedName: step-76
+---
+
+# --description--
+
+Call `cross()` on `v1` and pass `v2` as the argument. Assign this call to a new variable `v6`.
+
+# --hints--
+
+You should declare a variable named `v6` and assign it a call to the `cross()` method on `v1` passing it `v2` as the `argument`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v6").is_equivalent("v6 = v1.cross(v2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
new file mode 100644
index 00000000000..47d13a7bd4d
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
@@ -0,0 +1,210 @@
+---
+id: 6601ad0fe415985a5c83f3cc
+title: Step 77
+challengeType: 20
+dashedName: step-77
+---
+
+# --description--
+
+As a final step, call the `print` function and pass it the f-string `f'v1 x v2 = {v6}'` to see the output of the dot product.
+
+With that, you have completed the vector space project. Well done!
+
+# --hints--
+
+You should print `f'v1 x v2 = {v6}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 x v2 = {v6}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+print(f'v1 x v2 = {v6}')
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
new file mode 100644
index 00000000000..d25b1a4c723
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
@@ -0,0 +1,53 @@
+---
+id: 6659875502b6d7765498f324
+title: Step 26
+challengeType: 20
+dashedName: step-26
+---
+
+# --description--
+
+Use f-strings to modify your `print` calls so that they result in the output `v1 = (2, 3)` and `v2 = (2, 2, 3)`, respectively.
+
+# --hints--
+
+You should use an f-string to interpolate `v1` and generate the output `v1 = (2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}')")`)) })
+```
+
+You should use an f-string to interpolate `v2` and generate the output `v2 = (2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
new file mode 100644
index 00000000000..bc5ffa5f75d
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
@@ -0,0 +1,51 @@
+---
+id: 66680ddfd0f8c76782923cb0
+title: Step 22
+challengeType: 20
+dashedName: step-22
+---
+
+# --description--
+
+The `norm()` method is returning the correct values, but there's still something you can improve: readability.
+
+The `vars()` built-in function takes an object as its argument and returns the `__dict__` attribute of that object.
+
+Instead of directly accessing the `__dict__` attribute of `self`, modify the `norm` method to use the `vars()` function.
+
+# --hints--
+
+You should modify your `norm` method to use `vars(self)` instead of `self.__dict__`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in vars(self).values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
new file mode 100644
index 00000000000..e0f1c196265
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
@@ -0,0 +1,61 @@
+---
+id: 66682150151af29efec9727d
+title: Step 33
+challengeType: 20
+dashedName: step-33
+---
+
+# --description--
+
+The `__getattribute__` method is called under the hood any time you try to access an instance attribute. If the attribute is not found at the instance level, the method will search for it at the class level, and eventually in parent classes.
+
+Inside your class, define a `__getattribute__` method with two parameters, `self` and `attr`, and make it return the string `'calling __getattribute__'`. You'll override momentarily the default implementation just to see how the attribute access works.
+
+# --hints--
+
+You should define a method named `__getattribute__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_args("self, attr")`)) })
+```
+
+Your `__getattribute__` method should return the string `'calling __getattribute__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_return("'calling __getattribute__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
new file mode 100644
index 00000000000..948a541cb76
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
@@ -0,0 +1,61 @@
+---
+id: 666826f258fda1ab3396a509
+title: Step 34
+challengeType: 20
+dashedName: step-34
+---
+
+# --description--
+
+Now, print the result of accessing the `x` attribute of `v1` both with the dot operator and the `getattr()` built-in function.
+
+You will see that `__getattribute__` is called in both cases.
+
+# --hints--
+
+You should print the `x` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.x)") and n.has_call("print(getattr(v1, 'x'))")) or n.has_call("print(v1.x, getattr(v1, 'x'))") or n.has_call("print(getattr(v1, 'x'), v1.x)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
new file mode 100644
index 00000000000..8c3a650010b
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
@@ -0,0 +1,69 @@
+---
+id: 666827a6fd0dbaafe8330ea6
+title: Step 35
+challengeType: 20
+dashedName: step-35
+---
+
+# --description--
+
+`__getattr__` is another special method that plays a role in accessing attributes.
+
+The default implementation of `__getattribute__` is to raise an `AttributeError` when the requested attribute is not an instance attribute or it is not present in the class tree.
+
+In that case, `__getattr__` is called if defined by the class. You can consider it as a sort of fallback when the usual attribute accessing procedure fails.
+
+Turn the `__getattribute__` method into `__getattr__` and modify the string returned by the method into `'calling __getattr__'`.
+
+# --hints--
+
+You should define a method named `__getattr__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_args("self, attr")`)) })
+```
+
+Your `__getattr__` method should return the string `'calling __getattr__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_return("'calling __getattr__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+print(v1.x)
+print(getattr(v1, 'x'))
+
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
new file mode 100644
index 00000000000..598c9822428
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
@@ -0,0 +1,62 @@
+---
+id: 666832e427d70bc5219dc62a
+title: Step 36
+challengeType: 20
+dashedName: step-36
+---
+
+# --description--
+
+As you can see from the output, although you defined `__getattr__` in your class, this method is not called yet. This happens because the default attribute access occurs through `__getattribute__`. Therefore, you can see the attribute value printed on the terminal.
+
+Now modify the last two lines of code to access the `z` attribute of `v1` in both your `print()` calls. This time, you are going to access an attribute that `v1` does not have. As a result, `__getattribute__` will raise an error and `__getattr__` will be called.
+
+# --hints--
+
+You should modify your code to print the `z` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.z)") and n.has_call("print(getattr(v1, 'z'))")) or n.has_call("print(v1.z, getattr(v1, 'z'))") or n.has_call("print(getattr(v1, 'z'), v1.z)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+print(v1.x)
+print(getattr(v1, 'x'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
new file mode 100644
index 00000000000..3f18e7c657c
--- /dev/null
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
@@ -0,0 +1,75 @@
+---
+id: 6668374ed18b7fce10259cb3
+title: Step 37
+challengeType: 20
+dashedName: step-37
+---
+
+# --description--
+
+Now that you have an idea of how the attribute access work, remove the last two lines of your code together with the `__getattr__` method.
+
+Then, restore the `print()` calls you commented out before and delete the second argument from both of them.
+
+# --hints--
+
+You should not have a `__getattr__` method.
+
+```js
+({ test: () => assert.isFalse(runPython(`_Node(_code).find_class("R2Vector").has_function("__getattr__")`)) })
+```
+
+You should not have `print(v1.z)`and `print(getattr(v1, 'z'))` in your code.
+
+```js
+({ test: () => assert.isFalse(runPython(`
+n = _Node(_code)
+n.has_call("print(v1.z)") or n.has_call("print(getattr(v1, 'z'))")
+`)) })
+```
+
+You should restore the `print()` calls you commented out before and remove the second argument from both of them.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).has_call("print(f'v1 = {v1}')") and _Node(_code).has_call("print(f'v2 = {v2}')")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+print(v1.z)
+print(getattr(v1, 'z'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551ecf597038c36637f3759.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551ecf597038c36637f3759.md
index 5a7a8e606dd..06ef74d37dd 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551ecf597038c36637f3759.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551ecf597038c36637f3759.md
@@ -1,6 +1,6 @@
---
id: 6551ecf597038c36637f3759
-title: Step 1
+title: 1° passo
challengeType: 20
dashedName: step-1
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551eebe6cbb2e6cadf9b468.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551eebe6cbb2e6cadf9b468.md
index a880a21a027..5fa7e5c131a 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551eebe6cbb2e6cadf9b468.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551eebe6cbb2e6cadf9b468.md
@@ -1,6 +1,6 @@
---
id: 6551eebe6cbb2e6cadf9b468
-title: Step 2
+title: Passo 2
challengeType: 20
dashedName: step-2
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551ef504d91936d2d4e54f8.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551ef504d91936d2d4e54f8.md
index 2b65b4b4212..a453ca462f8 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551ef504d91936d2d4e54f8.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551ef504d91936d2d4e54f8.md
@@ -1,6 +1,6 @@
---
id: 6551ef504d91936d2d4e54f8
-title: Step 4
+title: Passo 4
challengeType: 20
dashedName: step-4
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f1e8737dbe6e0cb08ea4.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f1e8737dbe6e0cb08ea4.md
index f8bb0f2f644..480519b26ad 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f1e8737dbe6e0cb08ea4.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f1e8737dbe6e0cb08ea4.md
@@ -1,6 +1,6 @@
---
id: 6551f1e8737dbe6e0cb08ea4
-title: Step 10
+title: Passo 10
challengeType: 20
dashedName: step-10
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f22653e6ce6e4f1d1370.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f22653e6ce6e4f1d1370.md
index d80be1b9b59..a925202283f 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f22653e6ce6e4f1d1370.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f22653e6ce6e4f1d1370.md
@@ -1,6 +1,6 @@
---
id: 6551f22653e6ce6e4f1d1370
-title: Step 11
+title: Passo 10
challengeType: 20
dashedName: step-11
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f3bfed58796ebb1268dc.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f3bfed58796ebb1268dc.md
index e55d6fbfb37..17f73888aa2 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f3bfed58796ebb1268dc.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f3bfed58796ebb1268dc.md
@@ -1,13 +1,13 @@
---
id: 6551f3bfed58796ebb1268dc
-title: Step 5
+title: Passo 5
challengeType: 20
dashedName: step-5
---
# --description--
-Each string character can be referenced by a numerical index. The index count starts at zero. So the first character of a string has an index of `0`. For example, in the string `'Hello World'`, `'H'` is at index `0`, `'e'` is at index `1`, and so on.
+Each string character can be referenced by a numerical index. The index count starts at zero. So the first character of a string has an index of `0`. For example, in the string `'Hello World'`, `'H'` is at index `0`, `'e'` is at index `1`, and so on.
Each character of a string can be accessed by using bracket notation. You need to write the variable name followed by square brackets and add the index of the character between the brackets:
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f4259d66026ee28cb205.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f4259d66026ee28cb205.md
index d04e0d082d3..3c181c9e227 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f4259d66026ee28cb205.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f4259d66026ee28cb205.md
@@ -1,6 +1,6 @@
---
id: 6551f4259d66026ee28cb205
-title: Step 6
+title: Passo 6
challengeType: 20
dashedName: step-6
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f5756c20146fc94f8675.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f5756c20146fc94f8675.md
index b2d39487b22..3bdf6f4a082 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f5756c20146fc94f8675.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f5756c20146fc94f8675.md
@@ -1,6 +1,6 @@
---
id: 6551f5756c20146fc94f8675
-title: Step 7
+title: Passo 7
challengeType: 20
dashedName: step-7
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f6f9ec6db270eb83f3db.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f6f9ec6db270eb83f3db.md
index 3103cb653bf..3f39c728f42 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f6f9ec6db270eb83f3db.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551f6f9ec6db270eb83f3db.md
@@ -1,6 +1,6 @@
---
id: 6551f6f9ec6db270eb83f3db
-title: Step 8
+title: Passo 8
challengeType: 20
dashedName: step-8
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551fb531ce7f773071a0b84.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551fb531ce7f773071a0b84.md
index 5b4ea67556d..1b5aff64b1c 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551fb531ce7f773071a0b84.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551fb531ce7f773071a0b84.md
@@ -1,6 +1,6 @@
---
id: 6551fb531ce7f773071a0b84
-title: Step 9
+title: Passo 9
challengeType: 20
dashedName: step-9
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551fe3b1df7c9740f13f270.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551fe3b1df7c9740f13f270.md
index 074c15b2e19..e628bab3bd8 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551fe3b1df7c9740f13f270.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6551fe3b1df7c9740f13f270.md
@@ -1,6 +1,6 @@
---
id: 6551fe3b1df7c9740f13f270
-title: Step 12
+title: Passo 12
challengeType: 20
dashedName: step-12
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6552008c0d9d9075cbec9772.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6552008c0d9d9075cbec9772.md
index 5521a7ef0cb..017af0ab0e5 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6552008c0d9d9075cbec9772.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6552008c0d9d9075cbec9772.md
@@ -1,6 +1,6 @@
---
id: 6552008c0d9d9075cbec9772
-title: Step 13
+title: Passo 13
challengeType: 20
dashedName: step-13
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655208d59b131e7816f18c96.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655208d59b131e7816f18c96.md
index d2285f294cc..7081dcb9bf9 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655208d59b131e7816f18c96.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655208d59b131e7816f18c96.md
@@ -1,6 +1,6 @@
---
id: 655208d59b131e7816f18c96
-title: Step 15
+title: Passo 15
challengeType: 20
dashedName: step-15
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655209a4a27dd37873c4cac3.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655209a4a27dd37873c4cac3.md
index 3a5e125bb42..d3305b1e5e8 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655209a4a27dd37873c4cac3.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655209a4a27dd37873c4cac3.md
@@ -1,6 +1,6 @@
---
id: 655209a4a27dd37873c4cac3
-title: Step 17
+title: Passo 17
challengeType: 20
dashedName: step-17
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65520e6f2b9678799977f24d.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65520e6f2b9678799977f24d.md
index c4c346e5bc3..9fa9fdd46aa 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65520e6f2b9678799977f24d.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65520e6f2b9678799977f24d.md
@@ -1,6 +1,6 @@
---
id: 65520e6f2b9678799977f24d
-title: Step 18
+title: Passo 18
challengeType: 20
dashedName: step-18
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65520f8282faf57a0db4f7fe.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65520f8282faf57a0db4f7fe.md
index c84dce1fe16..03df142b3e1 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65520f8282faf57a0db4f7fe.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65520f8282faf57a0db4f7fe.md
@@ -1,6 +1,6 @@
---
id: 65520f8282faf57a0db4f7fe
-title: Step 21
+title: Passo 21
challengeType: 20
dashedName: step-21
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65521203d7165c7b84b22ad4.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65521203d7165c7b84b22ad4.md
index 871e2f11a1f..ae51f509fe6 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65521203d7165c7b84b22ad4.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65521203d7165c7b84b22ad4.md
@@ -1,6 +1,6 @@
---
id: 65521203d7165c7b84b22ad4
-title: Step 23
+title: Passo 23
challengeType: 20
dashedName: step-23
---
@@ -37,14 +37,14 @@ const commentless_code = __helpers.python.removeComments(code);
assert.match(commentless_code, /^for\s+i/m)
```
-You should write the `in` keyword after `for i `. Make sure to leave a space around the `in` keyword.
+You should write the `in` keyword after `for i`. Make sure to leave a space around the `in` keyword.
```js
const commentless_code = __helpers.python.removeComments(code);
assert.match(commentless_code, /^for\s+i\s+in\s+/m)
```
-You should write `text` after `for i in `. Don't forget to add the final `:`.
+You should write `text` after `for i in`. Don't forget to add the final `:`.
```js
const commentless_code = __helpers.python.removeComments(code);
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65521fc818947e800bffe48a.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65521fc818947e800bffe48a.md
index 8a28b338b4b..d898f65b5b0 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65521fc818947e800bffe48a.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65521fc818947e800bffe48a.md
@@ -1,6 +1,6 @@
---
id: 65521fc818947e800bffe48a
-title: Step 26
+title: Passo 26
challengeType: 20
dashedName: step-26
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655220953ba90d80514d7ee2.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655220953ba90d80514d7ee2.md
index 17b10b3830e..1aa834c12ed 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655220953ba90d80514d7ee2.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655220953ba90d80514d7ee2.md
@@ -1,6 +1,6 @@
---
id: 655220953ba90d80514d7ee2
-title: Step 27
+title: Passo 27
challengeType: 20
dashedName: step-27
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65522255d5b9cd80f335c6f2.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65522255d5b9cd80f335c6f2.md
index d92af7b037d..c500d60cf85 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65522255d5b9cd80f335c6f2.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65522255d5b9cd80f335c6f2.md
@@ -1,6 +1,6 @@
---
id: 65522255d5b9cd80f335c6f2
-title: Step 29
+title: Passo 29
challengeType: 20
dashedName: step-29
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6552487e689f6e895f658717.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6552487e689f6e895f658717.md
index 790a65cef4a..7719b3cd871 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6552487e689f6e895f658717.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6552487e689f6e895f658717.md
@@ -1,6 +1,6 @@
---
id: 6552487e689f6e895f658717
-title: Step 33
+title: Passo 33
challengeType: 20
dashedName: step-33
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65524b3aa6a1938a069a91ab.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65524b3aa6a1938a069a91ab.md
index d239b9e0d97..b4aa698f8f7 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65524b3aa6a1938a069a91ab.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65524b3aa6a1938a069a91ab.md
@@ -1,6 +1,6 @@
---
id: 65524b3aa6a1938a069a91ab
-title: Step 34
+title: Passo 34
challengeType: 20
dashedName: step-34
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65524b790ba8558a2f1c9fe5.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65524b790ba8558a2f1c9fe5.md
index 5a2bcca9beb..15b5fcf51ad 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65524b790ba8558a2f1c9fe5.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65524b790ba8558a2f1c9fe5.md
@@ -1,6 +1,6 @@
---
id: 65524b790ba8558a2f1c9fe5
-title: Step 35
+title: Passo 35
challengeType: 20
dashedName: step-35
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65524d2a1a253b8bb5197ae2.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65524d2a1a253b8bb5197ae2.md
index 600c1db8bf4..41cda3cfd65 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65524d2a1a253b8bb5197ae2.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65524d2a1a253b8bb5197ae2.md
@@ -1,6 +1,6 @@
---
id: 65524d2a1a253b8bb5197ae2
-title: Step 28
+title: Passo 28
challengeType: 20
dashedName: step-28
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655251308f31958d06cdf267.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655251308f31958d06cdf267.md
index ae422ccd386..d06b4fdbb9b 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655251308f31958d06cdf267.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655251308f31958d06cdf267.md
@@ -1,6 +1,6 @@
---
id: 655251308f31958d06cdf267
-title: Step 36
+title: Passo 36
challengeType: 20
dashedName: step-36
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65525e359ca28d938baa82c5.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65525e359ca28d938baa82c5.md
index 9cee9f8f54d..13bdd009eae 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65525e359ca28d938baa82c5.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65525e359ca28d938baa82c5.md
@@ -1,6 +1,6 @@
---
id: 65525e359ca28d938baa82c5
-title: Step 39
+title: Passo 39
challengeType: 20
dashedName: step-39
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655261b2e1f2c197093f3993.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655261b2e1f2c197093f3993.md
index 88f5c9d935f..1939d0cbf3c 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655261b2e1f2c197093f3993.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655261b2e1f2c197093f3993.md
@@ -1,6 +1,6 @@
---
id: 655261b2e1f2c197093f3993
-title: Step 41
+title: Passo 41
challengeType: 20
dashedName: step-41
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553980e0527fa115c705646.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553980e0527fa115c705646.md
index 084318f08c8..a9727bd27eb 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553980e0527fa115c705646.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553980e0527fa115c705646.md
@@ -1,6 +1,6 @@
---
id: 6553980e0527fa115c705646
-title: Step 42
+title: Passo 42
challengeType: 20
dashedName: step-42
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553995f412dd8122ed38e4a.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553995f412dd8122ed38e4a.md
index 3e58afd81dd..1f4f8681696 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553995f412dd8122ed38e4a.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553995f412dd8122ed38e4a.md
@@ -1,6 +1,6 @@
---
id: 6553995f412dd8122ed38e4a
-title: Step 43
+title: Passo 43
challengeType: 20
dashedName: step-43
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a44b1801991847d8cc69.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a44b1801991847d8cc69.md
index 63faaeff7aa..8a848a4ccd4 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a44b1801991847d8cc69.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a44b1801991847d8cc69.md
@@ -1,6 +1,6 @@
---
id: 6553a44b1801991847d8cc69
-title: Step 47
+title: Passo 47
challengeType: 20
dashedName: step-47
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a572f7a65718f1e42e18.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a572f7a65718f1e42e18.md
index 83bee644083..35e6e93298d 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a572f7a65718f1e42e18.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a572f7a65718f1e42e18.md
@@ -1,6 +1,6 @@
---
id: 6553a572f7a65718f1e42e18
-title: Step 49
+title: Passo 49
challengeType: 20
dashedName: step-49
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a755879b131a445e664c.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a755879b131a445e664c.md
index 78656b5b37e..972c2ca8c5a 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a755879b131a445e664c.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a755879b131a445e664c.md
@@ -1,6 +1,6 @@
---
id: 6553a755879b131a445e664c
-title: Step 44
+title: Passo 44
challengeType: 20
dashedName: step-44
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a7d8d05cbb1ae335a665.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a7d8d05cbb1ae335a665.md
index f7de0e045e0..254f7d177d6 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a7d8d05cbb1ae335a665.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553a7d8d05cbb1ae335a665.md
@@ -1,6 +1,6 @@
---
id: 6553a7d8d05cbb1ae335a665
-title: Step 45
+title: Passo 45
challengeType: 20
dashedName: step-45
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6b4ec51112d44d737c8.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6b4ec51112d44d737c8.md
index bdda381401c..33fceb9073f 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6b4ec51112d44d737c8.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6b4ec51112d44d737c8.md
@@ -1,6 +1,6 @@
---
id: 6553f6b4ec51112d44d737c8
-title: Step 48
+title: Passo 48
challengeType: 20
dashedName: step-48
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
index 5efbe910d0e..ab8d95e137d 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
@@ -7,8 +7,7 @@ dashedName: step-60
# --description--
-Since your key is shorter than the text that you will have to encrypt, you will need to repeat it to generate the whole encrypted text.
-At the beginning of your function body, declare a `key_index` variable and set it to zero.
+Since your key is shorter than the text that you will have to encrypt, you will need to repeat it to generate the whole encrypted text. At the beginning of your function body, declare a `key_index` variable and set it to zero.
# --hints--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
index b8abcbb5788..839352832e3 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
@@ -37,7 +37,7 @@ def vigenere(message, key):
for char in message.lower():
--fcc-editable-region--
-
+
if char == ' ':
encrypted_text += char
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
index b58810881c4..921879d9acc 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
@@ -7,8 +7,7 @@ dashedName: step-63
# --description--
-You will need to increase the `key_index` count for the next iteration.
-To do this, after the line you just added and in the same code block, use the addition assignment operator to increment `key_index` by one.
+You will need to increase the `key_index` count for the next iteration. To do this, after the line you just added and in the same code block, use the addition assignment operator to increment `key_index` by one.
# --hints--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
index 0bd011f3056..139a3fea8db 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
@@ -37,7 +37,7 @@ def vigenere(message, key):
if char == ' ':
encrypted_text += char
else:
-
+
key_char = key[key_index % len(key)]
key_index += 1
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
index ad2d60bc565..b1c21af09e5 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
@@ -52,7 +52,7 @@ def vigenere(message, key):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -61,7 +61,7 @@ def vigenere(message, key):
# Find the right key character to encode
key_char = key[key_index % len(key)]
key_index += 1
-
+
--fcc-editable-region--
index = alphabet.find(char)
new_index = (index + offset) % len(alphabet)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
index 7457687ccd9..2bff453ec4b 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
@@ -32,7 +32,7 @@ def vigenere(message, key):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -41,7 +41,7 @@ def vigenere(message, key):
key_char = key[key_index % len(key)]
key_index += 1
--fcc-editable-region--
-
+
offset = alphabet.index(key_char)
index = alphabet.find(char)
new_index = (index + offset) % len(alphabet)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
index 38d7810807e..4c7bb7ab462 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
@@ -62,7 +62,7 @@ def vigenere(message, key):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
index 2405723afae..1eeeb3697b1 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
@@ -43,7 +43,7 @@ def vigenere(message, key):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -57,7 +57,7 @@ def vigenere(message, key):
index = alphabet.find(char)
new_index = (index + offset) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
index c4181e5c5d0..5f093f3df2c 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
@@ -31,7 +31,7 @@ def vigenere(message, key):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -45,7 +45,7 @@ def vigenere(message, key):
index = alphabet.find(char)
new_index = (index + offset) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
index 0d2791f2f50..65ac8f3f6c4 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
@@ -45,7 +45,7 @@ def vigenere(message, key):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -59,9 +59,9 @@ def vigenere(message, key):
index = alphabet.find(char)
new_index = (index + offset) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
-
+
encryption = vigenere(text, custom_key)
print(encryption)
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
index f8a74620872..2df3eb6fceb 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
@@ -31,7 +31,7 @@ def vigenere(message, key, direction):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -47,9 +47,9 @@ def vigenere(message, key, direction):
new_index = (index + offset) % len(alphabet)
--fcc-editable-region--
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
-
+
#encryption = vigenere(text, custom_key)
#print(encryption)
```
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
index 2a57a505732..5e52b90279e 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
@@ -31,7 +31,7 @@ def vigenere(message, key, direction):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -45,9 +45,9 @@ def vigenere(message, key, direction):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
-
+
--fcc-editable-region--
#encryption = vigenere(text, custom_key)
#print(encryption)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
index 72b7af3dadc..02e14d9019c 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
@@ -45,7 +45,7 @@ def vigenere(message, key, direction):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -59,7 +59,7 @@ def vigenere(message, key, direction):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
--fcc-editable-region--
encryption = vigenere(text, custom_key, 1)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
index 4ac59ba2ee4..7f91537aead 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
@@ -31,7 +31,7 @@ def vigenere(message, key, direction):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -45,7 +45,7 @@ def vigenere(message, key, direction):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
--fcc-editable-region--
encryption = vigenere(text, custom_key, 1)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
index f4745b80538..d5bdb7ff5d1 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
@@ -39,7 +39,7 @@ def vigenere(message, key, direction):
encrypted_text = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
encrypted_text += char
@@ -53,7 +53,7 @@ def vigenere(message, key, direction):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
encrypted_text += alphabet[new_index]
-
+
return encrypted_text
--fcc-editable-region--
encryption = vigenere(text, custom_key, 1)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
index 14d6aad3a62..a80c318bd1d 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
@@ -38,7 +38,7 @@ def vigenere(message, key, direction):
final_message = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
final_message += char
@@ -52,9 +52,9 @@ def vigenere(message, key, direction):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
-
+
encryption = vigenere(text, custom_key, 1)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
index 9298423269b..82e1790a7d8 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
@@ -40,7 +40,7 @@ def vigenere(message, key, direction=1):
final_message = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
final_message += char
@@ -54,9 +54,9 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
-
+
encryption = vigenere(text, custom_key)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
index 2cbbb0a082a..8603eb7e6d8 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
@@ -53,9 +53,9 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
-
+
encryption = vigenere(text, custom_key)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
index 37ab3631ee0..5c6c8181984 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
@@ -48,9 +48,9 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
-
+
encryption = vigenere(text, custom_key)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
index 0fc9fdd1938..db091c232cc 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
@@ -46,9 +46,9 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
-
+
encryption = vigenere(text, custom_key)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
index b5baba46613..9588d739f44 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
@@ -68,7 +68,7 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
index dbe2439e466..b8c910a3aa5 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
@@ -51,7 +51,7 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
--fcc-editable-region--
def encrypt(message, key):
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
index b713ce9b2af..28da95df2b0 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
@@ -71,12 +71,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
--fcc-editable-region--
def encrypt(message, key):
return vigenere(message, key)
-
+
encryption = vigenere(text, custom_key)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
index afc5580a630..4fcaff7b89c 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
@@ -51,15 +51,15 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
--fcc-editable-region--
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
-
+
encryption = vigenere(text, custom_key)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
index 920a8be3ade..f8ea2a67964 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
@@ -54,15 +54,15 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
-
+
encryption = encrypt(text, custom_key)
print(encryption)
decryption = decrypt(encryption, custom_key)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
index 10b4700ca86..6799724af14 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
@@ -45,7 +45,7 @@ def vigenere(message, key, direction):
final_message = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
final_message += char
@@ -59,9 +59,9 @@ def vigenere(message, key, direction):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
-
+
encryption = vigenere(text, custom_key, 1)
print(encryption)
decryption = vigenere(encryption, custom_key, -1)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
index 38da1a0f062..97049b3b537 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
@@ -31,7 +31,7 @@ def vigenere(message, key, direction=1):
final_message = ''
for char in message.lower():
-
+
# Append space to the message
if char == ' ':
final_message += char
@@ -45,7 +45,7 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
--fcc-editable-region--
encryption = vigenere(text, custom_key, 1)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
index 7fae4626dfc..d310105bfe1 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
@@ -13,7 +13,7 @@ Call the `print()` function and use the `+` operator to concatenate the `text` v
# --hints--
-You should call `print()` and pass `'Encrypted text: ' + text` as the arguments.
+You should call `print()` and pass `'Encrypted text: ' + text` as the arguments.
```js
const commentless_code = __helpers.python.removeComments(code);
@@ -54,12 +54,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
index 09ea7a24978..3a91139cf33 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
@@ -52,12 +52,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
index dc9a8c24fc2..bc5788b45f8 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
@@ -7,7 +7,7 @@ dashedName: step-91
# --description--
-In Python, there's a way to easily format strings. *f-strings* enable you to interpolate values in your strings.
+In Python, there's a way to easily format strings. *f-strings* enable you to interpolate values in your strings.
Interpolation means writing placeholders that will be replaced by the specified values when the program runs. For example, you can get the same result of `'Encrypted text: ' + text` with `f'Encrypted text: {text}'`. You need to put an `f` before the quotes to create the f-string and write the variables or expressions you want to interpolate between curly braces.
@@ -49,12 +49,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
index e372c7bd573..4d7848b4be9 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
@@ -45,12 +45,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
index 2cb1b183b8b..e895a41b321 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
@@ -47,12 +47,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
index 7bdde40cd59..f878bb6c12b 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
@@ -50,12 +50,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
index 0a6a778d0e1..9b3df4758a0 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
@@ -54,12 +54,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
@@ -96,12 +96,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655619327c7b364166f8dd6f.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655619327c7b364166f8dd6f.md
index 46566b96317..72c1e12af27 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655619327c7b364166f8dd6f.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655619327c7b364166f8dd6f.md
@@ -1,6 +1,6 @@
---
id: 655619327c7b364166f8dd6f
-title: Step 46
+title: Passo 46
challengeType: 20
dashedName: step-46
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655a2a7210094920069b117c.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655a2a7210094920069b117c.md
index d085aa7fef7..ecf7907cae8 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655a2a7210094920069b117c.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655a2a7210094920069b117c.md
@@ -1,14 +1,13 @@
---
id: 655a2a7210094920069b117c
-title: Step 40
+title: Passo 40
challengeType: 20
dashedName: step-40
---
# --description--
-Comparison operators allow you to compare two objects based on their values. You can use a comparison operator by placing it between the objects you want to compare.
-They return a *Boolean* value — namely `True` or `False` — depending on the truthfulness of the expression.
+Comparison operators allow you to compare two objects based on their values. You can use a comparison operator by placing it between the objects you want to compare. They return a *Boolean* value — namely `True` or `False` — depending on the truthfulness of the expression.
Python has the following comparison operators:
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65687d2f8c7ee27b0446cef3.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65687d2f8c7ee27b0446cef3.md
index a7d50d62d26..8a13db7161c 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65687d2f8c7ee27b0446cef3.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65687d2f8c7ee27b0446cef3.md
@@ -1,6 +1,6 @@
---
id: 65687d2f8c7ee27b0446cef3
-title: Step 24
+title: Passo 24
challengeType: 20
dashedName: step-24
---
@@ -27,7 +27,7 @@ Give your `for` loop a body by adding a call to `print(i)`. Remember to indent t
# --hints--
-You should add `print(i)` to your `for` loop body. Pay attention to the indentation.
+You should add `print(i)` to your `for` loop body. Pay attention to the indentation.
```js
assert.match(code, /^for\s+i\s+in\s+text:\s+print\s*\(\s*i\s*\)/m)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/656886ec4e4d9b96ded3c565.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/656886ec4e4d9b96ded3c565.md
index b1b9f3d44b8..a08287423d9 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/656886ec4e4d9b96ded3c565.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/656886ec4e4d9b96ded3c565.md
@@ -1,6 +1,6 @@
---
id: 656886ec4e4d9b96ded3c565
-title: Step 25
+title: Passo 25
challengeType: 20
dashedName: step-25
---
@@ -13,7 +13,7 @@ Rename your `i` variable to `char`.
# --hints--
-You should replace `i` with `char`.
+You should replace `i` with `char`.
```js
assert.match(code, /^for\s+char\s+in\s+text:\s+print\s*\(\s*char\s*\)/m)
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65688a50e6c998a21d8e41d3.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65688a50e6c998a21d8e41d3.md
index 418b46ed7ba..449065f9336 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65688a50e6c998a21d8e41d3.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65688a50e6c998a21d8e41d3.md
@@ -1,6 +1,6 @@
---
id: 65688a50e6c998a21d8e41d3
-title: Step 30
+title: Passo 30
challengeType: 20
dashedName: step-30
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65688b5a1655a7a6caede847.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65688b5a1655a7a6caede847.md
index b811dd6baff..9cb01e25f09 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65688b5a1655a7a6caede847.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65688b5a1655a7a6caede847.md
@@ -1,6 +1,6 @@
---
id: 65688b5a1655a7a6caede847
-title: Step 31
+title: Passo 31
challengeType: 20
dashedName: step-31
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6568b7a40c7ba0ccbc4b4425.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6568b7a40c7ba0ccbc4b4425.md
index c72a6853cf2..70adbc33342 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6568b7a40c7ba0ccbc4b4425.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6568b7a40c7ba0ccbc4b4425.md
@@ -1,6 +1,6 @@
---
id: 6568b7a40c7ba0ccbc4b4425
-title: Step 32
+title: Passo 32
challengeType: 20
dashedName: step-32
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6568c86dc9193000d11ca5e0.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6568c86dc9193000d11ca5e0.md
index 9d7ee76d8c5..fa95664e92d 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6568c86dc9193000d11ca5e0.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6568c86dc9193000d11ca5e0.md
@@ -1,6 +1,6 @@
---
id: 6568c86dc9193000d11ca5e0
-title: Step 38
+title: Passo 38
challengeType: 20
dashedName: step-38
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6568cc9301a0c41058ed95c5.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6568cc9301a0c41058ed95c5.md
index 7f628c1a578..d3a914d8a41 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6568cc9301a0c41058ed95c5.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6568cc9301a0c41058ed95c5.md
@@ -1,6 +1,6 @@
---
id: 6568cc9301a0c41058ed95c5
-title: Step 37
+title: Passo 37
challengeType: 20
dashedName: step-37
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65951b637ddec63611c482c0.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65951b637ddec63611c482c0.md
index 101abfd8979..8d7df79f62c 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65951b637ddec63611c482c0.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65951b637ddec63611c482c0.md
@@ -1,6 +1,6 @@
---
id: 65951b637ddec63611c482c0
-title: Step 3
+title: Passo 3
challengeType: 20
dashedName: step-3
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/659526f3e5424b3eac4b6aa7.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/659526f3e5424b3eac4b6aa7.md
index fceca72c9b3..a3dc29f2467 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/659526f3e5424b3eac4b6aa7.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/659526f3e5424b3eac4b6aa7.md
@@ -1,6 +1,6 @@
---
id: 659526f3e5424b3eac4b6aa7
-title: Step 16
+title: Passo 16
challengeType: 20
dashedName: step-16
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65952b70924edb449faf1950.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65952b70924edb449faf1950.md
index 70e8dcca396..75da127bd13 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65952b70924edb449faf1950.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65952b70924edb449faf1950.md
@@ -1,6 +1,6 @@
---
id: 65952b70924edb449faf1950
-title: Step 19
+title: Passo 19
challengeType: 20
dashedName: step-19
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/659530ca823d6c47f61daa8a.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/659530ca823d6c47f61daa8a.md
index fffb54a7d67..47840357462 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/659530ca823d6c47f61daa8a.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/659530ca823d6c47f61daa8a.md
@@ -1,6 +1,6 @@
---
id: 659530ca823d6c47f61daa8a
-title: Step 20
+title: Passo 20
challengeType: 20
dashedName: step-20
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/659db3e3670d3e712be82593.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/659db3e3670d3e712be82593.md
index d3d731ffda0..55074ab77d7 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/659db3e3670d3e712be82593.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/659db3e3670d3e712be82593.md
@@ -1,6 +1,6 @@
---
id: 659db3e3670d3e712be82593
-title: Step 22
+title: Passo 22
challengeType: 20
dashedName: step-22
---
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
index 6b039444ed9..1bb2f8f1567 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
@@ -73,12 +73,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
index f66b75cbf83..29a960e8277 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
@@ -45,12 +45,12 @@ def vigenere(message, key, direction=1):
index = alphabet.find(char)
new_index = (index + offset*direction) % len(alphabet)
final_message += alphabet[new_index]
-
+
return final_message
def encrypt(message, key):
return vigenere(message, key)
-
+
def decrypt(message, key):
return vigenere(message, key, -1)
--fcc-editable-region--
diff --git a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6624e0ec0bf47017eed84b1f.md b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6624e0ec0bf47017eed84b1f.md
index 6cc15944f29..3224e7fcba7 100644
--- a/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6624e0ec0bf47017eed84b1f.md
+++ b/curriculum/challenges/portuguese/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6624e0ec0bf47017eed84b1f.md
@@ -1,6 +1,6 @@
---
id: 6624e0ec0bf47017eed84b1f
-title: Step 14
+title: Passo 14
challengeType: 20
dashedName: step-14
---
@@ -17,7 +17,7 @@ You should modify your existing `alphabet.find('z')` call passing `text[0]` to t
```js
assert.match(code, /^alphabet\.find\s*\(\s*text\s*\[\s*0\s*\]\s*\)/m)
-```
+```
# --seed--
diff --git a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md b/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
deleted file mode 100644
index a65ba9057bb..00000000000
--- a/curriculum/challenges/portuguese/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
+++ /dev/null
@@ -1,344 +0,0 @@
----
-id: 62aa1fed3d4e873366ff3131
-title: Passo 150
-challengeType: 0
-dashedName: step-150
----
-
-# --description--
-
-Na função `attack`, abaixo da variável `health`, crie uma instrução `if`. Defina a condição para chamar a função `isMonsterHit`.
-
-# --hints--
-
-Você deve adicionar uma instrução `if` que chama `isMonsterHit` à condição.
-
-```js
-assert.match(attack.toString(), /if\s*\(\s*isMonsterHit\s*\(\s*\)/)
-```
-
-# --seed--
-
-## --seed-contents--
-
-```html
-
-
-
-
-
-
+
+Within the `Vector` class, create an `__init__` method and give it three parameters, `self`, `x`, and `y`.
+
+# --hints--
+
+You should define an `__init__` method inside the `Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").has_function("__init__")`)) })
+```
+
+Your `__init__` method should take three parameters: `self`, `x`, and `y`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").find_function("__init__").has_args("self, x, y")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ pass
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
new file mode 100644
index 00000000000..62ab349a8db
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
@@ -0,0 +1,38 @@
+---
+id: 65f055b9190fc41ca35549b8
+title: Step 3
+challengeType: 20
+dashedName: step-3
+---
+
+# --description--
+
+Python offers various methods that include both a leading and trailing double underscore in their names. You may already be familiar with some, such as `__init__` and `__str__`. These methods, which follow the `__
+
+So far, you created a 2-dimensional vector. You want to be able to represent vectors with a different number of dimensions without rewriting the necessary code for each specific case. For that, you will use inheritance.
+
+Start by renaming the `Vector` class into `R2Vector` to specify that this class is going to deal with 2-dimensional vectors. Remember to modify the instantiation of `v1`, too.
+
+# --hints--
+
+You should rename the `Vector` class into `R2Vector`. Remember to modify the instantiation of `v1`, too.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+v1 = Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
new file mode 100644
index 00000000000..e26a20b0730
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
@@ -0,0 +1,70 @@
+---
+id: 65f40051d6b09a139f253e8e
+title: Step 12
+challengeType: 20
+dashedName: step-12
+---
+
+# --description--
+
+Inheritance enables you to define a class from an existing one. The new class, called child, inherits all the methods and properties of the existing class, called parent.
+
+```py
+class Tree:
+ def sprout(self):
+ print('Making new leaves!')
+
+class Oak(Tree):
+ pass
+
+Oak().sprout() # Output: Making new leaves!
+```
+
+In the example above, the child class `Oak` inherits from `Tree` and inherits the `sprout` method from the parent class `Tree`.
+
+Create a new class named `R3Vector` and follow the example above to make it inherit from the `R2Vector` class.
+
+# --hints--
+
+You should define a new class `R3Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R3Vector")
+ `))
+})
+```
+
+Your new class `R3Vector` should inherit from `R2Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").inherits_from("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
new file mode 100644
index 00000000000..c50cbefeb4a
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
@@ -0,0 +1,56 @@
+---
+id: 65f40401e6ef53173c04e27d
+title: Step 13
+challengeType: 20
+dashedName: step-13
+---
+
+# --description--
+
+Within your new class, declare an `__init__` method. Give it `self`, `x`, `y`, and `z` as the parameters.
+
+# --hints--
+
+You should define an `__init__` method inside your `R3Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").has_function("__init__")
+ `))
+})
+```
+
+Your `__init__` method should have four parameters `self`, `x`, `y`, and `z`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, x, y, z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
new file mode 100644
index 00000000000..cb7a33c0eb1
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
@@ -0,0 +1,49 @@
+---
+id: 65f407ea37ad6e181b90462e
+title: Step 14
+challengeType: 20
+dashedName: step-14
+---
+
+# --description--
+
+You could assign each `i` parameter to `self.i` as you did before. Although in this case you have few lines to repeat, one way to avoid this repetition is using the `super()` function. `super()` enables you to refer implicitly to the parent class: `super().__init__(x, y)` calls the `__init__` method of the parent class.
+
+Add a `super().__init__(x, y)` call to your `__init__` method.
+
+# --hints--
+
+You should have a `super().__init__(x, y)` call in your `__init__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_stmt("super().__init__(x, y)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
new file mode 100644
index 00000000000..caf708394fc
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
@@ -0,0 +1,47 @@
+---
+id: 65f40f8af784751c613d638a
+title: Step 15
+challengeType: 20
+dashedName: step-15
+---
+
+# --description--
+
+Now, you need to assign `z` to the `z` attribute of your `R3Vector` object.
+
+# --hints--
+
+You should assign `z` to `self.z` after the `super` call.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").is_ordered("super().__init__(x, y)", "self.z = z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
new file mode 100644
index 00000000000..68340ee6c11
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
@@ -0,0 +1,47 @@
+---
+id: 65f40fdb3579aa1ced28b2eb
+title: Step 16
+challengeType: 20
+dashedName: step-16
+---
+
+# --description--
+
+Create an `R3Vector` instance with `2`, `2`, and `3` as the values of `x`, `y`, and `z`, respectively. Assign the new instance to `v2`.
+
+# --hints--
+
+You should declare a variable `v2` and assign it `R3Vector(2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(2, 2, 3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
new file mode 100644
index 00000000000..06b727e3b29
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
@@ -0,0 +1,72 @@
+---
+id: 65f412c208c3791fee305acf
+title: Step 17
+challengeType: 20
+dashedName: step-17
+---
+
+# --description--
+
+In Python, you can enforce the use of keyword-only arguments by adding a `*` as an additional argument to the function or method signature. Modify both `__init__` methods by adding a `*` as the second parameter (after `self`). Every parameter placed after that will require the use of a keyword argument in the function/method call.
+
+This means that you need to modify the `super().__init__(x, y)` call, too. Do it by giving `x` the value `x`, and `y` the value `y`.
+
+Finally, modify the instantiation of `v1` and `v2` by using keyword arguments.
+
+# --hints--
+
+You should enforce keyword arguments by adding a `*` as the second parameter in both your `__init__` methods.
+
+```js
+({ test: () => {
+ assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__init__").has_args("self, *, x, y")`));
+ assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, *, x, y, z")`));
+} })
+```
+
+You should modify your `super.__init__(x, y)` call to use keyword arguments.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").find_body().is_equivalent("super().__init__(x=x, y=y)\\nself.z = z")`)) })
+```
+
+You should modify the assignment of `v1` to be `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R2Vector(x=2, y=3)")`)) })
+```
+
+You should modify the assignment of `v2` to be `R3Vector(x=2, y=2, z=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=2, y=2, z=3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+v2 = R3Vector(2, 2, 3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
new file mode 100644
index 00000000000..ef31cdd6194
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
@@ -0,0 +1,64 @@
+---
+id: 65f4148dea0f802040225e0c
+title: Step 18
+challengeType: 20
+dashedName: step-18
+---
+
+# --description--
+
+Remove the existing `print` calls. Then, as you did before for `v1`, print `v2` and the value returned by `v2.norm()`.
+
+# --hints--
+
+You should not have `print(v1)` and `print(v1.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1.norm())")`));
+ }
+})
+```
+
+You should print `v2` and `v2.norm()`.
+
+```js
+({
+ test: () => {
+ assert(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+print(v1.norm())
+print(v1)
+
+v2 = R3Vector(x=2, y=2, z=3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
new file mode 100644
index 00000000000..1a83f17e994
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
@@ -0,0 +1,64 @@
+---
+id: 65f4520e363e2642f8112e33
+title: Step 19
+challengeType: 20
+dashedName: step-19
+---
+
+# --description--
+
+As you can see, something is not quite right. The `norm` and `__str__` methods inherited from `R2Vector` cannot adapt to a 3-dimensional vector. Their implementation has to be more flexible.
+
+Every object in Python has a special attribute named `__dict__`, which is a dictionary that stores the object attributes.
+
+Remove the existing `print` calls. Then, print the `__dict__` attribute of your `v1` and `v2` vectors to see what they look like.
+
+# --hints--
+
+You should not have `print(v2)` and `print(v2.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+You should print the `__dict__` attribute of `v1` and `v2`.
+
+```js
+({ test: () => assert(runPython(`
+(_Node(_code).has_call("print(v1.__dict__)") and _Node(_code).has_call("print(v2.__dict__)")) or _Node(_code).has_call("print(v1.__dict__, v2.__dict__)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v2.norm())
+print(v2)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
new file mode 100644
index 00000000000..2a2c8f28376
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
@@ -0,0 +1,49 @@
+---
+id: 65f4535bbdb28d436ff3ddc9
+title: Step 20
+challengeType: 20
+dashedName: step-20
+---
+
+# --description--
+
+As you can see from the output, `__dict__` contains the values of your instance attributes. Instead of explicitly adding the squares of `self.x` and `self.y`, you are going to iterate over the values stored in `__dict__` to calculate the value of the norm.
+
+Within the `norm` method body, replace the content of the parentheses with a generator expression that elevates each value `val` in `self.__dict__.values()` to the power of `2`. Also, pass that generator expression as the argument to the `sum` function, so that all the squares are added together before calculating the square root.
+
+# --hints--
+
+You should return `sum(val**2 for val in self.__dict__.values())**0.5` from `norm()` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in self.__dict__.values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
new file mode 100644
index 00000000000..bbb82436c52
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
@@ -0,0 +1,53 @@
+---
+id: 65f870003444fb1a2ad171f2
+title: Step 21
+challengeType: 20
+dashedName: step-21
+---
+
+# --description--
+
+Modify the two `print` calls to print the norm of your vectors and verify that the `norm()` method works fine.
+
+# --hints--
+
+You should print `v1.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1.norm())")`)) })
+```
+
+You should print `v2.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v2.norm())")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
new file mode 100644
index 00000000000..22e3cab792e
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
@@ -0,0 +1,61 @@
+---
+id: 65f8709620b2ce1a62608f5a
+title: Step 23
+challengeType: 20
+dashedName: step-23
+---
+
+# --description--
+
+When you need to dynamically access some attributes starting from a string input, the built-in `getattr()` function is what you need. It takes an object as its first argument, and a string containing the attribute name as its second attribute.
+
+Start to fix the `__str__` method by replacing the string returned by `__str__()` with a generator expression that iterates through the object attributes and calls `getattr()` for each attribute `i`.
+
+# --hints--
+
+You should return a generator expression that iterates over `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_iters()[0].is_equivalent("vars(self)")`)) })
+```
+
+You should return a generator expression that uses `i` as the iteration variable.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_targets()[0].is_equivalent("i")`)) })
+```
+
+You should return a generator expression that calls `getattr(self, i)` for each item `i` in `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_expr().is_equivalent("getattr(self, i)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
new file mode 100644
index 00000000000..668bd89de56
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
@@ -0,0 +1,47 @@
+---
+id: 65f8720685ec351abef26740
+title: Step 24
+challengeType: 20
+dashedName: step-24
+---
+
+# --description--
+
+To obtain a proper string representation, call the `tuple()` constructor and pass it the generator expression you wrote in the previous step as the argument.
+
+# --hints--
+
+You should pass the expression returned by the `__str__` method to the `tuple()` constructor.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("tuple(getattr(self, i) for i in vars(self))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return (getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
new file mode 100644
index 00000000000..789f37ee6fe
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
@@ -0,0 +1,47 @@
+---
+id: 65f872a0fe6aa21b456ad4fe
+title: Step 25
+challengeType: 20
+dashedName: step-25
+---
+
+# --description--
+
+Finally, pass the `tuple()` call as the argument to the `str()` function.
+
+# --hints--
+
+You should pass the `tuple()` call you are currently returning from the `__str__` method to the `str()` function.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("str(tuple(getattr(self, i) for i in vars(self)))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return tuple(getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
new file mode 100644
index 00000000000..6a2c44baef5
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
@@ -0,0 +1,56 @@
+---
+id: 65f8749b13774b1d2e4a7fba
+title: Step 27
+challengeType: 20
+dashedName: step-27
+---
+
+# --description--
+
+While the `__str__` method returns a human-readable string representation of an object, the `__repr__` method is supposed to return the string needed to instantiate the object.
+
+Add a `__repr__` method with a `self` parameter within the `R2Vector` class.
+
+# --hints--
+
+Your `R2Vector` class should have a `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__repr__")`)) })
+```
+
+Your `__repr__` method should have a `self` parameter.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_args("self")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
new file mode 100644
index 00000000000..7f5a3e0f9c9
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
@@ -0,0 +1,74 @@
+---
+id: 65f876d17832001e8e1abb05
+title: Step 28
+challengeType: 20
+dashedName: step-28
+---
+
+# --description--
+
+Declare a variable `arg_list`. Give it the value of a list comprehension that iterates over `key` and `val` for each key-value pair in `vars(self).items()` and computes the f-string `f'{key}={val}'` at each iteration.
+
+# --hints--
+
+You should declare a variable `arg_list`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_variable("arg_list")`)) })
+```
+
+You should assign a list comprehension that iterates over `vars(self).items()` to `arg_list`.
+
+```js
+({ test: () => runPython(`
+import ast
+var = _Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list")
+assert isinstance(var.tree.value, ast.ListComp), "Expected arg_list to be a list comprehension"
+assert (actual := var.find_comp_iters()[0].is_equivalent("vars(self).items()")), f"Expected vars(self).items(), got {actual}"
+`) })
+```
+
+The list comprehension assigned to `arg_list` should use `key` and `val` to iterate over `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_targets()[0].is_equivalent("key, val")
+`)) })
+```
+
+The list comprehension assigned to `arg_list` should compute the string `f'{key}={val}'` for each key-value pair in `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_expr().is_equivalent("f'{key}={val}'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
new file mode 100644
index 00000000000..0c56316394e
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
@@ -0,0 +1,50 @@
+---
+id: 65f93acbb514857003510e79
+title: Step 29
+challengeType: 20
+dashedName: step-29
+---
+
+# --description--
+
+Declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+# --hints--
+
+You should declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("args").is_equivalent("args = ', '.join(arg_list)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
new file mode 100644
index 00000000000..e826611fa57
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
@@ -0,0 +1,52 @@
+---
+id: 65f93b67169a9c703264458a
+title: Step 30
+challengeType: 20
+dashedName: step-30
+---
+
+# --description--
+
+Since the method should return the string to instantiate the object for `R2Vector` as well as `R3Vector` when inherited, you cannot build the string specifying the class name.
+
+You can access the name of a class with `__class__.__name__`. Add a `return` statement to the `__repr__` method and return the string necessary to instantiate the object.
+
+# --hints--
+
+You should use `__class__.__name__` to build the f-string needed to instantiate a vector object and return it from the `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_return("f'{self.__class__.__name__}({args})'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
new file mode 100644
index 00000000000..13682539c2c
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
@@ -0,0 +1,57 @@
+---
+id: 65f93d4647ce2670dc6f095c
+title: Step 31
+challengeType: 20
+dashedName: step-31
+---
+
+# --description--
+
+The `__repr__` method is called under the hood by the `repr` function. Verify that `__repr__` works properly by adding `f'\nrepr = {repr(v1)}'` and `f'\nrepr = {repr(v2)}'` as the second argument to your first and second `print` calls, respectively.
+
+# --hints--
+
+You should add `f'\nrepr = {repr(v1)}'` as the second argument to your `print(f'v1 = {v1}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}', f'\\\\nrepr = {repr(v1)}')")`)) })
+```
+
+You should add `f'\nrepr = {repr(v2)}'` as the second argument to your `print(f'v2 = {v2}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}', f'\\\\nrepr = {repr(v2)}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
new file mode 100644
index 00000000000..a25da243ba9
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
@@ -0,0 +1,56 @@
+---
+id: 65f93e54a9121571dcdd3e79
+title: Step 32
+challengeType: 20
+dashedName: step-32
+---
+
+# --description--
+
+The output is correct, `repr` is giving you the string required to instantiate the objects.
+
+Now comment out both your `print` calls.
+
+# --hints--
+
+You should comment out both your `print()` calls.
+
+```js
+({ test: () => {
+ assert.match(code, /#\s*print\s*\(\s*f('|")v1 = \{\s*v1\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v1\s*\)\s*\}\2\s*\)/);
+ assert.match(code, /#\s*print\s*\(\s*f('|")v2 = \{\s*v2\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v2\s*\)\s*\}\2\s*\)/);
+} })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
new file mode 100644
index 00000000000..127f701ba31
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
@@ -0,0 +1,62 @@
+---
+id: 65f9b17a638f0d0dcce8c354
+title: Step 38
+challengeType: 20
+dashedName: step-38
+---
+
+# --description--
+
+To create a vector space, you need to define how vectors should behave in several cases. Vectors can be added, forming a new vector.
+
+The special method `__add__` can be implemented to override what happens by default when two objects are added together using the `+` operator.
+
+Right now, trying to add two instances of `R2Vector` or `R3Vector` would raise an exception. Create an empty `__add__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define an `__add__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__add__")`)) })
+```
+
+Your `__add__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
new file mode 100644
index 00000000000..f90c14fe57b
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b486989cb90ff3e77ac8
+title: Step 39
+challengeType: 20
+dashedName: step-39
+---
+
+# --description--
+
+The `other` parameter of your `__add__` method represents the operand placed at the right side of the `+` operator in an addition operation.
+
+You want to verify that the right-hand operand is not an object of the same class as the left-hand operand (i.e. `self`). Create an `if` statement that verifies that by checking the type of the operands.
+
+# --hints--
+
+You should create an `if` statement that checks if `type(self)` and `type(other)` are different.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
new file mode 100644
index 00000000000..1fa83e0f9aa
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b9710cca621244d3bde1
+title: Step 40
+challengeType: 20
+dashedName: step-40
+---
+
+# --description--
+
+In Python, `NotImplemented` is a special value used to indicate that an operation is not implemented for a specific case.
+
+`NotImplemented` does not raise an exception immediately. Instead, it signals to ask to the other operand how to perform the operation. If the request cannot be satisfied, a `TypeError` is returned by default.
+
+Because you want to be able to sum two vectors only if they belong to the same class, return `NotImplemented` from the `if` statement you created in the previous step.
+
+# --hints--
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
new file mode 100644
index 00000000000..9df77e46895
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
@@ -0,0 +1,58 @@
+---
+id: 65f9bb7c0d524612b2a88a4b
+title: Step 41
+challengeType: 20
+dashedName: step-41
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_stmt("kwargs = {}")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
new file mode 100644
index 00000000000..f5d28e43bd6
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
@@ -0,0 +1,92 @@
+---
+id: 65f9bc10a9fb1612e066e9e8
+title: Step 42
+challengeType: 20
+dashedName: step-42
+---
+
+# --description--
+
+When adding two vectors, each component of one vector is added to the same component of the other vector. For example, adding `(1, 2)` and `(2, 4)` generates a third vector `(3, 6)`, where `3` is the sum of `1` and `2` and `6` is the sum of `2` and `4`.
+
+The `kwargs` dictionary will contain the key-value pairs needed to instantiate a new vector of the same class of the two vectors added together.
+
+Turn the empty dictionary into a dictionary comprehension that iterates through `vars(self)` and for each key (`i`) creates a key-value pair, where the key is the same key of the current iteration and its value is the sum of the values of the `i` attributes of the two operands.
+
+# --hints--
+
+You should turn the empty dictionary assigned to `kwargs` into a dictionary comprehension that iterates over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_iters()[0].is_equivalent("vars(self)")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_key().is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the sum of the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i` in `vars(self)`. Use the `getattr()` function for that.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) + getattr(other, i)") or node.is_equivalent("getattr(other, i) + getattr(self, i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
new file mode 100644
index 00000000000..d1cd1755778
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
@@ -0,0 +1,70 @@
+---
+id: 65f9c2c2006feb1428ad2d4c
+title: Step 43
+challengeType: 20
+dashedName: step-43
+---
+
+# --description--
+
+You can unpack a dictionary into keyword arguments by using the `**` operator:
+
+```py
+def spam(a, b):
+ return a + b
+
+my_dict = {a: 11, b: 4}
+
+spam(**my_dict) # 15
+```
+
+Return an instance of the current class by using `__class__` and passing `**kwargs` as the argument.
+
+# --hints--
+
+You should return `self.__class__(**kwargs)` from the `__add__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
new file mode 100644
index 00000000000..689ab778fe5
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
@@ -0,0 +1,90 @@
+---
+id: 65f9cb678070ca1668898c70
+title: Step 44
+challengeType: 20
+dashedName: step-44
+---
+
+# --description--
+
+In the same way `__add__` is called under the hood when two objects are added together, the `__sub__` method is called implicitly in case of subtraction.
+
+Now, define an empty `__sub__` method and give two parameters: `self`, and `other`. Inside your new method, create an if statement to check if `self` and `other` do not belong to the same class and return `NotImplemented`, as you did previously.
+
+# --hints--
+
+You should define a `__sub__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__sub__")
+ `))
+})
+```
+
+Your `__sub__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_args("self, other")
+ `))
+})
+```
+
+You should create an `if` statement that checks if `self` and `other` does not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+ `))
+})
+```
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
new file mode 100644
index 00000000000..2d452d2413e
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
@@ -0,0 +1,89 @@
+---
+id: 65f9dd6e5a08af19c196c2df
+title: Step 45
+challengeType: 20
+dashedName: step-45
+---
+
+# --description--
+
+The vector resulting from the subtraction of one vector from another is obtained by calculating the difference of each of their components. For example, subtracting `(2, 4)` from `(7, 3)` generates a third vector `(5, -1)`, where `5` is the difference between `7` and `2` and `-1` is the difference between `3` and `4`.
+
+As you did before inside the `__add__` method, declare a `kwargs` variable after the `if` statement. Assign it a dictionary comprehension that iterates through the object attributes and creates a key-value pair for each key `i`, where the key is the same key as the current iteration and its value is the difference between the values of the `i` attributes of two operands.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it a dictionary comprehension that iterates over the object attributes.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_iters()[0]
+node.is_equivalent("vars(self)") or node.is_equivalent("self.__dict__")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over the object attributes.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_key().is_equivalent("i")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the difference between the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i`.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) - getattr(other, i)") or node.is_equivalent("self.__getattribute__(i) - other.__getattribute__(i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
new file mode 100644
index 00000000000..095bce27c7c
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
@@ -0,0 +1,65 @@
+---
+id: 65f9dfd2e75e291a38695f13
+title: Step 46
+challengeType: 20
+dashedName: step-46
+---
+
+# --description--
+
+Finally, return a new vector object. Use `__class__` and unpack `kwargs` to instantiate the new vector.
+
+# --hints--
+
+You should return a new vector using `__class__` and unpacking `kwargs` from the `__sub__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
new file mode 100644
index 00000000000..c5cb7742541
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
@@ -0,0 +1,67 @@
+---
+id: 65f9e0a578b22c1a736f3d82
+title: Step 47
+challengeType: 20
+dashedName: step-47
+---
+
+# --description--
+
+Modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+# --hints--
+
+You should modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v2 = R2Vector(x=0.5, y=1.25)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
new file mode 100644
index 00000000000..1d277671da4
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
@@ -0,0 +1,67 @@
+---
+id: 65fa8d5cf0ef3b141010f5d8
+title: Step 48
+challengeType: 20
+dashedName: step-48
+---
+
+# --description--
+
+It's time to verify that the addition and subtraction operations work as expected. Declare another variable `v3` and assign it the sum of `v1` plus `v2`.
+
+# --hints--
+
+You should declare a variable `v3` and assign it the sum of `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v3 = v1 + v2") or _Node(_code).has_stmt("v3 = v2 + v1")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
new file mode 100644
index 00000000000..87ddac5ea5f
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
@@ -0,0 +1,64 @@
+---
+id: 65fa8df56a0e2c149b4d24fe
+title: Step 49
+challengeType: 20
+dashedName: step-49
+---
+
+# --description--
+
+Next, check the new vector by printing the following f-string `f'v1 + v2 = {v3}'`.
+
+# --hints--
+
+You should print `f'v1 + v2 = {v3}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 + v2 = {v3}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
new file mode 100644
index 00000000000..e526a9cd4cc
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
@@ -0,0 +1,77 @@
+---
+id: 65fa9402d1fb5516aa42159d
+title: Step 50
+challengeType: 20
+dashedName: step-50
+---
+
+# --description--
+
+Feel free to modify `v3` so that it sums an `R2Vector` instance with an object of a different type, such as an integer or a string. You will be able to see a `TypeError` message printed on the console.
+
+Then, restore the original line and create a new variable `v4`. Assign the difference between `v1` and `v2` to your new variable and print the result following the same structure as the previous f-string.
+
+# --hints--
+
+You should declare a variable `v4` and assign it the difference between `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v4 = v1 - v2")
+ `))
+})
+```
+
+You should print `f'v1 - v2 = {v4}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 - v2 = {v4}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
new file mode 100644
index 00000000000..d2df1c3038d
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
@@ -0,0 +1,85 @@
+---
+id: 65fa9e1b6c6db919385359ec
+title: Step 51
+challengeType: 20
+dashedName: step-51
+---
+
+# --description--
+
+The special method `__mul__` can be implemented to specify what should happen when the current instance is multiplied by another object.
+
+Create an empty `__mul__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `__mul__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__mul__")
+ `))
+})
+```
+
+Your `__mul__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__mul__").has_args("self, other")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
new file mode 100644
index 00000000000..0a18b8b69d1
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
@@ -0,0 +1,94 @@
+---
+id: 65faaed8f7a9772f023ea816
+title: Step 52
+challengeType: 20
+dashedName: step-52
+---
+
+# --description--
+
+Vectors can be multiplied by a *scalar*, i.e. a number that multiplies each single component. The result of scalar multiplication is a vector with the same orientation as the original vector but a different magnitude.
+
+Implement the scalar multiplication by checking if `other` is either an `int` or a `float`. If it is, return a new instance of the current class that has each component of the starting vector multiplied by `other`. This will be the vector resulting from the scalar multiplication.
+
+Make sure the methods can be applied to compute the scalar multiplication of vectors with any number of dimensions.
+
+# --hints--
+
+Your method should return a new instance of the current class only when the type of `other` is either `int` or `float`.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=0, y=0)
+v2 = R3Vector(x=0, y=0, z=0)
+types = ["", True, [], {}]
+assert all((v1 * i) is None for i in types)
+types = [1, 1.0]
+assert all(type(v1 * i) is type(v1) for i in types)
+assert all(type(v2 * i) is type(v2) for i in types)
+`) })
+```
+
+The vector resulting from the scalar multiplication should have each component of the starting vector multiplied by the scalar.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=1, y=1.5)
+v2 = R3Vector(x=2.2, y=3, z=-1)
+assert vars(v1 * 3) == vars(R2Vector(x=3, y=4.5))
+assert vars(v2 * (-2.0)) == vars(R3Vector(x=-4.4, y=-6.0, z=2.0))
+`) })
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
new file mode 100644
index 00000000000..bcf1d3d0b55
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
@@ -0,0 +1,79 @@
+---
+id: 65fc87e19930a503e5f05500
+title: Step 53
+challengeType: 20
+dashedName: step-53
+---
+
+# --description--
+
+A vector can be multiplied by another vector, too. This operation is called *dot product*, or *scalar product*.
+
+Create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+You are going to implement the dot product inside this block during the next step.
+
+# --hints--
+
+You should create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__mul__").find_ifs()[0].find_conditions()[1]
+node.is_equivalent("type(self) == type(other)") or node.is_equivalent("type(other) == type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
new file mode 100644
index 00000000000..c5edc6d9b45
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
@@ -0,0 +1,87 @@
+---
+id: 65fc899d77495504d6deeccc
+title: Step 54
+challengeType: 20
+dashedName: step-54
+---
+
+# --description--
+
+The scalar product between two vectors $\mathbf{a}$ and $\mathbf{b}$ is indicated as:
+
+\\( \mathbf{a} \cdot \mathbf{b} = a_1 \cdot b_1 + a_2 \cdot b_2 + \ldots + a_n \cdot b_n = \sum_{i=1}^{n} a_i \cdot b_i \\)
+
+Where each component of $\mathbf{a}$ is multiplied by the correspondent component of $\mathbf{b}$, and all the products are summed together, resulting in a number.
+
+Within the `elif` clause, implement the above formula to compute the result of a scalar product and return the result. Remember that your implementation must be valid for any vector, independently from the number of components, when the method is inherited.
+
+# --hints--
+
+You should implement the scalar product calculation and return the result inside the `elif` body of your `__mul__` method.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+v3 = R3Vector(x=2, y=3, z=1.5)
+v4 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1*v2 == 4.75 and v3*v4 == 7.0
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
new file mode 100644
index 00000000000..36b78391926
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
@@ -0,0 +1,78 @@
+---
+id: 65fc8e7c766ab1070213aadb
+title: Step 55
+challengeType: 20
+dashedName: step-55
+---
+
+# --description--
+
+In case `other` is not an integer, a floating point number, or another instance of the current class, no product can be computed.
+
+After the `elif` clause, return `NotImplemented`.
+
+# --hints--
+
+You should return `NotImplemented` after the `elif` clause.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__mul__").has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
new file mode 100644
index 00000000000..bf365bd4903
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
@@ -0,0 +1,82 @@
+---
+id: 65fc8fa7e7860407ab479bf0
+title: Step 56
+challengeType: 20
+dashedName: step-56
+---
+
+# --description--
+
+It's time to test the multiplication. Declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`. Then, call the `print` function and pass it the following f-string: `f'v1 * 3 = {v5}'`.
+
+# --hints--
+
+You should declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * 3")`)) })
+```
+
+You should print the f-string `f'v1 * 3 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * 3 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
new file mode 100644
index 00000000000..034109b8c53
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
@@ -0,0 +1,87 @@
+---
+id: 65fd681b20b7e45f55def415
+title: Step 57
+challengeType: 20
+dashedName: step-57
+---
+
+# --description--
+
+The scalar multiplication works fine. Now, modify the assignment of `v5` to be the dot product `v1 * v2`. Also, update the `print` call.
+
+Before doing that, feel free to experiment and multiply `v1` by an object of invalid type to see the error message printed on the console.
+
+
+# --hints--
+
+You should update the assignment of `v5` assigning it the scalar product `v1 * v2`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * v2")`)) })
+```
+
+You should update your `print` call to print the f-string `f'v1 * v2 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * v2 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * 3
+print(f'v1 * 3 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
new file mode 100644
index 00000000000..f6184775ca4
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9250db0d6b8198cf29ef
+title: Step 58
+challengeType: 20
+dashedName: step-58
+---
+
+# --description--
+
+The `__eq__` method can be implemented to specify what should happen in case the comparison operator (`==`) is used to compare an object with something else.
+
+Within the `R2Vector` class, create an `__eq__` method and give it two parameters: `self` and `other`.
+
+# --hints--
+
+You should define a `__eq__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__eq__")`)) })
+```
+
+Your `__eq__` method should take two parameters: `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
new file mode 100644
index 00000000000..5d2d8cfc678
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
@@ -0,0 +1,88 @@
+---
+id: 65fd95c23beef982af29004c
+title: Step 59
+challengeType: 20
+dashedName: step-59
+---
+
+# --description--
+
+You want to compare two vectors, only when they belong to the same class. For that create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented` in that case.
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
new file mode 100644
index 00000000000..c3bea995dc8
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
@@ -0,0 +1,91 @@
+---
+id: 65fd97f3c1b4c4839bdeb8d2
+title: Step 60
+challengeType: 20
+dashedName: step-60
+---
+
+# --description--
+
+To compare two vectors, you are going to check that each component of the first vector is equal to the same component of the second vector.
+
+After the `if` statement you created in the previous step, return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+# --hints--
+
+The `__eq__` method should return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1 == v2 and not v1 == v3 and v4 == v5 and not v5 == v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
new file mode 100644
index 00000000000..a7f5d701215
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
@@ -0,0 +1,102 @@
+---
+id: 65fd9aa649f6cc84631882a9
+title: Step 61
+challengeType: 20
+dashedName: step-61
+---
+
+# --description--
+
+The `__ne__` method is called under the hood when the `!=` operator is used. Define a `__ne__` method with two parameters `self` and `other`. From your new method, return the opposite of `self == other`.
+
+# --hints--
+
+You should define a `__ne__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ne__")`)) })
+```
+
+Your `__ne__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ne__").has_args("self, other")`)) })
+```
+
+The `__ne__` method should return `False` if each attribute of the current instance is equal to the same attribute of `other` and `True` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+not v1 != v2 and v1 != v3 and not v4 != v5 and v5 != v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
new file mode 100644
index 00000000000..c151f678d86
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
@@ -0,0 +1,86 @@
+---
+id: 65fd9c6e49d7cd8513ab1005
+title: Step 62
+challengeType: 20
+dashedName: step-62
+---
+
+# --description--
+
+At the end of your code, use the equality operator to compare `v1` and `R2Vector(x=2, y=3)` and print the result.
+
+# --hints--
+
+You should print the result of comparing `v1` and `R2Vector(x=2, y=3)` using the equality operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 == R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) == v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
new file mode 100644
index 00000000000..804d4947304
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9d6203afea85931094c9
+title: Step 63
+challengeType: 20
+dashedName: step-63
+---
+
+# --description--
+
+The comparison returns `True`, since the two vectors have the same components. Now, modify the argument of the `print` call you added in the previous step to use the inequality operator.
+
+# --hints--
+
+You should modify the `print` call you added in the previous step using the inequality operator to compare `v1` and `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) != v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 == R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
new file mode 100644
index 00000000000..9255b41f2c6
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
@@ -0,0 +1,97 @@
+---
+id: 65fd9e2c56ff19862dfb8cbb
+title: Step 64
+challengeType: 20
+dashedName: step-64
+---
+
+# --description--
+
+The `__lt__` method is called under the hood when the `<` operator is used to compare an object with something else.
+
+Add an empty `__lt__` method and give it two parameters: `self`, `other`.
+
+# --hints--
+
+You should define a `__lt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__lt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
new file mode 100644
index 00000000000..ee258ff8a2a
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
@@ -0,0 +1,100 @@
+---
+id: 65fdc3c8478ee70fc7966151
+title: Step 65
+challengeType: 20
+dashedName: step-65
+---
+
+# --description--
+
+In the same way you did before for the `__eq__` method, create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
new file mode 100644
index 00000000000..390babbb01f
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
@@ -0,0 +1,91 @@
+---
+id: 65fdc496f4440e1055a2ac1b
+title: Step 66
+challengeType: 20
+dashedName: step-66
+---
+
+# --description--
+
+After the `if` statement, return the result of comparing the norm of the current instance with the norm of `other` using the less than operator.
+
+# --hints--
+
+The `__lt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the `<` operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_return("self.norm() < other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
new file mode 100644
index 00000000000..7193db8cba2
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
@@ -0,0 +1,122 @@
+---
+id: 6601918b44a11b4a8c986c6a
+title: Step 67
+challengeType: 20
+dashedName: step-67
+---
+
+# --description--
+
+The `__gt__` method is called under the hood when the `>` operator is used to compare an object with something else.
+
+After the `__lt__` method, in the same way you did for `__lt__`, implement the `__gt__` method. Pay attention to use the appropriate operator.
+
+# --hints--
+
+You should define a `__gt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__gt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_args("self, other")`)) })
+```
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+The `__gt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the greater than operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_return("self.norm() > other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
new file mode 100644
index 00000000000..fd051c7fca6
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
@@ -0,0 +1,111 @@
+---
+id: 66019258a7c71d4ae50da42e
+title: Step 68
+challengeType: 20
+dashedName: step-68
+---
+
+# --description--
+
+There are still two possible comparisons to implement. The `__le__` method is called when the `<=` operator is used to compare two objects.
+
+Define a `__le__` method with `self` and `other` as the parameters and make it return the opposite of `self > other`.
+
+# --hints--
+
+You should define a `__le__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__le__")`)) })
+```
+
+Your `__le__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_args("self, other")`)) })
+```
+
+Your `__le__` method return the opposite of `self > other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_return("not self > other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
new file mode 100644
index 00000000000..542035862a5
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
@@ -0,0 +1,116 @@
+---
+id: 66019319edb1cb4b57d3a793
+title: Step 69
+challengeType: 20
+dashedName: step-69
+---
+
+# --description--
+
+The last method you need is `__ge__`, which is called when the `>=` is used to compare two objects.
+
+Define a `__ge__` method with `self` and `other` as the parameters and make it return the opposite of `self < other`.
+
+# --hints--
+
+You should define a `__ge__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ge__")`)) })
+```
+
+Your `__ge__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_args("self, other")`)) })
+```
+
+Your `__ge__` method should return the opposite of `self < other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_return("not self < other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
new file mode 100644
index 00000000000..fe9c0cfa362
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
@@ -0,0 +1,104 @@
+---
+id: 660193a2a71faa4bd8f10970
+title: Step 70
+challengeType: 20
+dashedName: step-70
+---
+
+# --description--
+
+Feel free to play around with the new comparison operations you implemented. Then, remove your last `print` call.
+
+
+# --hints--
+
+You should not have `print(v1 != R2Vector(x=2, y=3))` in your code.
+
+```js
+({test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
new file mode 100644
index 00000000000..2157c6b8a3b
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
@@ -0,0 +1,111 @@
+---
+id: 66019977710caa516276c0a8
+title: Step 71
+challengeType: 20
+dashedName: step-71
+---
+
+# --description--
+
+The *cross product*, or *vector product*, is defined between 3-dimensional vectors and results in a third vector perpendicular to both of them.
+
+The `R3Vector` class inherits from `R2Vector`, meaning it has access to all the methods and properties defined in `R2Vector`. A child class can implement additional features. You already saw a way to change the implementation of a method. Now, you are going to give the child class `R3Vector` a new method instead.
+
+Within the `R3Vector` class, define a `cross` method and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `cross` method within the `R3Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").has_function("cross")`)) })
+```
+
+Your `cross` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
new file mode 100644
index 00000000000..b7948eb83c6
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
@@ -0,0 +1,114 @@
+---
+id: 6601a7eb860fb8546516674d
+title: Step 72
+challengeType: 20
+dashedName: step-72
+---
+
+# --description--
+
+Create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
new file mode 100644
index 00000000000..7a7cb7ef03c
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
@@ -0,0 +1,105 @@
+---
+id: 6601a88a6e2ccc550d7d7208
+title: Step 73
+challengeType: 20
+dashedName: step-73
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_variable("kwargs").is_equivalent("kwargs = {}")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
new file mode 100644
index 00000000000..c9e2224dad3
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
@@ -0,0 +1,116 @@
+---
+id: 6601a8fb2e993b55912f9e9f
+title: Step 74
+challengeType: 20
+dashedName: step-74
+---
+
+# --description--
+
+The dot product between two 3D vectors \\( \mathbf{a} \\) and \\( \mathbf{b} \\) can be computed as it follows:
+
+\\[ \mathbf{a} \times \mathbf{b} = \begin{pmatrix} a_yb_z - a_zb_y \\\ a_zb_x - a_xb_z \\\ a_xb_y - a_yb_x \end{pmatrix} \\]
+
+Where the resulting vector is represented as a column vector.
+
+Implement the formula above to compute the dot product between two 3-dimensional vectors and return the resulting vector from the `cross()` method.
+
+# --hints--
+
+The `cross()` method should return a new `R3Vector` instance resulting from the dot product computation.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+v1.cross(v2) == R3Vector(x=4.75, y=-3.5, z=1.0) and v2.cross(v1) == R3Vector(x=-4.75, y=3.5, z=-1.0) and v1.cross(v1) == R3Vector(x=0, y=0, z=0)
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
new file mode 100644
index 00000000000..c1435330d56
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
@@ -0,0 +1,119 @@
+---
+id: 6601ab2809898f57591f2f7f
+title: Step 75
+challengeType: 20
+dashedName: step-75
+---
+
+# --description--
+
+Now, modify the assignments of `v1` and `v2`. Turn them into `R3Vector` instances and pass `z=1` and `z=2` to `v1` and `v2`, respectively.
+
+# --hints--
+
+You should modify the assignment of `v1` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R3Vector(x=2, y=3, z=1)")`)) })
+```
+
+You should modify the assignment of `v2` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=0.5, y=1.25, z=2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+--fcc-editable-region--
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
new file mode 100644
index 00000000000..6904f99b5e1
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
@@ -0,0 +1,113 @@
+---
+id: 6601ac48a2ee6b59e6a5060d
+title: Step 76
+challengeType: 20
+dashedName: step-76
+---
+
+# --description--
+
+Call `cross()` on `v1` and pass `v2` as the argument. Assign this call to a new variable `v6`.
+
+# --hints--
+
+You should declare a variable named `v6` and assign it a call to the `cross()` method on `v1` passing it `v2` as the `argument`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v6").is_equivalent("v6 = v1.cross(v2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
new file mode 100644
index 00000000000..47d13a7bd4d
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
@@ -0,0 +1,210 @@
+---
+id: 6601ad0fe415985a5c83f3cc
+title: Step 77
+challengeType: 20
+dashedName: step-77
+---
+
+# --description--
+
+As a final step, call the `print` function and pass it the f-string `f'v1 x v2 = {v6}'` to see the output of the dot product.
+
+With that, you have completed the vector space project. Well done!
+
+# --hints--
+
+You should print `f'v1 x v2 = {v6}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 x v2 = {v6}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+print(f'v1 x v2 = {v6}')
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
new file mode 100644
index 00000000000..d25b1a4c723
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
@@ -0,0 +1,53 @@
+---
+id: 6659875502b6d7765498f324
+title: Step 26
+challengeType: 20
+dashedName: step-26
+---
+
+# --description--
+
+Use f-strings to modify your `print` calls so that they result in the output `v1 = (2, 3)` and `v2 = (2, 2, 3)`, respectively.
+
+# --hints--
+
+You should use an f-string to interpolate `v1` and generate the output `v1 = (2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}')")`)) })
+```
+
+You should use an f-string to interpolate `v2` and generate the output `v2 = (2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
new file mode 100644
index 00000000000..bc5ffa5f75d
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
@@ -0,0 +1,51 @@
+---
+id: 66680ddfd0f8c76782923cb0
+title: Step 22
+challengeType: 20
+dashedName: step-22
+---
+
+# --description--
+
+The `norm()` method is returning the correct values, but there's still something you can improve: readability.
+
+The `vars()` built-in function takes an object as its argument and returns the `__dict__` attribute of that object.
+
+Instead of directly accessing the `__dict__` attribute of `self`, modify the `norm` method to use the `vars()` function.
+
+# --hints--
+
+You should modify your `norm` method to use `vars(self)` instead of `self.__dict__`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in vars(self).values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
new file mode 100644
index 00000000000..e0f1c196265
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
@@ -0,0 +1,61 @@
+---
+id: 66682150151af29efec9727d
+title: Step 33
+challengeType: 20
+dashedName: step-33
+---
+
+# --description--
+
+The `__getattribute__` method is called under the hood any time you try to access an instance attribute. If the attribute is not found at the instance level, the method will search for it at the class level, and eventually in parent classes.
+
+Inside your class, define a `__getattribute__` method with two parameters, `self` and `attr`, and make it return the string `'calling __getattribute__'`. You'll override momentarily the default implementation just to see how the attribute access works.
+
+# --hints--
+
+You should define a method named `__getattribute__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_args("self, attr")`)) })
+```
+
+Your `__getattribute__` method should return the string `'calling __getattribute__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_return("'calling __getattribute__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
new file mode 100644
index 00000000000..948a541cb76
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
@@ -0,0 +1,61 @@
+---
+id: 666826f258fda1ab3396a509
+title: Step 34
+challengeType: 20
+dashedName: step-34
+---
+
+# --description--
+
+Now, print the result of accessing the `x` attribute of `v1` both with the dot operator and the `getattr()` built-in function.
+
+You will see that `__getattribute__` is called in both cases.
+
+# --hints--
+
+You should print the `x` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.x)") and n.has_call("print(getattr(v1, 'x'))")) or n.has_call("print(v1.x, getattr(v1, 'x'))") or n.has_call("print(getattr(v1, 'x'), v1.x)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
new file mode 100644
index 00000000000..8c3a650010b
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
@@ -0,0 +1,69 @@
+---
+id: 666827a6fd0dbaafe8330ea6
+title: Step 35
+challengeType: 20
+dashedName: step-35
+---
+
+# --description--
+
+`__getattr__` is another special method that plays a role in accessing attributes.
+
+The default implementation of `__getattribute__` is to raise an `AttributeError` when the requested attribute is not an instance attribute or it is not present in the class tree.
+
+In that case, `__getattr__` is called if defined by the class. You can consider it as a sort of fallback when the usual attribute accessing procedure fails.
+
+Turn the `__getattribute__` method into `__getattr__` and modify the string returned by the method into `'calling __getattr__'`.
+
+# --hints--
+
+You should define a method named `__getattr__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_args("self, attr")`)) })
+```
+
+Your `__getattr__` method should return the string `'calling __getattr__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_return("'calling __getattr__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+print(v1.x)
+print(getattr(v1, 'x'))
+
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
new file mode 100644
index 00000000000..598c9822428
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
@@ -0,0 +1,62 @@
+---
+id: 666832e427d70bc5219dc62a
+title: Step 36
+challengeType: 20
+dashedName: step-36
+---
+
+# --description--
+
+As you can see from the output, although you defined `__getattr__` in your class, this method is not called yet. This happens because the default attribute access occurs through `__getattribute__`. Therefore, you can see the attribute value printed on the terminal.
+
+Now modify the last two lines of code to access the `z` attribute of `v1` in both your `print()` calls. This time, you are going to access an attribute that `v1` does not have. As a result, `__getattribute__` will raise an error and `__getattr__` will be called.
+
+# --hints--
+
+You should modify your code to print the `z` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.z)") and n.has_call("print(getattr(v1, 'z'))")) or n.has_call("print(v1.z, getattr(v1, 'z'))") or n.has_call("print(getattr(v1, 'z'), v1.z)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+print(v1.x)
+print(getattr(v1, 'x'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
new file mode 100644
index 00000000000..3f18e7c657c
--- /dev/null
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
@@ -0,0 +1,75 @@
+---
+id: 6668374ed18b7fce10259cb3
+title: Step 37
+challengeType: 20
+dashedName: step-37
+---
+
+# --description--
+
+Now that you have an idea of how the attribute access work, remove the last two lines of your code together with the `__getattr__` method.
+
+Then, restore the `print()` calls you commented out before and delete the second argument from both of them.
+
+# --hints--
+
+You should not have a `__getattr__` method.
+
+```js
+({ test: () => assert.isFalse(runPython(`_Node(_code).find_class("R2Vector").has_function("__getattr__")`)) })
+```
+
+You should not have `print(v1.z)`and `print(getattr(v1, 'z'))` in your code.
+
+```js
+({ test: () => assert.isFalse(runPython(`
+n = _Node(_code)
+n.has_call("print(v1.z)") or n.has_call("print(getattr(v1, 'z'))")
+`)) })
+```
+
+You should restore the `print()` calls you commented out before and remove the second argument from both of them.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).has_call("print(f'v1 = {v1}')") and _Node(_code).has_call("print(f'v2 = {v2}')")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+print(v1.z)
+print(getattr(v1, 'z'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
index f84624b42de..e9870c4826a 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
@@ -1,6 +1,6 @@
---
id: 6553ed69ece88d29594748aa
-title: Step 50
+title: Step 52
challengeType: 20
dashedName: step-52
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
index bf46d6f32ca..36913664567 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
@@ -1,6 +1,6 @@
---
id: 6553efd6ada3f42aa2d75448
-title: Step 51
+title: Step 53
challengeType: 20
dashedName: step-53
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
index 2688363421c..bdc61a56deb 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
@@ -1,6 +1,6 @@
---
id: 6553f3fc92741c2bf8ded140
-title: Step 52
+title: Step 54
challengeType: 20
dashedName: step-54
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
index 16b2b7a8c78..c54923b4ea2 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
@@ -1,6 +1,6 @@
---
id: 6553f4f66099802c6ae94613
-title: Step 53
+title: Step 55
challengeType: 20
dashedName: step-55
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
index bcae9e4c2a5..92734e07289 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
@@ -1,6 +1,6 @@
---
id: 6553f6086add4b2cbb99fd78
-title: Step 54
+title: Step 56
challengeType: 20
dashedName: step-56
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
index 2f0fc79d3ff..1355edcf141 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
@@ -1,6 +1,6 @@
---
id: 6553f8c570f9982e013a8886
-title: Step 55
+title: Step 57
challengeType: 20
dashedName: step-57
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
index 51c7c51620d..5b984de7d3b 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
@@ -1,6 +1,6 @@
---
id: 655491bd5b98b813fa5bedca
-title: Step 56
+title: Step 58
challengeType: 20
dashedName: step-58
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
index 64bef622b35..b6a7f0aa9c6 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
@@ -1,6 +1,6 @@
---
id: 6554930320d70414e7b6acc6
-title: Step 57
+title: Step 59
challengeType: 20
dashedName: step-59
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
index c2b67a816d2..ab8d95e137d 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
@@ -1,6 +1,6 @@
---
id: 65549561463f0016876e852c
-title: Step 58
+title: Step 60
challengeType: 20
dashedName: step-60
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
index 5d4a37a2fe9..839352832e3 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
@@ -1,6 +1,6 @@
---
id: 65549f90cf78131c96ebcf28
-title: Step 59
+title: Step 61
challengeType: 20
dashedName: step-61
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
index 4c05b0584c4..01181c37df7 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
@@ -1,6 +1,6 @@
---
id: 6554a334a40edb1fb4eff827
-title: Step 60
+title: Step 62
challengeType: 20
dashedName: step-62
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
index 63e5be90540..921879d9acc 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
@@ -1,6 +1,6 @@
---
id: 6554a49a4f782f208abcc87e
-title: Step 61
+title: Step 63
challengeType: 20
dashedName: step-63
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
index c8c045af50c..139a3fea8db 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
@@ -1,6 +1,6 @@
---
id: 6554a57ec0a2c52106e7ee50
-title: Step 62
+title: Step 64
challengeType: 20
dashedName: step-64
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
index f8aec7c6f01..b1c21af09e5 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
@@ -1,6 +1,6 @@
---
id: 6554a88d5af937226f4a9121
-title: Step 63
+title: Step 65
challengeType: 20
dashedName: step-65
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
index 9f67d3e0905..2bff453ec4b 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
@@ -1,6 +1,6 @@
---
id: 6554ac937a49be2701af4f2f
-title: Step 64
+title: Step 66
challengeType: 20
dashedName: step-66
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
index d9b8dbfc283..4c7bb7ab462 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
@@ -1,6 +1,6 @@
---
id: 6554ad2463b8892748f8efdd
-title: Step 65
+title: Step 67
challengeType: 20
dashedName: step-67
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
index e2ed67b3ab6..1eeeb3697b1 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
@@ -1,6 +1,6 @@
---
id: 6554d0332949b133a0b35eaa
-title: Step 66
+title: Step 68
challengeType: 20
dashedName: step-68
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
index 863de41bbc0..5f093f3df2c 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
@@ -1,6 +1,6 @@
---
id: 6554d15c8acb5f34499ad789
-title: Step 67
+title: Step 69
challengeType: 20
dashedName: step-69
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
index c24fa10d6c6..65ac8f3f6c4 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
@@ -1,6 +1,6 @@
---
id: 6554d25dc5ceaa354307a77e
-title: Step 68
+title: Step 70
challengeType: 20
dashedName: step-70
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
index 076f1a41e91..2df3eb6fceb 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
@@ -1,6 +1,6 @@
---
id: 6554de295ade563a069936a1
-title: Step 69
+title: Step 71
challengeType: 20
dashedName: step-71
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
index 9793f1023c3..5e52b90279e 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
@@ -1,6 +1,6 @@
---
id: 6554dfce1683be3c0c9609a6
-title: Step 70
+title: Step 72
challengeType: 20
dashedName: step-72
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
index 9454a27cb5e..02e14d9019c 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
@@ -1,6 +1,6 @@
---
id: 6554e0adc7bb193cbfdb36d5
-title: Step 71
+title: Step 73
challengeType: 20
dashedName: step-73
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
index 182346eca82..7f91537aead 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
@@ -1,6 +1,6 @@
---
id: 6554e2ee23bfd93f2c83640f
-title: Step 72
+title: Step 74
challengeType: 20
dashedName: step-74
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
index 48ececac1ab..d5bdb7ff5d1 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
@@ -1,6 +1,6 @@
---
id: 6554e343caea913ffba7bec6
-title: Step 73
+title: Step 75
challengeType: 20
dashedName: step-75
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
index 368cf69b225..a80c318bd1d 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
@@ -1,6 +1,6 @@
---
id: 655516e410b8e30fb4fb64e8
-title: Step 74
+title: Step 76
challengeType: 20
dashedName: step-76
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
index 22de7de4fa0..82e1790a7d8 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
@@ -1,6 +1,6 @@
---
id: 65551a628bcb7e121e32d04b
-title: Step 77
+title: Step 79
challengeType: 20
dashedName: step-79
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
index 7f0ec8191b3..8603eb7e6d8 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
@@ -1,6 +1,6 @@
---
id: 6555201d9b7fc917399f9f0b
-title: Step 78
+title: Step 80
challengeType: 20
dashedName: step-80
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
index 01549558a4b..5c6c8181984 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
@@ -1,6 +1,6 @@
---
id: 655520c20cb1e6177b0641d6
-title: Step 79
+title: Step 81
challengeType: 20
dashedName: step-81
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
index cc4f4eacee1..db091c232cc 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
@@ -1,6 +1,6 @@
---
id: 655522883e66f618e03a9411
-title: Step 80
+title: Step 82
challengeType: 20
dashedName: step-82
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
index cd29fc36bb4..9588d739f44 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
@@ -1,6 +1,6 @@
---
id: 6555231eac4d9f19bd3d44b5
-title: Step 81
+title: Step 83
challengeType: 20
dashedName: step-83
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
index c02b037de64..b8c910a3aa5 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
@@ -1,6 +1,6 @@
---
id: 65552a111190e11f0963949e
-title: Step 82
+title: Step 84
challengeType: 20
dashedName: step-84
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
index eb0c5d14c63..28da95df2b0 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
@@ -1,6 +1,6 @@
---
id: 65552a9593755e1fb2f5ab50
-title: Step 83
+title: Step 85
challengeType: 20
dashedName: step-85
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
index aa1a050cf04..4fcaff7b89c 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
@@ -1,6 +1,6 @@
---
id: 65552b14e803731fe3c1e4ca
-title: Step 84
+title: Step 86
challengeType: 20
dashedName: step-86
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
index 3b6cc0579a3..f8ea2a67964 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
@@ -1,6 +1,6 @@
---
id: 65553159615a8123b190ee43
-title: Step 85
+title: Step 87
challengeType: 20
dashedName: step-87
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
index 1e3ad3dfb8a..6799724af14 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
@@ -1,6 +1,6 @@
---
id: 6555d6e12c95701172b55709
-title: Step 75
+title: Step 77
challengeType: 20
dashedName: step-77
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
index f3c3b93e0c6..97049b3b537 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
@@ -1,6 +1,6 @@
---
id: 6555d8b0b3d20b128bdadd37
-title: Step 76
+title: Step 78
challengeType: 20
dashedName: step-78
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
index 866b80d387b..d310105bfe1 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
@@ -1,6 +1,6 @@
---
id: 6555db4a7b788e15795674e5
-title: Step 87
+title: Step 89
challengeType: 20
dashedName: step-89
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
index 2cf86f2dd96..3a91139cf33 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
@@ -1,6 +1,6 @@
---
id: 6555df0c81300b175308557d
-title: Step 88
+title: Step 90
challengeType: 20
dashedName: step-90
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
index 959034b7875..bc5788b45f8 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
@@ -1,6 +1,6 @@
---
id: 6555e1bfcd374e18c6be8e58
-title: Step 89
+title: Step 91
challengeType: 20
dashedName: step-91
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
index 791d9bdbd6d..4d7848b4be9 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
@@ -1,6 +1,6 @@
---
id: 6555e3f387381a19d5e00333
-title: Step 90
+title: Step 92
challengeType: 20
dashedName: step-92
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
index 20f69b6bd24..e895a41b321 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
@@ -1,6 +1,6 @@
---
id: 6555e43e783ed31a0532b1b2
-title: Step 91
+title: Step 93
challengeType: 20
dashedName: step-93
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
index 9acf44cfdc2..f878bb6c12b 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
@@ -1,6 +1,6 @@
---
id: 6555e547c18a2b1a7b795bd8
-title: Step 93
+title: Step 95
challengeType: 20
dashedName: step-95
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
index 312d322e32f..9b3df4758a0 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
@@ -1,6 +1,6 @@
---
id: 6555e5991af57d1ae0e35f0a
-title: Step 94
+title: Step 96
challengeType: 20
dashedName: step-96
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
index 3493c823d5d..1bb2f8f1567 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
@@ -1,6 +1,6 @@
---
id: 65a450e8fb2c9d75c7378d28
-title: Step 86
+title: Step 88
challengeType: 20
dashedName: step-88
---
diff --git a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
index a15a486b7eb..29a960e8277 100644
--- a/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
+++ b/curriculum/challenges/swahili/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
@@ -1,6 +1,6 @@
---
id: 65a51c9e000b660122b8b29e
-title: Step 92
+title: Step 94
challengeType: 20
dashedName: step-94
---
diff --git a/curriculum/challenges/swahili/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md b/curriculum/challenges/swahili/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
deleted file mode 100644
index 632abe728dd..00000000000
--- a/curriculum/challenges/swahili/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
+++ /dev/null
@@ -1,344 +0,0 @@
----
-id: 62aa1fed3d4e873366ff3131
-title: Step 150
-challengeType: 0
-dashedName: step-150
----
-
-# --description--
-
-In your `attack` function, below the `health` variable, create an `if` statement. Set the condition to call the `isMonsterHit` function.
-
-# --hints--
-
-You should add an `if` statement which calls `isMonsterHit` in the condition.
-
-```js
-assert.match(attack.toString(), /if\s*\(\s*isMonsterHit\s*\(\s*\)/)
-```
-
-# --seed--
-
-## --seed-contents--
-
-```html
-
-
-
-
-
-
+
+Within the `Vector` class, create an `__init__` method and give it three parameters, `self`, `x`, and `y`.
+
+# --hints--
+
+You should define an `__init__` method inside the `Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").has_function("__init__")`)) })
+```
+
+Your `__init__` method should take three parameters: `self`, `x`, and `y`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("Vector").find_function("__init__").has_args("self, x, y")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ pass
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
new file mode 100644
index 00000000000..62ab349a8db
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f055b9190fc41ca35549b8.md
@@ -0,0 +1,38 @@
+---
+id: 65f055b9190fc41ca35549b8
+title: Step 3
+challengeType: 20
+dashedName: step-3
+---
+
+# --description--
+
+Python offers various methods that include both a leading and trailing double underscore in their names. You may already be familiar with some, such as `__init__` and `__str__`. These methods, which follow the `__
+
+So far, you created a 2-dimensional vector. You want to be able to represent vectors with a different number of dimensions without rewriting the necessary code for each specific case. For that, you will use inheritance.
+
+Start by renaming the `Vector` class into `R2Vector` to specify that this class is going to deal with 2-dimensional vectors. Remember to modify the instantiation of `v1`, too.
+
+# --hints--
+
+You should rename the `Vector` class into `R2Vector`. Remember to modify the instantiation of `v1`, too.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+v1 = Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
new file mode 100644
index 00000000000..e26a20b0730
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40051d6b09a139f253e8e.md
@@ -0,0 +1,70 @@
+---
+id: 65f40051d6b09a139f253e8e
+title: Step 12
+challengeType: 20
+dashedName: step-12
+---
+
+# --description--
+
+Inheritance enables you to define a class from an existing one. The new class, called child, inherits all the methods and properties of the existing class, called parent.
+
+```py
+class Tree:
+ def sprout(self):
+ print('Making new leaves!')
+
+class Oak(Tree):
+ pass
+
+Oak().sprout() # Output: Making new leaves!
+```
+
+In the example above, the child class `Oak` inherits from `Tree` and inherits the `sprout` method from the parent class `Tree`.
+
+Create a new class named `R3Vector` and follow the example above to make it inherit from the `R2Vector` class.
+
+# --hints--
+
+You should define a new class `R3Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_class("R3Vector")
+ `))
+})
+```
+
+Your new class `R3Vector` should inherit from `R2Vector`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").inherits_from("R2Vector")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
new file mode 100644
index 00000000000..c50cbefeb4a
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40401e6ef53173c04e27d.md
@@ -0,0 +1,56 @@
+---
+id: 65f40401e6ef53173c04e27d
+title: Step 13
+challengeType: 20
+dashedName: step-13
+---
+
+# --description--
+
+Within your new class, declare an `__init__` method. Give it `self`, `x`, `y`, and `z` as the parameters.
+
+# --hints--
+
+You should define an `__init__` method inside your `R3Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").has_function("__init__")
+ `))
+})
+```
+
+Your `__init__` method should have four parameters `self`, `x`, `y`, and `z`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, x, y, z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
new file mode 100644
index 00000000000..cb7a33c0eb1
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f407ea37ad6e181b90462e.md
@@ -0,0 +1,49 @@
+---
+id: 65f407ea37ad6e181b90462e
+title: Step 14
+challengeType: 20
+dashedName: step-14
+---
+
+# --description--
+
+You could assign each `i` parameter to `self.i` as you did before. Although in this case you have few lines to repeat, one way to avoid this repetition is using the `super()` function. `super()` enables you to refer implicitly to the parent class: `super().__init__(x, y)` calls the `__init__` method of the parent class.
+
+Add a `super().__init__(x, y)` call to your `__init__` method.
+
+# --hints--
+
+You should have a `super().__init__(x, y)` call in your `__init__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").has_stmt("super().__init__(x, y)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
new file mode 100644
index 00000000000..caf708394fc
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40f8af784751c613d638a.md
@@ -0,0 +1,47 @@
+---
+id: 65f40f8af784751c613d638a
+title: Step 15
+challengeType: 20
+dashedName: step-15
+---
+
+# --description--
+
+Now, you need to assign `z` to the `z` attribute of your `R3Vector` object.
+
+# --hints--
+
+You should assign `z` to `self.z` after the `super` call.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R3Vector").find_function("__init__").is_ordered("super().__init__(x, y)", "self.z = z")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+--fcc-editable-region--
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
new file mode 100644
index 00000000000..68340ee6c11
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f40fdb3579aa1ced28b2eb.md
@@ -0,0 +1,47 @@
+---
+id: 65f40fdb3579aa1ced28b2eb
+title: Step 16
+challengeType: 20
+dashedName: step-16
+---
+
+# --description--
+
+Create an `R3Vector` instance with `2`, `2`, and `3` as the values of `x`, `y`, and `z`, respectively. Assign the new instance to `v2`.
+
+# --hints--
+
+You should declare a variable `v2` and assign it `R3Vector(2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(2, 2, 3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
new file mode 100644
index 00000000000..06b727e3b29
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f412c208c3791fee305acf.md
@@ -0,0 +1,72 @@
+---
+id: 65f412c208c3791fee305acf
+title: Step 17
+challengeType: 20
+dashedName: step-17
+---
+
+# --description--
+
+In Python, you can enforce the use of keyword-only arguments by adding a `*` as an additional argument to the function or method signature. Modify both `__init__` methods by adding a `*` as the second parameter (after `self`). Every parameter placed after that will require the use of a keyword argument in the function/method call.
+
+This means that you need to modify the `super().__init__(x, y)` call, too. Do it by giving `x` the value `x`, and `y` the value `y`.
+
+Finally, modify the instantiation of `v1` and `v2` by using keyword arguments.
+
+# --hints--
+
+You should enforce keyword arguments by adding a `*` as the second parameter in both your `__init__` methods.
+
+```js
+({ test: () => {
+ assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__init__").has_args("self, *, x, y")`));
+ assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").has_args("self, *, x, y, z")`));
+} })
+```
+
+You should modify your `super.__init__(x, y)` call to use keyword arguments.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("__init__").find_body().is_equivalent("super().__init__(x=x, y=y)\\nself.z = z")`)) })
+```
+
+You should modify the assignment of `v1` to be `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R2Vector(x=2, y=3)")`)) })
+```
+
+You should modify the assignment of `v2` to be `R3Vector(x=2, y=2, z=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=2, y=2, z=3)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+--fcc-editable-region--
+class R2Vector:
+ def __init__(self, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, x, y, z):
+ super().__init__(x, y)
+ self.z = z
+
+v1 = R2Vector(2, 3)
+print(v1.norm())
+print(v1)
+v2 = R3Vector(2, 2, 3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
new file mode 100644
index 00000000000..ef31cdd6194
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4148dea0f802040225e0c.md
@@ -0,0 +1,64 @@
+---
+id: 65f4148dea0f802040225e0c
+title: Step 18
+challengeType: 20
+dashedName: step-18
+---
+
+# --description--
+
+Remove the existing `print` calls. Then, as you did before for `v1`, print `v2` and the value returned by `v2.norm()`.
+
+# --hints--
+
+You should not have `print(v1)` and `print(v1.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v1.norm())")`));
+ }
+})
+```
+
+You should print `v2` and `v2.norm()`.
+
+```js
+({
+ test: () => {
+ assert(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+print(v1.norm())
+print(v1)
+
+v2 = R3Vector(x=2, y=2, z=3)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
new file mode 100644
index 00000000000..1a83f17e994
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4520e363e2642f8112e33.md
@@ -0,0 +1,64 @@
+---
+id: 65f4520e363e2642f8112e33
+title: Step 19
+challengeType: 20
+dashedName: step-19
+---
+
+# --description--
+
+As you can see, something is not quite right. The `norm` and `__str__` methods inherited from `R2Vector` cannot adapt to a 3-dimensional vector. Their implementation has to be more flexible.
+
+Every object in Python has a special attribute named `__dict__`, which is a dictionary that stores the object attributes.
+
+Remove the existing `print` calls. Then, print the `__dict__` attribute of your `v1` and `v2` vectors to see what they look like.
+
+# --hints--
+
+You should not have `print(v2)` and `print(v2.norm())` in your code.
+
+```js
+({
+ test: () => {
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2)")`));
+ assert.isFalse(runPython(`_Node(_code).has_call("print(v2.norm())")`));
+ }
+})
+```
+
+You should print the `__dict__` attribute of `v1` and `v2`.
+
+```js
+({ test: () => assert(runPython(`
+(_Node(_code).has_call("print(v1.__dict__)") and _Node(_code).has_call("print(v2.__dict__)")) or _Node(_code).has_call("print(v1.__dict__, v2.__dict__)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v2.norm())
+print(v2)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
new file mode 100644
index 00000000000..2a2c8f28376
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f4535bbdb28d436ff3ddc9.md
@@ -0,0 +1,49 @@
+---
+id: 65f4535bbdb28d436ff3ddc9
+title: Step 20
+challengeType: 20
+dashedName: step-20
+---
+
+# --description--
+
+As you can see from the output, `__dict__` contains the values of your instance attributes. Instead of explicitly adding the squares of `self.x` and `self.y`, you are going to iterate over the values stored in `__dict__` to calculate the value of the norm.
+
+Within the `norm` method body, replace the content of the parentheses with a generator expression that elevates each value `val` in `self.__dict__.values()` to the power of `2`. Also, pass that generator expression as the argument to the `sum` function, so that all the squares are added together before calculating the square root.
+
+# --hints--
+
+You should return `sum(val**2 for val in self.__dict__.values())**0.5` from `norm()` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in self.__dict__.values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return (self.x**2 + self.y**2)**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
new file mode 100644
index 00000000000..bbb82436c52
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f870003444fb1a2ad171f2.md
@@ -0,0 +1,53 @@
+---
+id: 65f870003444fb1a2ad171f2
+title: Step 21
+challengeType: 20
+dashedName: step-21
+---
+
+# --description--
+
+Modify the two `print` calls to print the norm of your vectors and verify that the `norm()` method works fine.
+
+# --hints--
+
+You should print `v1.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1.norm())")`)) })
+```
+
+You should print `v2.norm()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v2.norm())")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.__dict__)
+print(v2.__dict__)
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
new file mode 100644
index 00000000000..22e3cab792e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8709620b2ce1a62608f5a.md
@@ -0,0 +1,61 @@
+---
+id: 65f8709620b2ce1a62608f5a
+title: Step 23
+challengeType: 20
+dashedName: step-23
+---
+
+# --description--
+
+When you need to dynamically access some attributes starting from a string input, the built-in `getattr()` function is what you need. It takes an object as its first argument, and a string containing the attribute name as its second attribute.
+
+Start to fix the `__str__` method by replacing the string returned by `__str__()` with a generator expression that iterates through the object attributes and calls `getattr()` for each attribute `i`.
+
+# --hints--
+
+You should return a generator expression that iterates over `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_iters()[0].is_equivalent("vars(self)")`)) })
+```
+
+You should return a generator expression that uses `i` as the iteration variable.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_targets()[0].is_equivalent("i")`)) })
+```
+
+You should return a generator expression that calls `getattr(self, i)` for each item `i` in `vars(self)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").find_return().find_comp_expr().is_equivalent("getattr(self, i)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
new file mode 100644
index 00000000000..668bd89de56
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8720685ec351abef26740.md
@@ -0,0 +1,47 @@
+---
+id: 65f8720685ec351abef26740
+title: Step 24
+challengeType: 20
+dashedName: step-24
+---
+
+# --description--
+
+To obtain a proper string representation, call the `tuple()` constructor and pass it the generator expression you wrote in the previous step as the argument.
+
+# --hints--
+
+You should pass the expression returned by the `__str__` method to the `tuple()` constructor.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("tuple(getattr(self, i) for i in vars(self))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return (getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
new file mode 100644
index 00000000000..789f37ee6fe
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f872a0fe6aa21b456ad4fe.md
@@ -0,0 +1,47 @@
+---
+id: 65f872a0fe6aa21b456ad4fe
+title: Step 25
+challengeType: 20
+dashedName: step-25
+---
+
+# --description--
+
+Finally, pass the `tuple()` call as the argument to the `str()` function.
+
+# --hints--
+
+You should pass the `tuple()` call you are currently returning from the `__str__` method to the `str()` function.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__str__").has_return("str(tuple(getattr(self, i) for i in vars(self)))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return tuple(getattr(self, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
new file mode 100644
index 00000000000..6a2c44baef5
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f8749b13774b1d2e4a7fba.md
@@ -0,0 +1,56 @@
+---
+id: 65f8749b13774b1d2e4a7fba
+title: Step 27
+challengeType: 20
+dashedName: step-27
+---
+
+# --description--
+
+While the `__str__` method returns a human-readable string representation of an object, the `__repr__` method is supposed to return the string needed to instantiate the object.
+
+Add a `__repr__` method with a `self` parameter within the `R2Vector` class.
+
+# --hints--
+
+Your `R2Vector` class should have a `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__repr__")`)) })
+```
+
+Your `__repr__` method should have a `self` parameter.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_args("self")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
new file mode 100644
index 00000000000..7f5a3e0f9c9
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f876d17832001e8e1abb05.md
@@ -0,0 +1,74 @@
+---
+id: 65f876d17832001e8e1abb05
+title: Step 28
+challengeType: 20
+dashedName: step-28
+---
+
+# --description--
+
+Declare a variable `arg_list`. Give it the value of a list comprehension that iterates over `key` and `val` for each key-value pair in `vars(self).items()` and computes the f-string `f'{key}={val}'` at each iteration.
+
+# --hints--
+
+You should declare a variable `arg_list`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_variable("arg_list")`)) })
+```
+
+You should assign a list comprehension that iterates over `vars(self).items()` to `arg_list`.
+
+```js
+({ test: () => runPython(`
+import ast
+var = _Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list")
+assert isinstance(var.tree.value, ast.ListComp), "Expected arg_list to be a list comprehension"
+assert (actual := var.find_comp_iters()[0].is_equivalent("vars(self).items()")), f"Expected vars(self).items(), got {actual}"
+`) })
+```
+
+The list comprehension assigned to `arg_list` should use `key` and `val` to iterate over `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_targets()[0].is_equivalent("key, val")
+`)) })
+```
+
+The list comprehension assigned to `arg_list` should compute the string `f'{key}={val}'` for each key-value pair in `vars(self).items()`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("arg_list").find_comp_expr().is_equivalent("f'{key}={val}'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
new file mode 100644
index 00000000000..0c56316394e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93acbb514857003510e79.md
@@ -0,0 +1,50 @@
+---
+id: 65f93acbb514857003510e79
+title: Step 29
+challengeType: 20
+dashedName: step-29
+---
+
+# --description--
+
+Declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+# --hints--
+
+You should declare a variable `args` and assign it the value returned by joining the elements in `arg_list` with the string `', '`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").find_variable("args").is_equivalent("args = ', '.join(arg_list)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
new file mode 100644
index 00000000000..e826611fa57
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93b67169a9c703264458a.md
@@ -0,0 +1,52 @@
+---
+id: 65f93b67169a9c703264458a
+title: Step 30
+challengeType: 20
+dashedName: step-30
+---
+
+# --description--
+
+Since the method should return the string to instantiate the object for `R2Vector` as well as `R3Vector` when inherited, you cannot build the string specifying the class name.
+
+You can access the name of a class with `__class__.__name__`. Add a `return` statement to the `__repr__` method and return the string necessary to instantiate the object.
+
+# --hints--
+
+You should use `__class__.__name__` to build the f-string needed to instantiate a vector object and return it from the `__repr__` method.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__repr__").has_return("f'{self.__class__.__name__}({args})'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+--fcc-editable-region--
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
new file mode 100644
index 00000000000..13682539c2c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93d4647ce2670dc6f095c.md
@@ -0,0 +1,57 @@
+---
+id: 65f93d4647ce2670dc6f095c
+title: Step 31
+challengeType: 20
+dashedName: step-31
+---
+
+# --description--
+
+The `__repr__` method is called under the hood by the `repr` function. Verify that `__repr__` works properly by adding `f'\nrepr = {repr(v1)}'` and `f'\nrepr = {repr(v2)}'` as the second argument to your first and second `print` calls, respectively.
+
+# --hints--
+
+You should add `f'\nrepr = {repr(v1)}'` as the second argument to your `print(f'v1 = {v1}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}', f'\\\\nrepr = {repr(v1)}')")`)) })
+```
+
+You should add `f'\nrepr = {repr(v2)}'` as the second argument to your `print(f'v2 = {v2}')` call.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}', f'\\\\nrepr = {repr(v2)}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
new file mode 100644
index 00000000000..a25da243ba9
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f93e54a9121571dcdd3e79.md
@@ -0,0 +1,56 @@
+---
+id: 65f93e54a9121571dcdd3e79
+title: Step 32
+challengeType: 20
+dashedName: step-32
+---
+
+# --description--
+
+The output is correct, `repr` is giving you the string required to instantiate the objects.
+
+Now comment out both your `print` calls.
+
+# --hints--
+
+You should comment out both your `print()` calls.
+
+```js
+({ test: () => {
+ assert.match(code, /#\s*print\s*\(\s*f('|")v1 = \{\s*v1\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v1\s*\)\s*\}\2\s*\)/);
+ assert.match(code, /#\s*print\s*\(\s*f('|")v2 = \{\s*v2\s*\}\1\s*,\s*f('|")\\nrepr = \{\s*repr\s*\(\s*v2\s*\)\s*\}\2\s*\)/);
+} })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
new file mode 100644
index 00000000000..127f701ba31
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b17a638f0d0dcce8c354.md
@@ -0,0 +1,62 @@
+---
+id: 65f9b17a638f0d0dcce8c354
+title: Step 38
+challengeType: 20
+dashedName: step-38
+---
+
+# --description--
+
+To create a vector space, you need to define how vectors should behave in several cases. Vectors can be added, forming a new vector.
+
+The special method `__add__` can be implemented to override what happens by default when two objects are added together using the `+` operator.
+
+Right now, trying to add two instances of `R2Vector` or `R3Vector` would raise an exception. Create an empty `__add__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define an `__add__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__add__")`)) })
+```
+
+Your `__add__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
new file mode 100644
index 00000000000..f90c14fe57b
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b486989cb90ff3e77ac8.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b486989cb90ff3e77ac8
+title: Step 39
+challengeType: 20
+dashedName: step-39
+---
+
+# --description--
+
+The `other` parameter of your `__add__` method represents the operand placed at the right side of the `+` operator in an addition operation.
+
+You want to verify that the right-hand operand is not an object of the same class as the left-hand operand (i.e. `self`). Create an `if` statement that verifies that by checking the type of the operands.
+
+# --hints--
+
+You should create an `if` statement that checks if `type(self)` and `type(other)` are different.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
new file mode 100644
index 00000000000..1fa83e0f9aa
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9b9710cca621244d3bde1.md
@@ -0,0 +1,58 @@
+---
+id: 65f9b9710cca621244d3bde1
+title: Step 40
+challengeType: 20
+dashedName: step-40
+---
+
+# --description--
+
+In Python, `NotImplemented` is a special value used to indicate that an operation is not implemented for a specific case.
+
+`NotImplemented` does not raise an exception immediately. Instead, it signals to ask to the other operand how to perform the operation. If the request cannot be satisfied, a `TypeError` is returned by default.
+
+Because you want to be able to sum two vectors only if they belong to the same class, return `NotImplemented` from the `if` statement you created in the previous step.
+
+# --hints--
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__add__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
new file mode 100644
index 00000000000..9df77e46895
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bb7c0d524612b2a88a4b.md
@@ -0,0 +1,58 @@
+---
+id: 65f9bb7c0d524612b2a88a4b
+title: Step 41
+challengeType: 20
+dashedName: step-41
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_stmt("kwargs = {}")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
new file mode 100644
index 00000000000..f5d28e43bd6
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9bc10a9fb1612e066e9e8.md
@@ -0,0 +1,92 @@
+---
+id: 65f9bc10a9fb1612e066e9e8
+title: Step 42
+challengeType: 20
+dashedName: step-42
+---
+
+# --description--
+
+When adding two vectors, each component of one vector is added to the same component of the other vector. For example, adding `(1, 2)` and `(2, 4)` generates a third vector `(3, 6)`, where `3` is the sum of `1` and `2` and `6` is the sum of `2` and `4`.
+
+The `kwargs` dictionary will contain the key-value pairs needed to instantiate a new vector of the same class of the two vectors added together.
+
+Turn the empty dictionary into a dictionary comprehension that iterates through `vars(self)` and for each key (`i`) creates a key-value pair, where the key is the same key of the current iteration and its value is the sum of the values of the `i` attributes of the two operands.
+
+# --hints--
+
+You should turn the empty dictionary assigned to `kwargs` into a dictionary comprehension that iterates over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_iters()[0].is_equivalent("vars(self)")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over `vars(self)`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_key().is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the sum of the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i` in `vars(self)`. Use the `getattr()` function for that.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__add__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) + getattr(other, i)") or node.is_equivalent("getattr(other, i) + getattr(self, i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
new file mode 100644
index 00000000000..d1cd1755778
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9c2c2006feb1428ad2d4c.md
@@ -0,0 +1,70 @@
+---
+id: 65f9c2c2006feb1428ad2d4c
+title: Step 43
+challengeType: 20
+dashedName: step-43
+---
+
+# --description--
+
+You can unpack a dictionary into keyword arguments by using the `**` operator:
+
+```py
+def spam(a, b):
+ return a + b
+
+my_dict = {a: 11, b: 4}
+
+spam(**my_dict) # 15
+```
+
+Return an instance of the current class by using `__class__` and passing `**kwargs` as the argument.
+
+# --hints--
+
+You should return `self.__class__(**kwargs)` from the `__add__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__add__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
new file mode 100644
index 00000000000..689ab778fe5
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9cb678070ca1668898c70.md
@@ -0,0 +1,90 @@
+---
+id: 65f9cb678070ca1668898c70
+title: Step 44
+challengeType: 20
+dashedName: step-44
+---
+
+# --description--
+
+In the same way `__add__` is called under the hood when two objects are added together, the `__sub__` method is called implicitly in case of subtraction.
+
+Now, define an empty `__sub__` method and give two parameters: `self`, and `other`. Inside your new method, create an if statement to check if `self` and `other` do not belong to the same class and return `NotImplemented`, as you did previously.
+
+# --hints--
+
+You should define a `__sub__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__sub__")
+ `))
+})
+```
+
+Your `__sub__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_args("self, other")
+ `))
+})
+```
+
+You should create an `if` statement that checks if `self` and `other` does not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")
+ `))
+})
+```
+
+You should return `NotImplemented` from within the `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
new file mode 100644
index 00000000000..2d452d2413e
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dd6e5a08af19c196c2df.md
@@ -0,0 +1,89 @@
+---
+id: 65f9dd6e5a08af19c196c2df
+title: Step 45
+challengeType: 20
+dashedName: step-45
+---
+
+# --description--
+
+The vector resulting from the subtraction of one vector from another is obtained by calculating the difference of each of their components. For example, subtracting `(2, 4)` from `(7, 3)` generates a third vector `(5, -1)`, where `5` is the difference between `7` and `2` and `-1` is the difference between `3` and `4`.
+
+As you did before inside the `__add__` method, declare a `kwargs` variable after the `if` statement. Assign it a dictionary comprehension that iterates through the object attributes and creates a key-value pair for each key `i`, where the key is the same key as the current iteration and its value is the difference between the values of the `i` attributes of two operands.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it a dictionary comprehension that iterates over the object attributes.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_iters()[0]
+node.is_equivalent("vars(self)") or node.is_equivalent("self.__dict__")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should use the variable `i` to iterate over the object attributes.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_targets()[0].is_equivalent("i")
+ `))
+})
+```
+
+The dictionary comprehension assigned to `kwargs` should use `i` as the key.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_key().is_equivalent("i")`)) })
+```
+
+The dictionary comprehension assigned to `kwargs` should assign the difference between the `i` attribute of `self` and the `i` attribute of `other` to the `i` key for each `i`.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__sub__").find_variable("kwargs").find_comp_expr()
+node.is_equivalent("getattr(self, i) - getattr(other, i)") or node.is_equivalent("self.__getattribute__(i) - other.__getattribute__(i)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
new file mode 100644
index 00000000000..095bce27c7c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9dfd2e75e291a38695f13.md
@@ -0,0 +1,65 @@
+---
+id: 65f9dfd2e75e291a38695f13
+title: Step 46
+challengeType: 20
+dashedName: step-46
+---
+
+# --description--
+
+Finally, return a new vector object. Use `__class__` and unpack `kwargs` to instantiate the new vector.
+
+# --hints--
+
+You should return a new vector using `__class__` and unpacking `kwargs` from the `__sub__` method.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__sub__").has_return("self.__class__(**kwargs)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
new file mode 100644
index 00000000000..c5cb7742541
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65f9e0a578b22c1a736f3d82.md
@@ -0,0 +1,67 @@
+---
+id: 65f9e0a578b22c1a736f3d82
+title: Step 47
+challengeType: 20
+dashedName: step-47
+---
+
+# --description--
+
+Modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+# --hints--
+
+You should modify your `v2` variable assignment to be an `R2Vector` instance having `x=0.5` and `y=1.25`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v2 = R2Vector(x=0.5, y=1.25)")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
new file mode 100644
index 00000000000..1d277671da4
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8d5cf0ef3b141010f5d8.md
@@ -0,0 +1,67 @@
+---
+id: 65fa8d5cf0ef3b141010f5d8
+title: Step 48
+challengeType: 20
+dashedName: step-48
+---
+
+# --description--
+
+It's time to verify that the addition and subtraction operations work as expected. Declare another variable `v3` and assign it the sum of `v1` plus `v2`.
+
+# --hints--
+
+You should declare a variable `v3` and assign it the sum of `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v3 = v1 + v2") or _Node(_code).has_stmt("v3 = v2 + v1")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
new file mode 100644
index 00000000000..87ddac5ea5f
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa8df56a0e2c149b4d24fe.md
@@ -0,0 +1,64 @@
+---
+id: 65fa8df56a0e2c149b4d24fe
+title: Step 49
+challengeType: 20
+dashedName: step-49
+---
+
+# --description--
+
+Next, check the new vector by printing the following f-string `f'v1 + v2 = {v3}'`.
+
+# --hints--
+
+You should print `f'v1 + v2 = {v3}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 + v2 = {v3}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
new file mode 100644
index 00000000000..e526a9cd4cc
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9402d1fb5516aa42159d.md
@@ -0,0 +1,77 @@
+---
+id: 65fa9402d1fb5516aa42159d
+title: Step 50
+challengeType: 20
+dashedName: step-50
+---
+
+# --description--
+
+Feel free to modify `v3` so that it sums an `R2Vector` instance with an object of a different type, such as an integer or a string. You will be able to see a `TypeError` message printed on the console.
+
+Then, restore the original line and create a new variable `v4`. Assign the difference between `v1` and `v2` to your new variable and print the result following the same structure as the previous f-string.
+
+# --hints--
+
+You should declare a variable `v4` and assign it the difference between `v1` and `v2`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).has_stmt("v4 = v1 - v2")
+ `))
+})
+```
+
+You should print `f'v1 - v2 = {v4}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 - v2 = {v4}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
new file mode 100644
index 00000000000..d2df1c3038d
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fa9e1b6c6db919385359ec.md
@@ -0,0 +1,85 @@
+---
+id: 65fa9e1b6c6db919385359ec
+title: Step 51
+challengeType: 20
+dashedName: step-51
+---
+
+# --description--
+
+The special method `__mul__` can be implemented to specify what should happen when the current instance is multiplied by another object.
+
+Create an empty `__mul__` method within the `R2Vector` class and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `__mul__` method within the `R2Vector` class.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").has_function("__mul__")
+ `))
+})
+```
+
+Your `__mul__` method should have two parameters, `self` and `other`.
+
+```js
+({
+ test: () => assert(runPython(`
+ _Node(_code).find_class("R2Vector").find_function("__mul__").has_args("self, other")
+ `))
+})
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
new file mode 100644
index 00000000000..0a18b8b69d1
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65faaed8f7a9772f023ea816.md
@@ -0,0 +1,94 @@
+---
+id: 65faaed8f7a9772f023ea816
+title: Step 52
+challengeType: 20
+dashedName: step-52
+---
+
+# --description--
+
+Vectors can be multiplied by a *scalar*, i.e. a number that multiplies each single component. The result of scalar multiplication is a vector with the same orientation as the original vector but a different magnitude.
+
+Implement the scalar multiplication by checking if `other` is either an `int` or a `float`. If it is, return a new instance of the current class that has each component of the starting vector multiplied by `other`. This will be the vector resulting from the scalar multiplication.
+
+Make sure the methods can be applied to compute the scalar multiplication of vectors with any number of dimensions.
+
+# --hints--
+
+Your method should return a new instance of the current class only when the type of `other` is either `int` or `float`.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=0, y=0)
+v2 = R3Vector(x=0, y=0, z=0)
+types = ["", True, [], {}]
+assert all((v1 * i) is None for i in types)
+types = [1, 1.0]
+assert all(type(v1 * i) is type(v1) for i in types)
+assert all(type(v2 * i) is type(v2) for i in types)
+`) })
+```
+
+The vector resulting from the scalar multiplication should have each component of the starting vector multiplied by the scalar.
+
+```js
+({ test: () => runPython(`
+v1 = R2Vector(x=1, y=1.5)
+v2 = R3Vector(x=2.2, y=3, z=-1)
+assert vars(v1 * 3) == vars(R2Vector(x=3, y=4.5))
+assert vars(v2 * (-2.0)) == vars(R3Vector(x=-4.4, y=-6.0, z=2.0))
+`) })
+```
+
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
new file mode 100644
index 00000000000..bcf1d3d0b55
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc87e19930a503e5f05500.md
@@ -0,0 +1,79 @@
+---
+id: 65fc87e19930a503e5f05500
+title: Step 53
+challengeType: 20
+dashedName: step-53
+---
+
+# --description--
+
+A vector can be multiplied by another vector, too. This operation is called *dot product*, or *scalar product*.
+
+Create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+You are going to implement the dot product inside this block during the next step.
+
+# --hints--
+
+You should create an `elif` clause that checks if `other` is an object of the same class of the current instance.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__mul__").find_ifs()[0].find_conditions()[1]
+node.is_equivalent("type(self) == type(other)") or node.is_equivalent("type(other) == type(self)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
new file mode 100644
index 00000000000..c5edc6d9b45
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc899d77495504d6deeccc.md
@@ -0,0 +1,87 @@
+---
+id: 65fc899d77495504d6deeccc
+title: Step 54
+challengeType: 20
+dashedName: step-54
+---
+
+# --description--
+
+The scalar product between two vectors $\mathbf{a}$ and $\mathbf{b}$ is indicated as:
+
+\\( \mathbf{a} \cdot \mathbf{b} = a_1 \cdot b_1 + a_2 \cdot b_2 + \ldots + a_n \cdot b_n = \sum_{i=1}^{n} a_i \cdot b_i \\)
+
+Where each component of $\mathbf{a}$ is multiplied by the correspondent component of $\mathbf{b}$, and all the products are summed together, resulting in a number.
+
+Within the `elif` clause, implement the above formula to compute the result of a scalar product and return the result. Remember that your implementation must be valid for any vector, independently from the number of components, when the method is inherited.
+
+# --hints--
+
+You should implement the scalar product calculation and return the result inside the `elif` body of your `__mul__` method.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+v3 = R3Vector(x=2, y=3, z=1.5)
+v4 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1*v2 == 4.75 and v3*v4 == 7.0
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
new file mode 100644
index 00000000000..36b78391926
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8e7c766ab1070213aadb.md
@@ -0,0 +1,78 @@
+---
+id: 65fc8e7c766ab1070213aadb
+title: Step 55
+challengeType: 20
+dashedName: step-55
+---
+
+# --description--
+
+In case `other` is not an integer, a floating point number, or another instance of the current class, no product can be computed.
+
+After the `elif` clause, return `NotImplemented`.
+
+# --hints--
+
+You should return `NotImplemented` after the `elif` clause.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__mul__").has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
new file mode 100644
index 00000000000..bf365bd4903
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fc8fa7e7860407ab479bf0.md
@@ -0,0 +1,82 @@
+---
+id: 65fc8fa7e7860407ab479bf0
+title: Step 56
+challengeType: 20
+dashedName: step-56
+---
+
+# --description--
+
+It's time to test the multiplication. Declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`. Then, call the `print` function and pass it the following f-string: `f'v1 * 3 = {v5}'`.
+
+# --hints--
+
+You should declare a new variable `v5` and assign it the scalar multiplication `v1 * 3`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * 3")`)) })
+```
+
+You should print the f-string `f'v1 * 3 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * 3 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
new file mode 100644
index 00000000000..034109b8c53
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd681b20b7e45f55def415.md
@@ -0,0 +1,87 @@
+---
+id: 65fd681b20b7e45f55def415
+title: Step 57
+challengeType: 20
+dashedName: step-57
+---
+
+# --description--
+
+The scalar multiplication works fine. Now, modify the assignment of `v5` to be the dot product `v1 * v2`. Also, update the `print` call.
+
+Before doing that, feel free to experiment and multiply `v1` by an object of invalid type to see the error message printed on the console.
+
+
+# --hints--
+
+You should update the assignment of `v5` assigning it the scalar product `v1 * v2`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v5").is_equivalent("v5 = v1 * v2")`)) })
+```
+
+You should update your `print` call to print the f-string `f'v1 * v2 = {v5}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 * v2 = {v5}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * 3
+print(f'v1 * 3 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
new file mode 100644
index 00000000000..f6184775ca4
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9250db0d6b8198cf29ef.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9250db0d6b8198cf29ef
+title: Step 58
+challengeType: 20
+dashedName: step-58
+---
+
+# --description--
+
+The `__eq__` method can be implemented to specify what should happen in case the comparison operator (`==`) is used to compare an object with something else.
+
+Within the `R2Vector` class, create an `__eq__` method and give it two parameters: `self` and `other`.
+
+# --hints--
+
+You should define a `__eq__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__eq__")`)) })
+```
+
+Your `__eq__` method should take two parameters: `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
new file mode 100644
index 00000000000..5d2d8cfc678
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd95c23beef982af29004c.md
@@ -0,0 +1,88 @@
+---
+id: 65fd95c23beef982af29004c
+title: Step 59
+challengeType: 20
+dashedName: step-59
+---
+
+# --description--
+
+You want to compare two vectors, only when they belong to the same class. For that create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented` in that case.
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__eq__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
new file mode 100644
index 00000000000..c3bea995dc8
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd97f3c1b4c4839bdeb8d2.md
@@ -0,0 +1,91 @@
+---
+id: 65fd97f3c1b4c4839bdeb8d2
+title: Step 60
+challengeType: 20
+dashedName: step-60
+---
+
+# --description--
+
+To compare two vectors, you are going to check that each component of the first vector is equal to the same component of the second vector.
+
+After the `if` statement you created in the previous step, return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+# --hints--
+
+The `__eq__` method should return `True` if each attribute of the current instance is equal to the same attribute of `other` and `False` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+v1 == v2 and not v1 == v3 and v4 == v5 and not v5 == v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
new file mode 100644
index 00000000000..a7f5d701215
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9aa649f6cc84631882a9.md
@@ -0,0 +1,102 @@
+---
+id: 65fd9aa649f6cc84631882a9
+title: Step 61
+challengeType: 20
+dashedName: step-61
+---
+
+# --description--
+
+The `__ne__` method is called under the hood when the `!=` operator is used. Define a `__ne__` method with two parameters `self` and `other`. From your new method, return the opposite of `self == other`.
+
+# --hints--
+
+You should define a `__ne__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ne__")`)) })
+```
+
+Your `__ne__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ne__").has_args("self, other")`)) })
+```
+
+The `__ne__` method should return `False` if each attribute of the current instance is equal to the same attribute of `other` and `True` otherwise.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=2, y=3)
+v3 = R2Vector(x=0.5, y=1.25)
+v4 = R3Vector(x=2, y=3, z=1.5)
+v5 = R3Vector(x=2, y=3, z=1.5)
+v6 = R3Vector(x=0.5, y=1.25, z=1.5)
+not v1 != v2 and v1 != v3 and not v4 != v5 and v5 != v6
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+--fcc-editable-region--
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
new file mode 100644
index 00000000000..c151f678d86
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9c6e49d7cd8513ab1005.md
@@ -0,0 +1,86 @@
+---
+id: 65fd9c6e49d7cd8513ab1005
+title: Step 62
+challengeType: 20
+dashedName: step-62
+---
+
+# --description--
+
+At the end of your code, use the equality operator to compare `v1` and `R2Vector(x=2, y=3)` and print the result.
+
+# --hints--
+
+You should print the result of comparing `v1` and `R2Vector(x=2, y=3)` using the equality operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 == R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) == v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
new file mode 100644
index 00000000000..804d4947304
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9d6203afea85931094c9.md
@@ -0,0 +1,87 @@
+---
+id: 65fd9d6203afea85931094c9
+title: Step 63
+challengeType: 20
+dashedName: step-63
+---
+
+# --description--
+
+The comparison returns `True`, since the two vectors have the same components. Now, modify the argument of the `print` call you added in the previous step to use the inequality operator.
+
+# --hints--
+
+You should modify the `print` call you added in the previous step using the inequality operator to compare `v1` and `R2Vector(x=2, y=3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))") or _Node(_code).has_call("print(R2Vector(x=2, y=3) != v1)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 == R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
new file mode 100644
index 00000000000..9255b41f2c6
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fd9e2c56ff19862dfb8cbb.md
@@ -0,0 +1,97 @@
+---
+id: 65fd9e2c56ff19862dfb8cbb
+title: Step 64
+challengeType: 20
+dashedName: step-64
+---
+
+# --description--
+
+The `__lt__` method is called under the hood when the `<` operator is used to compare an object with something else.
+
+Add an empty `__lt__` method and give it two parameters: `self`, `other`.
+
+# --hints--
+
+You should define a `__lt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__lt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
new file mode 100644
index 00000000000..ee258ff8a2a
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc3c8478ee70fc7966151.md
@@ -0,0 +1,100 @@
+---
+id: 65fdc3c8478ee70fc7966151
+title: Step 65
+challengeType: 20
+dashedName: step-65
+---
+
+# --description--
+
+In the same way you did before for the `__eq__` method, create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ pass
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
new file mode 100644
index 00000000000..390babbb01f
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/65fdc496f4440e1055a2ac1b.md
@@ -0,0 +1,91 @@
+---
+id: 65fdc496f4440e1055a2ac1b
+title: Step 66
+challengeType: 20
+dashedName: step-66
+---
+
+# --description--
+
+After the `if` statement, return the result of comparing the norm of the current instance with the norm of `other` using the less than operator.
+
+# --hints--
+
+The `__lt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the `<` operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__lt__").has_return("self.norm() < other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
new file mode 100644
index 00000000000..7193db8cba2
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601918b44a11b4a8c986c6a.md
@@ -0,0 +1,122 @@
+---
+id: 6601918b44a11b4a8c986c6a
+title: Step 67
+challengeType: 20
+dashedName: step-67
+---
+
+# --description--
+
+The `__gt__` method is called under the hood when the `>` operator is used to compare an object with something else.
+
+After the `__lt__` method, in the same way you did for `__lt__`, implement the `__gt__` method. Pay attention to use the appropriate operator.
+
+# --hints--
+
+You should define a `__gt__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__gt__")`)) })
+```
+
+Your `__lt__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_args("self, other")`)) })
+```
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_conditions()[0]
+node.is_equivalent("type(self) != type(other)") or node.is_equivalent("type(other) != type(self)")`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+The `__gt__` method should return the result of comparing the norm of the current instance with the norm of `other` using the greater than operator.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__gt__").has_return("self.norm() > other.norm()")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
new file mode 100644
index 00000000000..fd051c7fca6
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019258a7c71d4ae50da42e.md
@@ -0,0 +1,111 @@
+---
+id: 66019258a7c71d4ae50da42e
+title: Step 68
+challengeType: 20
+dashedName: step-68
+---
+
+# --description--
+
+There are still two possible comparisons to implement. The `__le__` method is called when the `<=` operator is used to compare two objects.
+
+Define a `__le__` method with `self` and `other` as the parameters and make it return the opposite of `self > other`.
+
+# --hints--
+
+You should define a `__le__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__le__")`)) })
+```
+
+Your `__le__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_args("self, other")`)) })
+```
+
+Your `__le__` method return the opposite of `self > other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__le__").has_return("not self > other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+--fcc-editable-region--
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
new file mode 100644
index 00000000000..542035862a5
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019319edb1cb4b57d3a793.md
@@ -0,0 +1,116 @@
+---
+id: 66019319edb1cb4b57d3a793
+title: Step 69
+challengeType: 20
+dashedName: step-69
+---
+
+# --description--
+
+The last method you need is `__ge__`, which is called when the `>=` is used to compare two objects.
+
+Define a `__ge__` method with `self` and `other` as the parameters and make it return the opposite of `self < other`.
+
+# --hints--
+
+You should define a `__ge__` method within the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").has_function("__ge__")`)) })
+```
+
+Your `__ge__` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_args("self, other")`)) })
+```
+
+Your `__ge__` method should return the opposite of `self < other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__ge__").has_return("not self < other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
new file mode 100644
index 00000000000..fe9c0cfa362
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/660193a2a71faa4bd8f10970.md
@@ -0,0 +1,104 @@
+---
+id: 660193a2a71faa4bd8f10970
+title: Step 70
+challengeType: 20
+dashedName: step-70
+---
+
+# --description--
+
+Feel free to play around with the new comparison operations you implemented. Then, remove your last `print` call.
+
+
+# --hints--
+
+You should not have `print(v1 != R2Vector(x=2, y=3))` in your code.
+
+```js
+({test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(v1 != R2Vector(x=2, y=3))")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+print(v1 != R2Vector(x=2, y=3))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
new file mode 100644
index 00000000000..2157c6b8a3b
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66019977710caa516276c0a8.md
@@ -0,0 +1,111 @@
+---
+id: 66019977710caa516276c0a8
+title: Step 71
+challengeType: 20
+dashedName: step-71
+---
+
+# --description--
+
+The *cross product*, or *vector product*, is defined between 3-dimensional vectors and results in a third vector perpendicular to both of them.
+
+The `R3Vector` class inherits from `R2Vector`, meaning it has access to all the methods and properties defined in `R2Vector`. A child class can implement additional features. You already saw a way to change the implementation of a method. Now, you are going to give the child class `R3Vector` a new method instead.
+
+Within the `R3Vector` class, define a `cross` method and give it two parameters: `self`, and `other`.
+
+# --hints--
+
+You should define a `cross` method within the `R3Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").has_function("cross")`)) })
+```
+
+Your `cross` method should have two parameters, `self` and `other`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").has_args("self, other")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
new file mode 100644
index 00000000000..b7948eb83c6
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a7eb860fb8546516674d.md
@@ -0,0 +1,114 @@
+---
+id: 6601a7eb860fb8546516674d
+title: Step 72
+challengeType: 20
+dashedName: step-72
+---
+
+# --description--
+
+Create an `if` statement that checks if `self` and `other` do not belong to the same class and return `NotImplemented`.
+
+# --hints--
+
+You should create an `if` statement that checks if `self` and `other` do not belong to the same class.
+
+```js
+({ test: () => assert(runPython(`
+node = _Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_conditions()[0]
+conditions = ["type(self) != type(other)", "type(other) != type(self)", "self.__class__ != other.__class__", "other.__class__ != self.__class__"]
+any(node.is_equivalent(condition) for condition in conditions)
+`)) })
+```
+
+You should return `NotImplemented` from your `if` body.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_ifs()[0].find_bodies()[0].has_return("NotImplemented")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ pass
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
new file mode 100644
index 00000000000..7a7cb7ef03c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a88a6e2ccc550d7d7208.md
@@ -0,0 +1,105 @@
+---
+id: 6601a88a6e2ccc550d7d7208
+title: Step 73
+challengeType: 20
+dashedName: step-73
+---
+
+# --description--
+
+After the `if` statement, declare a variable `kwargs` and assign it an empty dictionary.
+
+# --hints--
+
+You should declare a variable `kwargs` and assign it an empty dictionary after the `if` statement.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R3Vector").find_function("cross").find_variable("kwargs").is_equivalent("kwargs = {}")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
new file mode 100644
index 00000000000..c9e2224dad3
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601a8fb2e993b55912f9e9f.md
@@ -0,0 +1,116 @@
+---
+id: 6601a8fb2e993b55912f9e9f
+title: Step 74
+challengeType: 20
+dashedName: step-74
+---
+
+# --description--
+
+The dot product between two 3D vectors \\( \mathbf{a} \\) and \\( \mathbf{b} \\) can be computed as it follows:
+
+\\[ \mathbf{a} \times \mathbf{b} = \begin{pmatrix} a_yb_z - a_zb_y \\\ a_zb_x - a_xb_z \\\ a_xb_y - a_yb_x \end{pmatrix} \\]
+
+Where the resulting vector is represented as a column vector.
+
+Implement the formula above to compute the dot product between two 3-dimensional vectors and return the resulting vector from the `cross()` method.
+
+# --hints--
+
+The `cross()` method should return a new `R3Vector` instance resulting from the dot product computation.
+
+```js
+({ test: () => assert(runPython(`
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+v1.cross(v2) == R3Vector(x=4.75, y=-3.5, z=1.0) and v2.cross(v1) == R3Vector(x=-4.75, y=3.5, z=-1.0) and v1.cross(v1) == R3Vector(x=0, y=0, z=0)
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {}
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
new file mode 100644
index 00000000000..c1435330d56
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ab2809898f57591f2f7f.md
@@ -0,0 +1,119 @@
+---
+id: 6601ab2809898f57591f2f7f
+title: Step 75
+challengeType: 20
+dashedName: step-75
+---
+
+# --description--
+
+Now, modify the assignments of `v1` and `v2`. Turn them into `R3Vector` instances and pass `z=1` and `z=2` to `v1` and `v2`, respectively.
+
+# --hints--
+
+You should modify the assignment of `v1` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v1").is_equivalent("v1 = R3Vector(x=2, y=3, z=1)")`)) })
+```
+
+You should modify the assignment of `v2` to be an `R3Vector` instance.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v2").is_equivalent("v2 = R3Vector(x=0.5, y=1.25, z=2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R2Vector(x=0.5, y=1.25)
+--fcc-editable-region--
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
new file mode 100644
index 00000000000..6904f99b5e1
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ac48a2ee6b59e6a5060d.md
@@ -0,0 +1,113 @@
+---
+id: 6601ac48a2ee6b59e6a5060d
+title: Step 76
+challengeType: 20
+dashedName: step-76
+---
+
+# --description--
+
+Call `cross()` on `v1` and pass `v2` as the argument. Assign this call to a new variable `v6`.
+
+# --hints--
+
+You should declare a variable named `v6` and assign it a call to the `cross()` method on `v1` passing it `v2` as the `argument`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_variable("v6").is_equivalent("v6 = v1.cross(v2)")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
new file mode 100644
index 00000000000..47d13a7bd4d
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6601ad0fe415985a5c83f3cc.md
@@ -0,0 +1,210 @@
+---
+id: 6601ad0fe415985a5c83f3cc
+title: Step 77
+challengeType: 20
+dashedName: step-77
+---
+
+# --description--
+
+As a final step, call the `print` function and pass it the f-string `f'v1 x v2 = {v6}'` to see the output of the dot product.
+
+With that, you have completed the vector space project. Well done!
+
+# --hints--
+
+You should print `f'v1 x v2 = {v6}'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 x v2 = {v6}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+--fcc-editable-region--
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+--fcc-editable-region--
+```
+
+# --solutions--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __add__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) + getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __sub__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {i: getattr(self, i) - getattr(other, i) for i in vars(self)}
+ return self.__class__(**kwargs)
+
+ def __mul__(self, other):
+ if type(other) in (int, float):
+ kwargs = {i: getattr(self, i) * other for i in vars(self)}
+ return self.__class__(**kwargs)
+ elif type(self) == type(other):
+ args = [getattr(self, i) * getattr(other, i) for i in vars(self)]
+ return sum(args)
+ return NotImplemented
+
+ def __eq__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return all(getattr(self, i) == getattr(other, i) for i in vars(self))
+
+ def __ne__(self, other):
+ return not self == other
+
+ def __lt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() < other.norm()
+
+ def __gt__(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ return self.norm() > other.norm()
+
+ def __le__(self, other):
+ return not self > other
+
+ def __ge__(self, other):
+ return not self < other
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+ def cross(self, other):
+ if type(self) != type(other):
+ return NotImplemented
+ kwargs = {
+ 'x': self.y * other.z - self.z * other.y,
+ 'y': self.z * other.x - self.x * other.z,
+ 'z': self.x * other.y - self.y * other.x
+ }
+
+ return self.__class__(**kwargs)
+
+v1 = R3Vector(x=2, y=3, z=1)
+v2 = R3Vector(x=0.5, y=1.25, z=2)
+print(f'v1 = {v1}')
+print(f'v2 = {v2}')
+v3 = v1 + v2
+print(f'v1 + v2 = {v3}')
+v4 = v1 - v2
+print(f'v1 - v2 = {v4}')
+v5 = v1 * v2
+print(f'v1 * v2 = {v5}')
+v6 = v1.cross(v2)
+print(f'v1 x v2 = {v6}')
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
new file mode 100644
index 00000000000..d25b1a4c723
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6659875502b6d7765498f324.md
@@ -0,0 +1,53 @@
+---
+id: 6659875502b6d7765498f324
+title: Step 26
+challengeType: 20
+dashedName: step-26
+---
+
+# --description--
+
+Use f-strings to modify your `print` calls so that they result in the output `v1 = (2, 3)` and `v2 = (2, 2, 3)`, respectively.
+
+# --hints--
+
+You should use an f-string to interpolate `v1` and generate the output `v1 = (2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v1 = {v1}')")`)) })
+```
+
+You should use an f-string to interpolate `v2` and generate the output `v2 = (2, 2, 3)`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).has_call("print(f'v2 = {v2}')")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+--fcc-editable-region--
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
new file mode 100644
index 00000000000..bc5ffa5f75d
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66680ddfd0f8c76782923cb0.md
@@ -0,0 +1,51 @@
+---
+id: 66680ddfd0f8c76782923cb0
+title: Step 22
+challengeType: 20
+dashedName: step-22
+---
+
+# --description--
+
+The `norm()` method is returning the correct values, but there's still something you can improve: readability.
+
+The `vars()` built-in function takes an object as its argument and returns the `__dict__` attribute of that object.
+
+Instead of directly accessing the `__dict__` attribute of `self`, modify the `norm` method to use the `vars()` function.
+
+# --hints--
+
+You should modify your `norm` method to use `vars(self)` instead of `self.__dict__`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("norm").has_return("sum(val**2 for val in vars(self).values())**0.5")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+--fcc-editable-region--
+ def norm(self):
+ return sum(val**2 for val in self.__dict__.values())**0.5
+--fcc-editable-region--
+ def __str__(self):
+ return f'{self.x, self.y}'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+print(v1.norm())
+print(v2.norm())
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
new file mode 100644
index 00000000000..e0f1c196265
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/66682150151af29efec9727d.md
@@ -0,0 +1,61 @@
+---
+id: 66682150151af29efec9727d
+title: Step 33
+challengeType: 20
+dashedName: step-33
+---
+
+# --description--
+
+The `__getattribute__` method is called under the hood any time you try to access an instance attribute. If the attribute is not found at the instance level, the method will search for it at the class level, and eventually in parent classes.
+
+Inside your class, define a `__getattribute__` method with two parameters, `self` and `attr`, and make it return the string `'calling __getattribute__'`. You'll override momentarily the default implementation just to see how the attribute access works.
+
+# --hints--
+
+You should define a method named `__getattribute__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_args("self, attr")`)) })
+```
+
+Your `__getattribute__` method should return the string `'calling __getattribute__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattribute__").has_return("'calling __getattribute__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
new file mode 100644
index 00000000000..948a541cb76
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666826f258fda1ab3396a509.md
@@ -0,0 +1,61 @@
+---
+id: 666826f258fda1ab3396a509
+title: Step 34
+challengeType: 20
+dashedName: step-34
+---
+
+# --description--
+
+Now, print the result of accessing the `x` attribute of `v1` both with the dot operator and the `getattr()` built-in function.
+
+You will see that `__getattribute__` is called in both cases.
+
+# --hints--
+
+You should print the `x` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.x)") and n.has_call("print(getattr(v1, 'x'))")) or n.has_call("print(v1.x, getattr(v1, 'x'))") or n.has_call("print(getattr(v1, 'x'), v1.x)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
new file mode 100644
index 00000000000..8c3a650010b
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666827a6fd0dbaafe8330ea6.md
@@ -0,0 +1,69 @@
+---
+id: 666827a6fd0dbaafe8330ea6
+title: Step 35
+challengeType: 20
+dashedName: step-35
+---
+
+# --description--
+
+`__getattr__` is another special method that plays a role in accessing attributes.
+
+The default implementation of `__getattribute__` is to raise an `AttributeError` when the requested attribute is not an instance attribute or it is not present in the class tree.
+
+In that case, `__getattr__` is called if defined by the class. You can consider it as a sort of fallback when the usual attribute accessing procedure fails.
+
+Turn the `__getattribute__` method into `__getattr__` and modify the string returned by the method into `'calling __getattr__'`.
+
+# --hints--
+
+You should define a method named `__getattr__` with two parameters, `self` and `attr`, inside the `R2Vector` class.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_args("self, attr")`)) })
+```
+
+Your `__getattr__` method should return the string `'calling __getattr__'`.
+
+```js
+({ test: () => assert(runPython(`_Node(_code).find_class("R2Vector").find_function("__getattr__").has_return("'calling __getattr__'")`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattribute__(self, attr):
+ return 'calling __getattribute__'
+--fcc-editable-region--
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+
+print(v1.x)
+print(getattr(v1, 'x'))
+
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
new file mode 100644
index 00000000000..598c9822428
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/666832e427d70bc5219dc62a.md
@@ -0,0 +1,62 @@
+---
+id: 666832e427d70bc5219dc62a
+title: Step 36
+challengeType: 20
+dashedName: step-36
+---
+
+# --description--
+
+As you can see from the output, although you defined `__getattr__` in your class, this method is not called yet. This happens because the default attribute access occurs through `__getattribute__`. Therefore, you can see the attribute value printed on the terminal.
+
+Now modify the last two lines of code to access the `z` attribute of `v1` in both your `print()` calls. This time, you are going to access an attribute that `v1` does not have. As a result, `__getattribute__` will raise an error and `__getattr__` will be called.
+
+# --hints--
+
+You should modify your code to print the `z` attribute of `v1` using both the dot operator and the `getattr()` function.
+
+```js
+({ test: () => assert(runPython(`
+n = _Node(_code)
+(n.has_call("print(v1.z)") and n.has_call("print(getattr(v1, 'z'))")) or n.has_call("print(v1.z, getattr(v1, 'z'))") or n.has_call("print(getattr(v1, 'z'), v1.z)")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+--fcc-editable-region--
+print(v1.x)
+print(getattr(v1, 'x'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
new file mode 100644
index 00000000000..3f18e7c657c
--- /dev/null
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-special-methods-by-building-a-vector-space/6668374ed18b7fce10259cb3.md
@@ -0,0 +1,75 @@
+---
+id: 6668374ed18b7fce10259cb3
+title: Step 37
+challengeType: 20
+dashedName: step-37
+---
+
+# --description--
+
+Now that you have an idea of how the attribute access work, remove the last two lines of your code together with the `__getattr__` method.
+
+Then, restore the `print()` calls you commented out before and delete the second argument from both of them.
+
+# --hints--
+
+You should not have a `__getattr__` method.
+
+```js
+({ test: () => assert.isFalse(runPython(`_Node(_code).find_class("R2Vector").has_function("__getattr__")`)) })
+```
+
+You should not have `print(v1.z)`and `print(getattr(v1, 'z'))` in your code.
+
+```js
+({ test: () => assert.isFalse(runPython(`
+n = _Node(_code)
+n.has_call("print(v1.z)") or n.has_call("print(getattr(v1, 'z'))")
+`)) })
+```
+
+You should restore the `print()` calls you commented out before and remove the second argument from both of them.
+
+```js
+({ test: () => assert(runPython(`
+_Node(_code).has_call("print(f'v1 = {v1}')") and _Node(_code).has_call("print(f'v2 = {v2}')")
+`)) })
+```
+
+# --seed--
+
+## --seed-contents--
+
+```py
+class R2Vector:
+ def __init__(self, *, x, y):
+ self.x = x
+ self.y = y
+
+ def norm(self):
+ return sum(val**2 for val in vars(self).values())**0.5
+
+ def __str__(self):
+ return str(tuple(getattr(self, i) for i in vars(self)))
+
+ def __repr__(self):
+ arg_list = [f'{key}={val}' for key, val in vars(self).items()]
+ args = ', '.join(arg_list)
+ return f'{self.__class__.__name__}({args})'
+--fcc-editable-region--
+ def __getattr__(self, attr):
+ return 'calling __getattr__'
+
+class R3Vector(R2Vector):
+ def __init__(self, *, x, y, z):
+ super().__init__(x=x, y=y)
+ self.z = z
+
+v1 = R2Vector(x=2, y=3)
+v2 = R3Vector(x=2, y=2, z=3)
+# print(f'v1 = {v1}', f'\nrepr = {repr(v1)}')
+# print(f'v2 = {v2}', f'\nrepr = {repr(v2)}')
+print(v1.z)
+print(getattr(v1, 'z'))
+--fcc-editable-region--
+```
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
index 1cb6148af6a..5ca8b18ffd4 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553ed69ece88d29594748aa.md
@@ -1,6 +1,6 @@
---
id: 6553ed69ece88d29594748aa
-title: Крок 50
+title: Step 52
challengeType: 20
dashedName: step-52
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
index d7aad6b812c..509855be99c 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553efd6ada3f42aa2d75448.md
@@ -1,6 +1,6 @@
---
id: 6553efd6ada3f42aa2d75448
-title: Крок 51
+title: Step 53
challengeType: 20
dashedName: step-53
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
index f9fedd21625..f8a15f68b89 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f3fc92741c2bf8ded140.md
@@ -1,6 +1,6 @@
---
id: 6553f3fc92741c2bf8ded140
-title: Крок 52
+title: Step 54
challengeType: 20
dashedName: step-54
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
index b57aea454ee..3fd6e427f16 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f4f66099802c6ae94613.md
@@ -1,6 +1,6 @@
---
id: 6553f4f66099802c6ae94613
-title: Крок 53
+title: Step 55
challengeType: 20
dashedName: step-55
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
index 8f74d553e90..ad4fb72f01d 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f6086add4b2cbb99fd78.md
@@ -1,6 +1,6 @@
---
id: 6553f6086add4b2cbb99fd78
-title: Крок 54
+title: Step 56
challengeType: 20
dashedName: step-56
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
index 405e3349187..2d24fc08b60 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6553f8c570f9982e013a8886.md
@@ -1,6 +1,6 @@
---
id: 6553f8c570f9982e013a8886
-title: Крок 55
+title: Step 57
challengeType: 20
dashedName: step-57
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
index 7b25f165bb8..70cef98bd1b 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655491bd5b98b813fa5bedca.md
@@ -1,6 +1,6 @@
---
id: 655491bd5b98b813fa5bedca
-title: Крок 56
+title: Step 58
challengeType: 20
dashedName: step-58
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
index 2b587314523..1004d617f04 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554930320d70414e7b6acc6.md
@@ -1,6 +1,6 @@
---
id: 6554930320d70414e7b6acc6
-title: Крок 57
+title: Step 59
challengeType: 20
dashedName: step-59
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
index b7208b44d69..ac5ceeb5c0a 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549561463f0016876e852c.md
@@ -1,6 +1,6 @@
---
id: 65549561463f0016876e852c
-title: Крок 58
+title: Step 60
challengeType: 20
dashedName: step-60
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
index 6be39efa631..fc1f45dec78 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65549f90cf78131c96ebcf28.md
@@ -1,6 +1,6 @@
---
id: 65549f90cf78131c96ebcf28
-title: Крок 59
+title: Step 61
challengeType: 20
dashedName: step-61
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
index 9987261faef..c298af7fc32 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a334a40edb1fb4eff827.md
@@ -1,6 +1,6 @@
---
id: 6554a334a40edb1fb4eff827
-title: Крок 60
+title: Step 62
challengeType: 20
dashedName: step-62
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
index 5a527415fef..5e42d12224b 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a49a4f782f208abcc87e.md
@@ -1,6 +1,6 @@
---
id: 6554a49a4f782f208abcc87e
-title: Крок 61
+title: Step 63
challengeType: 20
dashedName: step-63
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
index 85951409aa3..7841247c373 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a57ec0a2c52106e7ee50.md
@@ -1,6 +1,6 @@
---
id: 6554a57ec0a2c52106e7ee50
-title: Крок 62
+title: Step 64
challengeType: 20
dashedName: step-64
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
index 4044d5dee37..24598e804bf 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554a88d5af937226f4a9121.md
@@ -1,6 +1,6 @@
---
id: 6554a88d5af937226f4a9121
-title: Крок 63
+title: Step 65
challengeType: 20
dashedName: step-65
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
index 18b27f1fee6..06736eb0fc2 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ac937a49be2701af4f2f.md
@@ -1,6 +1,6 @@
---
id: 6554ac937a49be2701af4f2f
-title: Крок 64
+title: Step 66
challengeType: 20
dashedName: step-66
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
index 0009ac99c5b..df574934ea3 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554ad2463b8892748f8efdd.md
@@ -1,6 +1,6 @@
---
id: 6554ad2463b8892748f8efdd
-title: Крок 65
+title: Step 67
challengeType: 20
dashedName: step-67
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
index fb1c090ab8e..c48ac3f2236 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d0332949b133a0b35eaa.md
@@ -1,6 +1,6 @@
---
id: 6554d0332949b133a0b35eaa
-title: Крок 66
+title: Step 68
challengeType: 20
dashedName: step-68
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
index e335bfd51ad..44c2760e839 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d15c8acb5f34499ad789.md
@@ -1,6 +1,6 @@
---
id: 6554d15c8acb5f34499ad789
-title: Крок 67
+title: Step 69
challengeType: 20
dashedName: step-69
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
index 44a5e7d3f90..4bdc1d496d5 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554d25dc5ceaa354307a77e.md
@@ -1,6 +1,6 @@
---
id: 6554d25dc5ceaa354307a77e
-title: Крок 68
+title: Step 70
challengeType: 20
dashedName: step-70
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
index c2630f990cd..775f753b664 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554de295ade563a069936a1.md
@@ -1,6 +1,6 @@
---
id: 6554de295ade563a069936a1
-title: Крок 69
+title: Step 71
challengeType: 20
dashedName: step-71
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
index 05f62b2abaa..966e04e5922 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554dfce1683be3c0c9609a6.md
@@ -1,6 +1,6 @@
---
id: 6554dfce1683be3c0c9609a6
-title: Крок 70
+title: Step 72
challengeType: 20
dashedName: step-72
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
index 1b5d8d621bf..61729964d8d 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e0adc7bb193cbfdb36d5.md
@@ -1,6 +1,6 @@
---
id: 6554e0adc7bb193cbfdb36d5
-title: Крок 71
+title: Step 73
challengeType: 20
dashedName: step-73
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
index 34f97944b7c..d42ac8dfeb7 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e2ee23bfd93f2c83640f.md
@@ -1,6 +1,6 @@
---
id: 6554e2ee23bfd93f2c83640f
-title: Крок 72
+title: Step 74
challengeType: 20
dashedName: step-74
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
index 8f7efdfb87e..f949a598d11 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6554e343caea913ffba7bec6.md
@@ -1,6 +1,6 @@
---
id: 6554e343caea913ffba7bec6
-title: Крок 73
+title: Step 75
challengeType: 20
dashedName: step-75
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
index f68b9d76d0f..43a8c50496b 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655516e410b8e30fb4fb64e8.md
@@ -1,6 +1,6 @@
---
id: 655516e410b8e30fb4fb64e8
-title: Крок 74
+title: Step 76
challengeType: 20
dashedName: step-76
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
index d0bec5764e0..74a3e0a9fe1 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65551a628bcb7e121e32d04b.md
@@ -1,6 +1,6 @@
---
id: 65551a628bcb7e121e32d04b
-title: Крок 77
+title: Step 79
challengeType: 20
dashedName: step-79
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
index ca92c11b66d..e6a4f04c983 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555201d9b7fc917399f9f0b.md
@@ -1,6 +1,6 @@
---
id: 6555201d9b7fc917399f9f0b
-title: Крок 78
+title: Step 80
challengeType: 20
dashedName: step-80
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
index c4ec8605c77..0a53fe9eba8 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655520c20cb1e6177b0641d6.md
@@ -1,6 +1,6 @@
---
id: 655520c20cb1e6177b0641d6
-title: Крок 79
+title: Step 81
challengeType: 20
dashedName: step-81
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
index 6751480f7d3..7778940f535 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/655522883e66f618e03a9411.md
@@ -1,6 +1,6 @@
---
id: 655522883e66f618e03a9411
-title: Крок 80
+title: Step 82
challengeType: 20
dashedName: step-82
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
index 68f226b7a7c..17e23a6800f 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555231eac4d9f19bd3d44b5.md
@@ -1,6 +1,6 @@
---
id: 6555231eac4d9f19bd3d44b5
-title: Крок 81
+title: Step 83
challengeType: 20
dashedName: step-83
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
index 5ec03f99d19..e2ed6e2e717 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a111190e11f0963949e.md
@@ -1,6 +1,6 @@
---
id: 65552a111190e11f0963949e
-title: Крок 82
+title: Step 84
challengeType: 20
dashedName: step-84
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
index 09495f5c48d..09a8591efd9 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552a9593755e1fb2f5ab50.md
@@ -1,6 +1,6 @@
---
id: 65552a9593755e1fb2f5ab50
-title: Крок 83
+title: Step 85
challengeType: 20
dashedName: step-85
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
index 57e483fd868..820ad829c3a 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65552b14e803731fe3c1e4ca.md
@@ -1,6 +1,6 @@
---
id: 65552b14e803731fe3c1e4ca
-title: Крок 84
+title: Step 86
challengeType: 20
dashedName: step-86
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
index d44b44e3adb..67e3ffd8789 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65553159615a8123b190ee43.md
@@ -1,6 +1,6 @@
---
id: 65553159615a8123b190ee43
-title: Крок 85
+title: Step 87
challengeType: 20
dashedName: step-87
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
index f747eb24e6d..294f60658b9 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d6e12c95701172b55709.md
@@ -1,6 +1,6 @@
---
id: 6555d6e12c95701172b55709
-title: Крок 75
+title: Step 77
challengeType: 20
dashedName: step-77
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
index 9fba4866fa3..21418787d2c 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555d8b0b3d20b128bdadd37.md
@@ -1,6 +1,6 @@
---
id: 6555d8b0b3d20b128bdadd37
-title: Крок 76
+title: Step 78
challengeType: 20
dashedName: step-78
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
index 8db908b7f58..a97af3e5f37 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555db4a7b788e15795674e5.md
@@ -1,6 +1,6 @@
---
id: 6555db4a7b788e15795674e5
-title: Крок 87
+title: Step 89
challengeType: 20
dashedName: step-89
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
index c4ae37b63fb..159e8fbb201 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555df0c81300b175308557d.md
@@ -1,6 +1,6 @@
---
id: 6555df0c81300b175308557d
-title: Крок 88
+title: Step 90
challengeType: 20
dashedName: step-90
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
index 3c3bceb891a..ae68e06c1e5 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e1bfcd374e18c6be8e58.md
@@ -1,6 +1,6 @@
---
id: 6555e1bfcd374e18c6be8e58
-title: Крок 89
+title: Step 91
challengeType: 20
dashedName: step-91
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
index 61b3bf5456c..c36c2d5cdf4 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e3f387381a19d5e00333.md
@@ -1,6 +1,6 @@
---
id: 6555e3f387381a19d5e00333
-title: Крок 90
+title: Step 92
challengeType: 20
dashedName: step-92
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
index 71c49da7532..6c8f8970c4b 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e43e783ed31a0532b1b2.md
@@ -1,6 +1,6 @@
---
id: 6555e43e783ed31a0532b1b2
-title: Крок 91
+title: Step 93
challengeType: 20
dashedName: step-93
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
index a7094438dd4..0c7bc9ec362 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e547c18a2b1a7b795bd8.md
@@ -1,6 +1,6 @@
---
id: 6555e547c18a2b1a7b795bd8
-title: Крок 93
+title: Step 95
challengeType: 20
dashedName: step-95
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
index de2944f5c01..db78be78018 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/6555e5991af57d1ae0e35f0a.md
@@ -1,6 +1,6 @@
---
id: 6555e5991af57d1ae0e35f0a
-title: Крок 94
+title: Step 96
challengeType: 20
dashedName: step-96
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
index e026f216451..da7cf8cda88 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a450e8fb2c9d75c7378d28.md
@@ -1,6 +1,6 @@
---
id: 65a450e8fb2c9d75c7378d28
-title: Крок 86
+title: Step 88
challengeType: 20
dashedName: step-88
---
diff --git a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
index 1a8c9c55e5f..53dbb673e44 100644
--- a/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
+++ b/curriculum/challenges/ukrainian/07-scientific-computing-with-python/learn-string-manipulation-by-building-a-cipher/65a51c9e000b660122b8b29e.md
@@ -1,6 +1,6 @@
---
id: 65a51c9e000b660122b8b29e
-title: Крок 92
+title: Step 94
challengeType: 20
dashedName: step-94
---
diff --git a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md b/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
deleted file mode 100644
index a7122a305f2..00000000000
--- a/curriculum/challenges/ukrainian/15-javascript-algorithms-and-data-structures-22/learn-basic-javascript-by-building-a-role-playing-game/62aa1fed3d4e873366ff3131.md
+++ /dev/null
@@ -1,344 +0,0 @@
----
-id: 62aa1fed3d4e873366ff3131
-title: Step 150
-challengeType: 0
-dashedName: step-150
----
-
-# --description--
-
-Створіть інструкцію `if` під змінною `health` у своїй функції `attack`. Встановіть умову для виклику функції `isMonsterHit`.
-
-# --hints--
-
-Ви повинні додати інструкцію `if`, яка викликає `isMonsterHit` в умові.
-
-```js
-assert.match(attack.toString(), /if\s*\(\s*isMonsterHit\s*\(\s*\)/)
-```
-
-# --seed--
-
-## --seed-contents--
-
-```html
-
-
-
-
-
-