chore(i18n,learn): processed translations (#55488)

This commit is contained in:
freeCodeCamp's Camper Bot
2024-07-11 22:11:30 -05:00
committed by GitHub
parent 8ca1f764a6
commit a1b40fecb9
776 changed files with 84742 additions and 75 deletions

View File

@@ -0,0 +1,30 @@
---
id: 662a6bc12cde72c32fb526f0
title: Step 1
challengeType: 20
dashedName: step-1
---
# --description--
An <dfn>interface</dfn> is like a blueprint for a class. An interface contains a set of methods and properties that a class should implement.
Start this project by declaring an empty class named `Equation`. You will use this class to define an interface, a blueprint for a generic equation.
# --hints--
You should define a new class named `Equation`.
```js
({ test: () => assert(runPython(`_Node(_code).has_class("Equation")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
--fcc-editable-region--
```

View File

@@ -0,0 +1,47 @@
---
id: 662bd456896f16d9bd03f1a6
title: Step 2
challengeType: 20
dashedName: step-2
---
# --description--
Within the `Equation` class, define two new instance methods named `solve` and `analyze`.
# --hints--
You should define a method named `solve` within the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").has_function("solve")`)) })
```
Your `solve` method should take one parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("solve").has_args("self")`)) })
```
You should define a method named `analyze` within the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").has_function("analyze")`)) })
```
Your `analyze` method should take one parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("analyze").has_args("self")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
class Equation:
pass
--fcc-editable-region--
```

View File

@@ -0,0 +1,40 @@
---
id: 662bd552e1c1d2db1b88ba47
title: Step 3
challengeType: 20
dashedName: step-3
---
# --description--
Now, define another class named `LinearEquation` and make it inherit from `Equation`. You'll use this class to represent linear equations.
# --hints--
You should define a class named `LinearEquation`.
```js
({ test: () => assert(runPython(`_Node(_code).has_class("LinearEquation")`)) })
```
Your `LinearEquation` class should inherit from the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").inherits_from("Equation")`)) })
```
# --seed--
## --seed-contents--
```py
class Equation:
def solve(self):
pass
def analyze(self):
pass
--fcc-editable-region--
--fcc-editable-region--
```

View File

@@ -0,0 +1,48 @@
---
id: 662bd8260da84bdd5feae419
title: Step 4
challengeType: 20
dashedName: step-4
---
# --description--
You want the `LinearEquation` class to implement and not simply inherit all the methods defined inside the `Equation` class, which should act as an interface.
Currently, the `Equation` class is simply the parent class of `LinearEquation`. In the next steps you will learn how to turn it into a formal interface.
For now, create an instance of `Equation` and assign it to a variable `eq`, and an instance of `LinearEquation` and assign it to a variable `lin_eq`.
# --hints--
You should declare a variable `eq` and assign it an instance of `Equation`.
```js
({ test: () => assert(runPython(`_Node(_code).has_stmt("eq = Equation()")`)) })
```
You should declare a variable `lin_eq` and assign it an instance of `LinearEquation`.
```js
({ test: () => assert(runPython(`_Node(_code).has_stmt("lin_eq = LinearEquation()")`)) })
```
# --seed--
## --seed-contents--
```py
class Equation:
def solve(self):
pass
def analyze(self):
pass
class LinearEquation(Equation):
pass
--fcc-editable-region--
--fcc-editable-region--
```

View File

@@ -0,0 +1,44 @@
---
id: 662bdd364bf2cde1487922a9
title: Step 5
challengeType: 20
dashedName: step-5
---
# --description--
Unlike other programming languages, Python does not implement interfaces in its core language, but the Python standard library allows you to define interfaces in a simple way.
For this project, you'll use utilities from the `abc` module. Therefore, import this module in your code.
# --hints--
You should import the `abc` module.
```js
({ test: () => assert(runPython(`_Node(_code).has_import("import abc")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
--fcc-editable-region--
class Equation:
def solve(self):
pass
def analyze(self):
pass
class LinearEquation(Equation):
pass
eq = Equation()
lin_eq = LinearEquation()
```

View File

@@ -0,0 +1,52 @@
---
id: 662bde88dc84f1e249801b1a
title: Step 6
challengeType: 20
dashedName: step-6
---
# --description--
`ABC` stands for *Abstract Base Classes*. The `ABC` class enables you to turn a regular class into an abstract class, which is a class that acts as a blueprint for concrete classes.
Modify your `import` statement to import just the `ABC` class from the `abc` module. You can import a specific object `x` from a module `y` following the import construct `from y import x`.
Then, turn your `Equation` class into an abstract class by making it inherit from `ABC`.
# --hints--
You should import `ABC` from the `abc` module.
```js
({ test: () => assert(runPython(`_Node(_code).has_import("from abc import ABC")`)) })
```
Your `Equation` class should inherit from `ABC`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").inherits_from("ABC")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
import abc
class Equation:
def solve(self):
pass
def analyze(self):
pass
class LinearEquation(Equation):
pass
eq = Equation()
lin_eq = LinearEquation()
--fcc-editable-region--
```

View File

@@ -0,0 +1,57 @@
---
id: 662f6d7c92381a3049e4c987
title: Step 8
challengeType: 20
dashedName: step-8
---
# --description--
An interface doesn't have to define only abstract methods, but it can also implement methods to be inherited by the concrete classes.
Before taking care of the actual implementation of `solve` and `analyze`, within the `Equation` class, define an `__init__` method. Do not use any decorator on it.
# --hints--
You should define an `__init__` method in your `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").has_function("__init__")`)) })
```
Your `__init__` method should take one parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").has_args("self")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
from abc import ABC, abstractmethod
class Equation(ABC):
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation()
--fcc-editable-region--
```

View File

@@ -0,0 +1,88 @@
---
id: 662f96576ef178927de87975
title: Step 7
challengeType: 20
dashedName: step-7
---
# --description--
In order to be recognized as an abstract method, a method should be decorated with the `@abstractmethod` decorator.
Modify your import statement to import the `abstractmethod` decorator and decorate both the `solve` and `analyze` methods of the `Equation` class. This will raise two exceptions.
Once a class inheriting from `ABC` has an abstract method, the class cannot be instantiated anymore. Therefore, delete the `Equation` instance to get rid of the error.
The other error occurs because the `LinearEquation` class must implement all the abstract methods defined in the interface. Make sure to define them inside the `LinearEquation` class, too. You must not use the `abstractmethod` decorator in the concrete class.
# --hints--
You should import `abstractmethod` from the `abc` module.
```js
({ test: () => assert(runPython(`
_Node(_code).has_import("from abc import ABC, abstractmethod") or \\
_Node(_code).has_import("from abc import abstractmethod, ABC") or \\
(_Node(_code).has_import("from abc import abstractmethod") and _Node(_code).has_import("from abc import ABC"))
`)) })
```
You should decorate with `@abstractmethod` the `solve` method within the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("solve").has_decorators("abstractmethod")`)) })
```
You should decorate with `@abstractmethod` the `analyze` method within the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("analyze").has_decorators("abstractmethod")`)) })
```
You should define a method named `solve` within the `LinearEquation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").has_function("solve")`)) })
```
Your `solve` method should take one parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").find_function("solve").has_args("self")`)) })
```
You should define a method named `analyze` within the `LinearEquation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").has_function("analyze")`)) })
```
Your `solve` method should take one parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").find_function("analyze").has_args("self")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
from abc import ABC
class Equation(ABC):
def solve(self):
pass
def analyze(self):
pass
class LinearEquation(Equation):
pass
eq = Equation()
lin_eq = LinearEquation()
--fcc-editable-region--
```

View File

@@ -0,0 +1,52 @@
---
id: 662fa2e2cf27c09f21f4f5d0
title: Step 9
challengeType: 20
dashedName: step-9
---
# --description--
In Python, data types are recognized during runtime (when the code is executed). Therefore, you don't have to specify the data type of a variable when you declare it. Nonetheless, you can annotate a variable to clarify that it will hold a specific data type with `variable: <data type> = value` or just `variable: <data type>`. Note that the Python interpreter does not enforce the types used to annotate variables, and normally you'd need external tools to do it.
Inside the `Equation` class, define a class attribute `degree`. Do not assign it a value. Instead use a type annotation of `int` to show that it will store an integer number inside the concrete classes.
Later on, you'll use this class attribute as a part of the validation process of the arguments passed to instantiate the equation objects.
# --hints--
You should define class attribute named `degree` and annotate it with `int` within the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_variable("degree").is_equivalent("degree: int")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
--fcc-editable-region--
class Equation(ABC):
def __init__(self):
pass
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
def solve(self):
pass
def analyze(self):
pass
--fcc-editable-region--
lin_eq = LinearEquation()
```

View File

@@ -0,0 +1,83 @@
---
id: 662fbcef5f05e1b84f541a0c
title: Step 13
challengeType: 20
dashedName: step-13
---
# --description--
Each equation object will be instantiated passing as many arguments as the coefficients of the equation, starting from n-th degree of \\( x \\) down to the zero-th degree, including the possible coefficient with the value of `0`.
For example, `LinearEquation(4, 5)` would represent the equation \\( 4x + 5 = 0 \\), with `4` being the coefficient of the first (highest here) degree and `5` the coefficient of the zero-th degree.
You need to check that the right number of arguments is passed to instantiate the equation object.
Inside the `__init__` method, create an `if` statement to check if the length of `args` is different from the number of coefficients the equation should have (`degree + 1`). If it is, raise a `TypeError` and use the following string to provide a custom message: `f"'{self.__class__.__name__}' object takes {self.degree + 1} positional arguments but {len(args)} were given"`.
Then, fix the error by passing the `2` and `3` to instantiate `lin_eq`.
# --hints--
You should create an `if` statement that checks if the number of coefficients used to instantiate the equation is different from `degree + 1`.
```js
({ test: () => assert(runPython(`
cond = _Node(_code).find_class("Equation").find_function("__init__").find_ifs()[0].find_conditions()[0]
cond.is_equivalent("(self.degree + 1) != len(args)") or cond.is_equivalent("len(args) != (self.degree + 1)")
`)) })
```
You should raise a `TypeError` within the new `if` statement and use the provided string to return a custom error message.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").find_ifs()[0].find_bodies()[0].has_stmt('raise TypeError(f"\\'{self.__class__.__name__}\\' object takes {self.degree + 1} positional arguments but {len(args)} were given")')
`)) })
```
You should pass `2` and `3` to instantiate `lin_eq`.
```js
({ test: () => assert(runPython(`_Node(_code).has_stmt("lin_eq = LinearEquation(2, 3)")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
--fcc-editable-region--
def __init__(self, *args):
pass
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation()
--fcc-editable-region--
```

View File

@@ -0,0 +1,87 @@
---
id: 662fc3eba556a6bf800d48c1
title: Step 14
challengeType: 20
dashedName: step-14
---
# --description--
The `isinstance()` built-in function takes two arguments and returns a Boolean indicating if the object passed as the first argument is an instance of the class passed as the second argument.
```py
isinstance(7, int) # True
```
Another thing you want to check is that every argument is a number. After your first `if`, create a `for` loop that iterates over `args` and checks if the argument at the current iteration is not an instance of `int` or `float`. Use the `isinstance()` function and pass it a tuple containing `int` and `float` as the second argument.
If the argument is not a number, raise a `TypeError` saying `"Coefficients must be of type 'int' or 'float'"`.
# --hints--
You should create a `for` loop that iterates over `args` after your `if` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").find_for_loops()[0].find_for_iter().is_equivalent("args")`)) })
```
You should create an `if` statement that checks if the current coefficient is not an instance of either `int` or `float` within the `for` loop.
```js
({ test: () => assert(runPython(`
var = str(_Node(_code).find_class("Equation").find_function("__init__").find_for_loops()[0].find_for_vars())
cond1 = f'not isinstance({var}, (int, float))'
cond2 = f'not isinstance({var}, (float, int))'
if_stmt = _Node(_code).find_class("Equation").find_function("__init__").find_for_loops()[0].find_ifs()[0].find_conditions()[0]
if_stmt.is_equivalent(cond1) or if_stmt.is_equivalent(cond2)
`)) })
```
You should use the provided string to raise a `TypeError` within the `if` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").find_for_loops()[0].find_ifs()[0].find_bodies()[0].has_stmt("raise TypeError(\\"Coefficients must be of type 'int' or 'float'\\")")
`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
--fcc-editable-region--
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'{self.__class__.__name__}' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
--fcc-editable-region--
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
```

View File

@@ -0,0 +1,74 @@
---
id: 6639f947d3a1818c9322c64a
title: Step 16
challengeType: 20
dashedName: step-16
---
# --description--
The last step of validating the coefficients is checking that the highest degree coefficient is different from zero. Remember that the highest degree coefficient should be passed as the first argument when instantiating the object.
Add an `if` statement for that and raise a `ValueError` using the following string to provide a custom message: `'Highest degree coefficient must be different from zero'`.
# --hints--
You should create an `if` statement that checks if the first coefficient passed to instantiate the equation is equal to zero.
```js
({ test: () => assert(runPython(`
cond = _Node(_code).find_class("Equation").find_function("__init__").find_ifs()[2].find_conditions()[0]
cond.is_equivalent("args[0] == 0") or cond.is_equivalent("0 == args[0]") or cond.is_equivalent("not args[0]")
`)) })
```
You should raise a `ValueError` within the new `if` statement and use the provided string to return a custom error message.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").find_ifs()[2].find_bodies()[0].has_stmt("raise ValueError('Highest degree coefficient must be different from zero')")
`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
--fcc-editable-region--
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
--fcc-editable-region--
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
```

View File

@@ -0,0 +1,94 @@
---
id: 6639fdcc701833a54c364211
title: Step 17
challengeType: 20
dashedName: step-17
---
# --description--
After validating the coefficients, you need to store them in an instance attribute. Use a dictionary comprehension to create a dictionary in which the key is the degree of the coefficient and the corresponding value is the coefficient, and assign it to an attribute named `coefficients`.
For example, a `LinearEquation` object instantiated with `2` and `4` should have the following `coefficients` attribute: `{1: 2, 0: 4}`, because `2` corresponds to the first degree of `x` and `4` corresponds to zero-th degree of `x`.
Create the key-value pairs in your new dictionary following the same order as in `args`.
# --hints--
You should declare an attribute named `coefficients` within your `__init__` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").has_variable("self.coefficients")`)) })
```
You should use a dictionary comprehension to store your coefficients.
```js
({ test: () => runPython(`
import ast
node = _Node(_code).find_class("Equation").find_function("__init__").find_variable("self.coefficients")
assert isinstance(node.tree.value, ast.DictComp)
`) })
```
Your `coefficients` attribute should be a dictionary containing key-value pairs in the form degree-coefficient. Remember to follow the same order in which coefficients are stored inside `args`.
```js
({ test: () => runPython(`
actual1 = list(LinearEquation(1, 6).coefficients.items())
expected1 = list({1: 1, 0: 6}.items())
actual2 = list(LinearEquation(-3.5, 0).coefficients.items())
expected2 = list({1: -3.5, 0: 0}.items())
assert actual1 == expected1
assert actual2 == expected2
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
--fcc-editable-region--
--fcc-editable-region--
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
```

View File

@@ -0,0 +1,96 @@
---
id: 663a22ba7420c4d2f7fd2aec
title: Step 25
challengeType: 20
dashedName: step-25
---
# --description--
It's time to implement the `solve` method. Given a linear equation in the form \\( ax + b = 0 \\), the solution is \\(x = -\frac{b}{a}\\).
Unpack the coefficients stored in the `coefficients` attribute into the variables `a` and `b`. Note that you'll need to use the `.values()` method.
Then, declare a variable `x`, assign it the solution of the equation and return it from the `solve` method.
# --hints--
You should unpack the values stored inside the `coefficients` attribute into the variables `a` and `b`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").find_function("solve").has_stmt("a, b = self.coefficients.values()")`)) })
```
You should declare a variable named `x` and assign it the solution of the linear equation.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").find_function("solve").has_stmt("x = -b/a")`)) })
```
You should return `x` from your `solve` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").find_function("solve").has_return("x")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
continue
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+').strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
--fcc-editable-region--
def solve(self):
pass
--fcc-editable-region--
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,83 @@
---
id: 663a2dd1901cbeecc28748bd
title: Step 26
challengeType: 20
dashedName: step-26
---
# --description--
It's time to test the `solve` method. Call it on `lin_eq` and print the result.
# --hints--
You should call the `solve` method of your `lin_eq` object and print the result.
```js
({ test: () => assert(runPython(`
_Node(_code).has_call("print(lin_eq.solve())")
`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
pass
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
print(lin_eq)
--fcc-editable-region--
```

View File

@@ -0,0 +1,106 @@
---
id: 663a32735b317af9812eb0d7
title: Step 27
challengeType: 20
dashedName: step-27
---
# --description--
In linear equations in the form \\( ax + b = 0 \\), the slope is simply the coefficient \\( a \\), and the y-intercept is the coefficient \\( b \\).
<img alt="a plot of a linear function" src="https://cdn.freecodecamp.org/curriculum/python/linear-equation.png" style="background-color: white; height: 350px; width: auto; padding: 15px; display: block; margin-right: auto; margin-left: auto; margin-bottom: 1.2rem;" />
You are going to use the `analyze` method to provide additional information about the equation. Inside the `analyze` method, unpack the coefficients into the variables `slope` and `intercept`.
Then, return a dictionary with the keys `'slope'` and `'intercept'` and the values of the slope and the y-intercept, respectively. After that, call `analyze` on `lin_eq` and print the result.
# --hints--
You should unpack the values stored in the `coefficients` attribute into the variables `slope` and `intercept` inside the `analyze` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").find_function("analyze").has_stmt("slope, intercept = self.coefficients.values()")`)) })
```
The `analyze` method should return a dictionary with the keys `'slope'` and `'intercept'` and the values of the slope and the y-intercept, respectively.
```js
({ test: () => runPython(`
eq = LinearEquation(2.2, 1.5)
a = eq.analyze()
assert a['slope'] == 2.2, "Expected different slope"
assert a['intercept'] == 1.5, "Expected different intercept"
`) })
```
You should call the `analyze` method of your `lin_eq` object.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(lin_eq.analyze())")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
--fcc-editable-region--
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
print(lin_eq.solve())
--fcc-editable-region--
```

View File

@@ -0,0 +1,116 @@
---
id: 663b7fefd437bd984e091cbf
title: Step 29
challengeType: 20
dashedName: step-29
---
# --description--
Next, create a new class named `QuadraticEquation` and make it inherit from `Equation`. You'll use this new class to represent quadratic equations, which are second-degree equations having the form $ax^2 + bx + c = 0$.
Inside your new class, define a `degree` class attribute with the value `2`, which is the degree of a quadratic equation. Also, define the `solve` and `analyze` methods. You will take care of the implementation in the following steps.
# --hints--
You should create a new class named `QuadraticEquation` and make it inherit from the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").inherits_from("Equation")`)) })
```
You should define a `solve` method within the `QuadraticEquation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").has_function("solve")`)) })
```
Your `solve` method should take a single parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").find_function("solve").has_args("self")`)) })
```
You should define an `analyze` method within the `QuadraticEquation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").has_function("analyze")`)) })
```
Your `analyze` method should take a single parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").find_function("analyze").has_args("self")`)) })
```
You should define a `degree` class attribute within the `QuadraticEquation` class and assign it the value `2`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").find_variable("degree").is_equivalent("degree = 2")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
--fcc-editable-region--
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,97 @@
---
id: 663b83a28943e6aa6275a514
title: Step 19
challengeType: 20
dashedName: step-19
---
# --description--
Still within the `Equation` class, define a `__str__` method to give a proper string representation to the equation objects you are going to create.
For now, within the `__str__` method, declare a variable `terms` and assign it an empty list. You'll use this variable to store each term (coefficient times \\( x^n \\)) of your equation.
Then, declare a variable `equation_string`, assign it the result of joining the elements in the `terms` list with a space. Finally, return `equation_string`.
# --hints--
You should define a `__str__` method within the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").has_function("__str__")`)) })
```
Your `__str__` method should take one parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").has_args("self")`)) })
```
You should declare a variable `terms` and assign it an empty list within the `__str__` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").has_stmt("terms = []")`)) })
```
You should declare a variable `equation_string` and assign it the result of joining the elements in `terms` with a space within the `__str__` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").has_stmt("equation_string = ' '.join(terms)")`)) })
```
You should return `equation_string` from your `__str__` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").has_return("equation_string")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
--fcc-editable-region--
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,110 @@
---
id: 663b93aee129b3c4cc07d0db
title: Step 20
challengeType: 20
dashedName: step-20
---
# --description--
Just after the `terms` list, create a `for` loop and use the `.items()` method to iterate over the keys and values stored in the `coefficients` attribute. Use `n` and `coefficient` as the loop variables.
Inside the loop, create an `if` statement that checks if the coefficient at the current iteration has a falsy value and skip the iteration in that case. This is because you don't want to represent coefficients with the value of zero.
# --hints--
You should create a `for` loop that iterates over `coefficients.items()`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_for_iter().is_equivalent("self.coefficients.items()")`)) })
```
Your `for` loop should use `n` and `coefficient` to iterate over `coefficients.items()`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_for_vars().is_equivalent("n, coefficient")`)) })
```
You should create an `if` statement to check if `coefficient` has a falsy value inside your `for` loop.
```js
({ test: () => assert(runPython(`
if_cond = _Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[0].find_conditions()[0]
conditions = ["not coefficient", "coefficient == 0", "0 == coefficient"]
any(if_cond.is_equivalent(condition) for condition in conditions)
`)) })
```
You should use the `continue` keyword inside your new `if` statement.
```js
({ test: () => assert(runPython(`
_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[0].find_bodies()[0].has_stmt("continue")
`)) })
```
Your `for` loop should be placed just after the declaration of `terms`.
```js
({ test: () => assert(runPython(`
loop = str(_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0])
_Node(_code).find_class("Equation").find_function("__str__").is_ordered("terms = []", loop, "equation_string = ' '.join(terms)", "return equation_string")
`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
--fcc-editable-region--
def __str__(self):
terms = []
--fcc-editable-region--
equation_string = ' '.join(terms)
return equation_string
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,82 @@
---
id: 663b95d65caeb3ca04c5fef4
title: Step 21
challengeType: 20
dashedName: step-21
---
# --description--
If the coefficient has a non-zero value, you can have different cases. If `n == 0`, the term is made by the coefficient itself.
After your `if` statement, create another `if` statement for this case and append a string containing the coefficient to the `terms` list. Use an f-string for that.
# --hints--
You should create an `if` statement to check if `n` is equal to `0` after your existing `if` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_conditions()[0].is_equivalent("n==0")`)) })
```
You should append `f'{coefficient}'` to the `terms` list within your new `if` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_bodies()[0].is_equivalent("terms.append(f'{coefficient}')")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
--fcc-editable-region--
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
continue
equation_string = ' '.join(terms)
return equation_string
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,84 @@
---
id: 663c981b9b06922e13a97fe9
title: Step 22
challengeType: 20
dashedName: step-22
---
# --description--
Create an `elif` clause for the case `n == 1`. Within the `elif` clause, create an f-string containing the coefficient directly followed by a lowercase `x` and append it to the `terms` list.
# --hints--
You should create an `elif` clause to check if `n` is equal to `1`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_conditions()[1].is_equivalent("n==1")`)) })
```
You should append `f'{coefficient}x'` to the `terms` list within your new `elif` clause.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_bodies()[1].is_equivalent("terms.append(f'{coefficient}x')")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
--fcc-editable-region--
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
continue
if n == 0:
terms.append(f'{coefficient}')
equation_string = ' '.join(terms)
return equation_string
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,86 @@
---
id: 663c9f31306353460da54542
title: Step 23
challengeType: 20
dashedName: step-23
---
# --description--
As you can see, the `+` sign is missing from the output. The number sign is displayed by default only if negative. To change this behaviour, you can write a colon after the expression to be evaluated within the curly braces of your f-string, and specify the option `+`. This will allow you to display the sign both for positive and negative numbers.
Modify the string in your two conditional clauses by adding `:+` inside the curly braces after `coefficient`.
# --hints--
You should modify the string to append to the `terms` list within your `if` statement into `f'{coefficient:+}'`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_bodies()[0].is_equivalent("terms.append(f'{coefficient:+}')")`)) })
```
You should modify the string to insert into the `terms` list within your `elif` clause into `f'{coefficient:+}x'`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_bodies()[1].is_equivalent("terms.append(f'{coefficient:+}x')")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
--fcc-editable-region--
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
continue
if n == 0:
terms.append(f'{coefficient}')
elif n == 1:
terms.append(f'{coefficient}x')
equation_string = ' '.join(terms)
return equation_string
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,66 @@
---
id: 664c670069bae45fd060c25d
title: Step 18
challengeType: 20
dashedName: step-18
---
# --description--
Next, print your `lin_eq` instance.
# --hints--
You should print `lin_eq`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(lin_eq)")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
--fcc-editable-region--
```

View File

@@ -0,0 +1,87 @@
---
id: 664cb04a16fe6938708967ef
title: Step 24
challengeType: 20
dashedName: step-24
---
# --description--
After joining the terms, concatenate the string `' = 0'` to `equation_string` to display the complete equation.
Also, to refine the output, remove any leading `+` sign from `equation_string`.
# --hints--
The `__str__` method should return a different string representation.
```js
({ test: () => assert(runPython(`
eq1 = LinearEquation(4, 2)
str(eq1) == '4x +2 = 0'
`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
continue
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
--fcc-editable-region--
equation_string = ' '.join(terms)
return equation_string
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,116 @@
---
id: 664e4a590b52ba8d2adff19f
title: Step 30
challengeType: 20
dashedName: step-30
---
# --description--
The discriminant of a quadratic equation in the form \\( ax^2 + bx + c = 0 \\), usually indicated by the capital Greek letter delta, is equal to \\( Δ = b^2 - 4ac \\).
Within the `QuadraticEquation` class, define an `__init__` method. Use `super()` to call the `__init__` method from the parent class. Then, define a new attribute named `delta`, which stores the value of the discriminant of the equation.
# --hints--
You should define an `__init__` method within the `QuadraticEquation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").has_function("__init__")`)) })
```
Your `__init__` method should take two parameters, `self` and `*args`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").find_function("__init__").has_args("self, *args")`)) })
```
You should call `super().__init__(*args)` within your `__init__` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").find_function("__init__").has_call("super().__init__(*args)")`)) })
```
You should declare a `delta` attribute within your `__init__` method and assign it the value of the discriminant of the equation.
```js
({ test: () => runPython(`
eq = QuadraticEquation(2, -3, -4)
assert eq.delta == 41
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
--fcc-editable-region--
--fcc-editable-region--
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,105 @@
---
id: 664e4e1b6c35a99cbba49e84
title: Step 31
challengeType: 20
dashedName: step-31
---
# --description--
Now, create an instance of the `QuadraticEquation` class to represent the equation \\( 11x^2 - x + 1 = 0 \\).
Assign the new instance to a variable `quadr_eq`, then print your new variable. Note that, at this point, the second degree term would be missing from the string representation of the equation.
# --hints--
You should declare a variable named `quadr_eq` and assign it an instance of `QuadraticEquation` passing it `11`, `-1`, and `1` as the arguments.
```js
({ test: () => assert(runPython(`_Node(_code).has_stmt("quadr_eq = QuadraticEquation(11, -1, 1)")`)) })
```
You should print your `quadr_eq` variable.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(quadr_eq)")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
pass
def analyze(self):
pass
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
print(lin_eq)
--fcc-editable-region--
```

View File

@@ -0,0 +1,110 @@
---
id: 664ee8037f4bbe3c0944c35e
title: Step 32
challengeType: 20
dashedName: step-32
---
# --description--
As you can see, the second-degree term is missing from the string representation. Within the `__str__` method, create an `else` clause to handle the case in which the exponent of \\( x \\) is greater than `1`.
Append a string to the `terms` list so that the term is represented as `<coefficient>x**<exponent>`. Display the number sign both for positive and negative coefficients and make sure that the inserted string is suitable to represent equations of degree > 2, too.
# --hints--
You should create an `else` clause after your existing `elif` clause.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_conditions()[2].is_empty()`)) })
```
You should append `f'{coefficient:+}x**{n}'` to the `terms` list within your new `else` clause.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_bodies()[2].is_equivalent("terms.append(f'{coefficient:+}x**{n}')")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
--fcc-editable-region--
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
--fcc-editable-region--
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(11, -1, 1)
print(quadr_eq)
```

View File

@@ -0,0 +1,105 @@
---
id: 664eec7f38234443b42c206f
title: Step 33
challengeType: 20
dashedName: step-33
---
# --description--
Your equation is currently represented as `11x**2 -1x +1 = 0`, but it would be nice not to display the coefficient multiplying \\( x \\) when it's equal to one. So that equation is represented as `11x**2 -x +1 = 0`.
Import the `re` module. You are going to use a regular expression to substitute the coefficients for this case during the next steps.
# --hints--
You should import the `re` module.
```js
({ test: () => assert(runPython(`_Node(_code).has_import("import re")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
--fcc-editable-region--
--fcc-editable-region--
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(11, -1, 1)
print(quadr_eq)
```

View File

@@ -0,0 +1,114 @@
---
id: 664eef158d792a509e8d708a
title: Step 34
challengeType: 20
dashedName: step-34
---
# --description--
The `sub` function from the `re` module enables you to replace text inside a string based on a regex pattern.
```py
verse = 'Always look on the bright side of life'
spam = re.sub('bright', 'spam', verse)
spam == 'Always look on the spam side of life' # True
```
It takes three arguments: the regex pattern to match, the replacement, and the string on which you want to perform the replacement.
From your `__str__` function, return a `sub()` call passing the string `'1'`, an empty string, and your existing `equation_string.strip('+')` call as the arguments. This will replace each `1` with an empty string. The result is not refined yet and you'll continue to work on the regex pattern in the next steps.
# --hints--
You should return a `re.sub()` call from your `__str__` method. Pass the string `'1'`, an empty string, and your existing `equation_string.strip('+')` call as the arguments to `re.sub()`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").has_return("re.sub('1', '', equation_string.strip('+'))")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
--fcc-editable-region--
return equation_string.strip('+')
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(11, -1, 1)
print(quadr_eq)
```

View File

@@ -0,0 +1,124 @@
---
id: 664ef4623946e65e18d59764
title: Step 35
challengeType: 20
dashedName: step-35
---
# --description--
In a regex pattern, a *lookaround* is an assertion that matches a certain pattern without consuming characters in the string. One kind of lookaround is the lookbehind, which can be either positive or negative. They are denoted by `(?<=...)` and `(?<!...)`, respectively.
```py
spam = 'black back bat'
re.sub('(?<=l)a', 'o', spam) == 'block back bat' # True
re.sub('(?<!l)a', 'o', spam) == 'black bock bot' # True
```
In the example above, the pattern `(?<=l)a` contains a positive lookbehind, which is used to match the `a` character only when preceded by an `l`. In the last line of the example, the pattern `(?<!l)a` contains a negative lookbehind, which is used to match the `a` character only if it is **not** preceded by an `l`. Note how, in both cases, the character contained in the lookbehind is not consumed.
Modify your regex pattern to use a negative lookbehind so that the character `1` is substituted only if not preceded by a digit.
# --hints--
You should modify the pattern passed as the first argument to the `re.sub()` call using a negative lookbehind. TODO: add details/improve wording
```js
({ test: () => assert(runPython(`
node = _Node(_code).find_class("Equation").find_function("__str__")
values = [
"re.sub('(?<!\\d)1', '', equation_string.strip('+'))",
"re.sub(r'(?<!\\d)1', '', equation_string.strip('+'))",
"re.sub('(?<![0-9])1', '', equation_string.strip('+'))"
]
any(node.has_return(value) for value in values)
`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
--fcc-editable-region--
return re.sub('1', '', equation_string.strip('+'))
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(11, -1, 1)
print(quadr_eq)
```

View File

@@ -0,0 +1,114 @@
---
id: 664f0389424a6f7aa15fd3e5
title: Step 36
challengeType: 20
dashedName: step-36
---
# --description--
Another kind of lookaround assertion is the lookahead. Positive and negative lookahead are denoted by `(?=...)` and `(?!...)`, respectively. They are used to match a pattern if followed by a certain sequence of characters, which is not consumed:
```py
spam = 'black back bat'
re.sub('a(?=t)', 'o', spam) == 'black back bot' # True
re.sub('a(?!t)', 'o', spam) == 'block bock bat' # True
```
In the example above, the pattern `a(?=t)` contains a positive lookahead, which is used to match the `a` character only when followed by a `t`. In the last line of the example, the pattern `a(?!t)` contains a negative lookahead, which is used to match the `a` character only if **not** followed by a `t`. Again, in both cases, the character contained in the lookahead is not consumed.
Add a positive lookahead to your regex pattern so that the character `1` is substituted only if followed by the character `x`.
# --hints--
You should modify your regex pattern using a positive lookahead to substitute the character `1` only if followed by an `x`. Do not remove the negative lookbehind from your pattern.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").has_return("re.sub(r'(?<!\\d)1(?=x)', '', equation_string.strip('+'))")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
--fcc-editable-region--
return re.sub(r'(?<!\d)1', '', equation_string.strip('+'))
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(11, -1, 1)
print(quadr_eq)
```

View File

@@ -0,0 +1,111 @@
---
id: 664f4559c17d2138ae680566
title: Step 37
challengeType: 20
dashedName: step-37
---
# --description--
It's time to implement the `solve` method. When the discriminant of the quadratic equation is negative, the equation does not have real solutions, or roots.
Within the `solve` method, create an `if` statement to check if the discriminant is negative. If it is, return an empty list.
# --hints--
You should create an `if` statement to check if `self.delta` is lower than `0`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").find_function("solve").find_ifs()[0].find_conditions()[0].is_equivalent("self.delta < 0")`)) })
```
You should return an empty list from your new `if` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").find_function("solve").find_ifs()[0].find_bodies()[0].has_return("[]")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
--fcc-editable-region--
def solve(self):
pass
--fcc-editable-region--
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(11, -1, 1)
print(quadr_eq)
```

View File

@@ -0,0 +1,111 @@
---
id: 6650583d9d9a194714da47f0
title: Step 38
challengeType: 20
dashedName: step-38
---
# --description--
The roots of quadratic equations can be found by applying the formula:
\\[ x = \frac{-b \pm \sqrt{b^2 - 4ac}}{2a} = \frac{-b \pm \sqrt{\Delta}}{2a} \\]
After the `if` statement, create two variables: assign them the root obtained by taking the plus sign between \\( b \\) and the square root of the discriminant in the formula above, and the root obtained by taking the minus sign. Then, return a list containing your two new variables.
# --hints--
Your `solve` method should return a list containing the correct solutions.
```js
({ test: () => runPython(`
eq = QuadraticEquation(-1, 2, 3)
assert eq.solve() == [-1, 3] or eq.solve() == [3, -1]
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
--fcc-editable-region--
def solve(self):
if self.delta < 0:
return []
--fcc-editable-region--
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(11, -1, 1)
print(quadr_eq)
```

View File

@@ -0,0 +1,109 @@
---
id: 6650633eaeccf266fee14ba6
title: Step 39
challengeType: 20
dashedName: step-39
---
# --description--
It's time to test the `solve` method. Call it on your `quadr_eq` instance and print the result.
# --hints--
You should print `quadr_eq.solve()`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(quadr_eq.solve())") or _Node(_code).has_call("print(quadr_eq.solve(), quadr_eq.results)")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
return [x1, x2]
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
--fcc-editable-region--
quadr_eq = QuadraticEquation(11, -1, 1)
print(quadr_eq)
--fcc-editable-region--
```

View File

@@ -0,0 +1,110 @@
---
id: 6650e11fa60e222e691bb283
title: Step 40
challengeType: 20
dashedName: step-40
---
# --description--
Modify the first argument used to instantiate `quadr_eq` into `-11`. In this way, the discriminant of the equation will be positive.
# --hints--
You should modify the first argument used to instantiate `quadr_eq` into `-11`.
```js
({ test: () => assert(runPython(`_Node(_code).has_stmt("quadr_eq = QuadraticEquation(-11, -1, 1)")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
return [x1, x2]
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
--fcc-editable-region--
quadr_eq = QuadraticEquation(11, -1, 1)
print(quadr_eq)
print(quadr_eq.solve())
--fcc-editable-region--
```

View File

@@ -0,0 +1,110 @@
---
id: 6650e27cf34f2335a9bbbd08
title: Step 41
challengeType: 20
dashedName: step-41
---
# --description--
One last check: modify your `quadr_eq` instance to represent the equation \\( x^2 + 2x + 1 = 0 \\).
# --hints--
You should modify the first two arguments used to instantiate `quadr_eq` into `1` and `2`.
```js
({ test: () => assert(runPython(`_Node(_code).has_stmt("quadr_eq = QuadraticEquation(1, 2, 1)")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
return [x1, x2]
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
--fcc-editable-region--
quadr_eq = QuadraticEquation(-11, -1, 1)
print(quadr_eq)
print(quadr_eq.solve())
--fcc-editable-region--
```

View File

@@ -0,0 +1,126 @@
---
id: 6650e88cc500673ec881c9ca
title: Step 42
challengeType: 20
dashedName: step-42
---
# --description--
In this case, the discriminant is zero and the two roots are coincidents.
Create an `if` statement to check if the discriminant is zero and return a list containing the root.
# --hints--
You should create an `if` statement to check if the `delta` attribute is equal to zero.
```js
({ test: () => assert(runPython(`
node = _Node(_code).find_class("QuadraticEquation").find_function("solve").find_ifs()[1].find_conditions()[0]
node.is_equivalent("self.delta == 0") or node.is_equivalent("not self.delta")
`)) })
```
You should return a list containing the root within your new `if` statement.
```js
({ test: () => runPython(`
eq = QuadraticEquation(4, 4, 1)
assert eq.solve() == [-0.5]
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
--fcc-editable-region--
--fcc-editable-region--
return [x1, x2]
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(1, 2, 1)
print(quadr_eq)
print(quadr_eq.solve())
```

View File

@@ -0,0 +1,115 @@
---
id: 6650eb84e248684c2f57555c
title: Step 43
challengeType: 20
dashedName: step-43
---
# --description--
In general, it is good practice to make the same methods from different classes return the same type of data. The `solve` method from the `QuadraticEquation` class returns a list, because quadratic equations can have two roots.
Although linear equations have a single real solution, modify the `solve` method within the `LinearEquation` class to return a list containing the root, so that the `solve` methods from different classes return the same type of data.
# --hints--
You should return a list containing the single root from the `solve` method of your `LinearEquation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").find_function("solve").has_return("[x]")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
--fcc-editable-region--
return x
--fcc-editable-region--
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(1, 2, 1)
print(quadr_eq)
print(quadr_eq.solve())
```

View File

@@ -0,0 +1,118 @@
---
id: 6650f037c017aa6855a608e3
title: Step 44
challengeType: 20
dashedName: step-44
---
# --description--
The graph of any quadratic equation has a parabolic shape. The \\( x \\) coordinate of the vertex of the parabola can be found at \\( x = - \frac{b}{2a} \\).
From the `analyze` method, return the dictionary containing two keys, `'x'`, and `'y'`, and the corresponding values of the vertex \\( x \\) and \\( y \\) coordinates, respectively.
Use the relation above to find the \\( x \\) coordinate. Then, use the \\( x \\) coordinate to calculate the \\( y \\) coordinate.
# --hints--
You should return a dictionary containing two keys, `'x'`, and `'y'`, and the corresponding values of vertex `x` and `y` coordinates, respectively.
```js
({ test: () => runPython(`
eq = QuadraticEquation(16, 2, 1)
assert eq.analyze() == {'x': -0.0625, 'y': 0.9375}
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
--fcc-editable-region--
def analyze(self):
pass
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(1, 2, 1)
print(quadr_eq)
print(quadr_eq.solve())
```

View File

@@ -0,0 +1,126 @@
---
id: 665460392acb7e91db2afad1
title: Step 45
challengeType: 20
dashedName: step-45
---
# --description--
When the second-degree coefficient is positive, the parabola has a minimum point and opens upward, or it is called concave upwards. Instead, when the second-degree coefficient is negative, the parabola has a maximum point and opens downward, or it is called concave downwards.
<img alt="two parabolas with different concavities" src="https://cdn.freecodecamp.org/curriculum/python/parabola.png" style="background-color: white; height: 350px; width: auto; padding: 15px; display: block; margin-right: auto; margin-left: auto; margin-bottom: 1.2rem;" />
Declare a `concavity` variable and assign it either the string `'upwards'` or `'downwards'`, depending on the concavity of the parabola. Also, declare a variable named `min_max` and assign it either the string `'min'` or `'max'`, depending on if the vertex is a minimum or a maximum, respectively.
Finally, add the dictionary to return two keys `'min_max'` and `'concavity'` with the values of `min_max'` and `concavity`, respectively.
# --hints--
Your `analyze` method should return a dictionary with four keys, `'x'`, `'y'`, `'min_max'`, and `'concavity'` and the values of `x`, `y`, `min_max`, and `concavity`, respectively.
```js
({ test: () => runPython(`
eq1 = QuadraticEquation(16, 2, 1)
eq2 = QuadraticEquation(-16, 2, 1)
assert eq1.analyze() == {'x': -0.0625, 'y': 0.9375, 'min_max': 'min', 'concavity': 'upwards'}
assert eq2.analyze() == {'x': 0.0625, 'y': 1.0625, 'min_max': 'max', 'concavity': 'downwards'}
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
--fcc-editable-region--
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
return {'x': x, 'y': y}
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(1, 2, 1)
print(quadr_eq)
print(quadr_eq.solve())
```

View File

@@ -0,0 +1,121 @@
---
id: 665467883dded0a1dad983b2
title: Step 46
challengeType: 20
dashedName: step-46
---
# --description--
Now, get rid of all your `print` calls.
# --hints--
You should delete all your `print` calls.
```js
({ test: () => assert(runPython(`
_Node(_code).find_calls("print") == []`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(1, 2, 1)
print(quadr_eq)
print(quadr_eq.solve())
--fcc-editable-region--
```

View File

@@ -0,0 +1,121 @@
---
id: 66558720bbe6e038315b7f81
title: Step 47
challengeType: 20
dashedName: step-47
---
# --description--
Next, you are going to create a function that will trigger the instance methods you wrote to solve the equation. Also, it will display the results in a formatted output.
Outside the classes, create a new function named `solver` that takes a single parameter, `equation`.
# --hints--
You should define a function named `solver` that takes a single parameter, `equation`.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").has_args("equation")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
--fcc-editable-region--
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
```

View File

@@ -0,0 +1,126 @@
---
id: 665621ef85db565d26632761
title: Step 48
challengeType: 20
dashedName: step-48
---
# --description--
Within your new function, create an `if` statement that checks if `equation` is not an instance of the `Equation` class and raise a `TypeError` using the string `'Argument must be an Equation object'` to provide a custom message.
# --hints--
You should create an `if` statement to check if `equation` is not an instance of the `Equation` class within your `solver` function.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_ifs()[0].find_conditions()[0].is_equivalent("not isinstance(equation, Equation)")`)) })
```
You should raise a `TypeError` with the provided string within your new `if` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_ifs()[0].find_bodies()[0].has_stmt("raise TypeError('Argument must be an Equation object')")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
--fcc-editable-region--
def solver(equation):
pass
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
```

View File

@@ -0,0 +1,152 @@
---
id: 66562f71937f877c66123bbe
title: Step 49
challengeType: 20
dashedName: step-49
---
# --description--
The first thing to display at the top of the output will be the equation type. Add a class attribute named `type` to the `Equation` class and annotate it with `str`.
Then, add another `if` statement to the `__init_subclass__` method to check if the classes inheriting from `Equation` have the `type` attribute. Use the same format of the existing `if` statement with the appropriate modifications.
Finally, add the new class attribute to the `LinearEquation` class and to the `QuadraticEquation` class. Assign it the string `'Linear Equation'` and the string `'Quadratic Equation'`, respectively.
# --hints--
You should define a class variable named `type` within the `Equation` class and annotate it with `str`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").has_stmt("type: str")`)) })
```
You should create an `if` statement that checks if `cls` does not have the attribute `type` inside the `__init_subclass__` method and raise an `AttributeError` using the provided string.
```js
({ test: () => assert(runPython(`
if_str = """
if not hasattr(cls, 'type'):
raise AttributeError(
f\\"Cannot create '{cls.__name__}' class: missing required attribute 'type'\\"
)
"""
_Node(_code).find_class("Equation").find_function("__init_subclass__").has_stmt(if_str)
`)) })
```
The `type` attribute of the `LinearEquation` class shouls have the value `'Linear Equation'`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").has_stmt("type = 'Linear Equation'")`)) })
```
The `type` attribute of the `QuadraticEquation` class should have the value `'Quadratic Equation'`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").has_stmt("type = 'Quadratic Equation'")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
--fcc-editable-region--
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
--fcc-editable-region--
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
```

View File

@@ -0,0 +1,89 @@
---
id: 665ee783d35cb68875c626d4
title: Step 28
challengeType: 20
dashedName: step-28
---
# --description--
Now, remove both the `print(lin_eq.solve())` and `print(lin_eq.analyze())` calls from your code.
# --hints--
You should remove both your `print(lin_eq.solve())` and `print(lin_eq.analyze())` calls.
```js
({ test: () => runPython(`
assert not _Node(_code).has_call("print(lin_eq.analyze())")
assert not _Node(_code).has_call("print(lin_eq.solve())")
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
lin_eq = LinearEquation(2, 3)
print(lin_eq)
--fcc-editable-region--
print(lin_eq.solve())
print(lin_eq.analyze())
--fcc-editable-region--
```

View File

@@ -0,0 +1,56 @@
---
id: 66759e32b88fb5459b1e0234
title: Step 10
challengeType: 20
dashedName: step-10
---
# --description--
The `__init_subclass__` method is called whenever the class that defines it is subclassed and it enables to customize the child classes. The method takes a parameter named by convention `cls` (standing for "class"), which represents the new child class.
Define an `__init_subclass__` method in your `Equation` class and give it a `cls` parameter.
# --hints--
You should define an `__init_subclass__` method with a `cls` parameter in your `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init_subclass__").has_args("cls")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self):
pass
--fcc-editable-region--
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation()
```

View File

@@ -0,0 +1,73 @@
---
id: 6675a38a8b535e4ff3274520
title: Step 11
challengeType: 20
dashedName: step-11
---
# --description--
The `hasatttr` built-in function takes an object as its first argument and a string representing an attribute name as its second argument. It returns a boolean indicating if the object has the specified attribute.
Now you are going to use the `__init_subclass__` method to check if the child class has the `degree` attribute at the moment of the instantiation.
Create an `if` statement to check if `cls` does not have a `degree` attribute. If so, raise an `AttributeError` and use the string `f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"` to provide a custom message.
After that, fix the error that has appeared in the terminal by declaring a `degree` class attribute inside the `LinearEquation` class. This attribute should represent the degree of the equation, which is the exponent of the highest \\( x \\) term. Therefore, assign the integer `1` to the `degree` atttribute.
# --hints--
You should create an `if` statement that checks if `cls` does not have the attribute `degree` inside the `__init_subclass__` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init_subclass__").find_ifs()[0].find_conditions()[0].is_equivalent("not hasattr(cls, 'degree')")`)) })
```
You should raise an `AttributeError` using the provided string inside your `if` statement.
```js
({ test: () => runPython(`
raise_stmt = 'raise AttributeError(f"Cannot create \\'{cls.__name__}\\' class: missing required attribute \\'degree\\'")'
node = _Node(_code).find_class("Equation").find_function("__init_subclass__").find_ifs()[0].find_bodies()[0]
assert node.has_stmt(raise_stmt)
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self):
pass
--fcc-editable-region--
def __init_subclass__(cls):
pass
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
--fcc-editable-region--
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation()
```

View File

@@ -0,0 +1,62 @@
---
id: 6675aaf418b41157f6ccd692
title: Step 12
challengeType: 20
dashedName: step-12
---
# --description--
It's time to go back to the `__init__` method. Depending on the equation type, you'll need to pass a variable number of arguments during the instantiation.
Add a second parameter `args` to the method and use the `*` operator to make it accept a variable number of arguments.
# --hints--
Your `__init__` method should take two parameters, `self`, and `*args`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").has_args("self, *args")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
--fcc-editable-region--
def __init__(self):
pass
--fcc-editable-region--
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation()
```

View File

@@ -0,0 +1,153 @@
---
id: 667938f754145d165c25725d
title: Step 50
challengeType: 20
dashedName: step-50
---
# --description--
An interesting feature of f-strings is the capability of forcing the output to be right/left-aligned, or centered. After the expression to be evaluated is inside the curly braces, you need to write a colon followed by an alignment option (`<` to left-align, `>` to right-align, `^` to center) and a number representing the width, that is the number of characters in which you want to arrange the text. For example:
```py
f'{"Hello World":>20}'
```
Printing the string from the example above would result in right-aligned text arranged in a space of 20 characters.
Back to the `solver` function, after your `if` statement, create a variable named `output_string` and assign it an f-string containing the equation type centered in a width of `24` characters. Make the string begin with a new line character, and return `output_string` from your function.
Then, call the `solver` function passing `lin_eq` as the argument, and print the result.
# --hints--
You should define a variable named `output_string` and assign it `f'\n{equation.type:^24}'`.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").has_stmt("output_string = f'\\\\n{equation.type:^24}'")`)) })
```
Your `solver` function should return `output_string`.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").has_return("output_string")`)) })
```
You should print `solver(lin_eq)`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(solver(lin_eq))")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
--fcc-editable-region--
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
--fcc-editable-region--
```

View File

@@ -0,0 +1,138 @@
---
id: 66793a552f357b17006a8726
title: Step 51
challengeType: 20
dashedName: step-51
---
# --description--
Between the colon and the alignment option, you can specify a fill character, which will be used to fill the space around the text within the specified width.
Add a `-` between the colon and the `^` in your f-string.
# --hints--
You should add a `-` character between the colon and the `^` in your f-string.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").has_stmt("output_string = f'\\\\n{equation.type:-^24}'")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
--fcc-editable-region--
output_string = f'\n{equation.type:^24}'
--fcc-editable-region--
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,150 @@
---
id: 66793c5b4bdacc17c40ff8e7
title: Step 52
challengeType: 20
dashedName: step-52
---
# --description--
Another feature of f-strings enables you to convert the content of the replacement field (the curly braces) into a string by using a `!` followed by the conversion type `s`. For example, `f'{obj!s}'` converts `obj` into a string and it is equivalent to `f'{str(obj)}'`.
From now on, you'll keep building the output by concatenating strings to `output_string`.
Create a string containing the string representation of your equation centered in a width of `24` characters. Make the string begin and end with two newline characters, and add your new string to the current value of `output_string`.
# --hints--
The `solver` function should return a different string.
```js
({ test: () => runPython(`
eq = LinearEquation(4, 3)
expected = """
----Linear Equation-----
4x +3 = 0
"""
assert solver(eq) == expected
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
--fcc-editable-region--
output_string = f'\n{equation.type:-^24}'
--fcc-editable-region--
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,149 @@
---
id: 66793d1e1581681871635ac6
title: Step 53
challengeType: 20
dashedName: step-53
---
# --description--
Add a new piece to your `output_string` formed by the string `'Solutions'` centered in a width of 24 characters. Use a `-` as a fill character, and make the string end with two new line characters.
# --hints--
The `solver` function should return a different string.
```js
({ test: () => runPython(`
eq = LinearEquation(4, 3)
expected = """
----Linear Equation-----
4x +3 = 0
-------Solutions--------
"""
assert solver(eq) == expected
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
--fcc-editable-region--
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
--fcc-editable-region--
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,139 @@
---
id: 66794346ddfa141cbe70093a
title: Step 54
challengeType: 20
dashedName: step-54
---
# --description--
Now, call the `solve()` method of `equation` and assign the result a variable named `results`.
# --hints--
You should declare a variable `results` and assign it the result of calling `equation.solve()`.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").has_stmt("results = equation.solve()")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
--fcc-editable-region--
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
--fcc-editable-region--
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,164 @@
---
id: 667944fed1f6b61da3406bd8
title: Step 55
challengeType: 20
dashedName: step-55
---
# --description--
Structural pattern matching is a Python construct that enables matching a pattern with a subject value, which is specified after the `match` keyword:
```py
match value:
case x:
<code>
case y:
<code>
```
Each pattern is specified after the `case` statement. If the match is positive, the code inside the `case` block is run.
Use the `match`/`case` syntax to check the length of `results`. In case the length is `0`, assign a list containing the string `'No real roots'` to a variable named `result_list`.
# --hints--
You should create a `match`/`case` construct using `len(results)` as the subject value.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_subject().is_equivalent("len(results)")`)) })
```
You should create a new `case` with the pattern `0`.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[0].find_case_pattern().is_equivalent("0")`)) })
```
You should assign a list containing `'No real roots'` to `result_list` inside the `case` body.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[0].find_case_body().is_equivalent("result_list = ['No real roots']")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
--fcc-editable-region--
results = equation.solve()
--fcc-editable-region--
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,165 @@
---
id: 66799278873fd2570217bffa
title: Step 56
challengeType: 20
dashedName: step-56
---
# --description--
Add another `case` for when the length of `results` is `1`. In this case, assign to `result_list` a list containing a string with the format `x = <root>`, where `<root>` is the solution of the equation. Format the string so that both positive and negative sign are displayed for the solution.
# --hints--
You should not modify the subject value of your `match` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_subject().is_equivalent("len(results)")`)) })
```
You should not modify your existing `case` block.
```js
({ test: () => runPython(`
case = _Node(_code).find_function("solver").find_matches()[0].find_match_cases()[0]
assert case.find_case_pattern().is_equivalent("0")
assert case.find_case_body().is_equivalent("result_list = ['No real roots']")
`) })
```
You should create a new `case` with the pattern `1` after the existing `case` block.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[1].find_case_pattern().is_equivalent("1")`)) })
```
You should assign a list containing `f'x = {results[0]:+}'` to `result_list` inside your new `case` body.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[1].find_case_body().is_equivalent("result_list = [f'x = {results[0]:+}']")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
results = equation.solve()
--fcc-editable-region--
match len(results):
case 0:
result_list = ['No real roots']
--fcc-editable-region--
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,170 @@
---
id: 6679934707d5fe577f898efd
title: Step 57
challengeType: 20
dashedName: step-57
---
# --description--
Add another case for when the length of `results` is `2`. This time, assign `result_list` a list containing two strings with the format `x1 = <root1>` and `x2 = <root2>`. Again, make the solution display both positive and negative signs.
# --hints--
You should not modify the subject value of your `match` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_subject().is_equivalent("len(results)")`)) })
```
You should not modify your existing `case` blocks.
```js
({ test: () => runPython(`
case0 = _Node(_code).find_function("solver").find_matches()[0].find_match_cases()[0]
assert case0.find_case_pattern().is_equivalent("0")
assert case0.find_case_body().is_equivalent("result_list = ['No real roots']")
case1 = _Node(_code).find_function("solver").find_matches()[0].find_match_cases()[1]
assert case1.find_case_pattern().is_equivalent("1")
assert case1.find_case_body().is_equivalent("result_list = [f'x = {results[0]:+}']")
`) })
```
You should create a new `case` with the pattern `2` after the existing `case` block.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[2].find_case_pattern().is_equivalent("2")`)) })
```
You should assign a list containing two strings with the format `x1 = <root1>` and `x2 = <root2>` to `result_list` inside your new `case` body. Display both positive and negative signs for the results.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[2].find_case_body().is_equivalent("result_list = [f'x1 = {results[0]:+}', f'x2 = {results[1]:+}']")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
results = equation.solve()
--fcc-editable-region--
match len(results):
case 0:
result_list = ['No real roots']
case 1:
result_list = [f'x = {results[0]:+}']
--fcc-editable-region--
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,159 @@
---
id: 66799ba07c5fd58a61a604d3
title: Step 58
challengeType: 20
dashedName: step-58
---
# --description--
After your `match`/`case` block, iterate through `result_list` and concatenate each element to `output_string`. Keep aligning the text to the center and make each result string end with a new line character.
# --hints--
The `solver` function should return a different string.
```js
({ test: () => runPython(`
eq = LinearEquation(4, 3)
expected = """
----Linear Equation-----
4x +3 = 0
-------Solutions--------
x = -0.75
"""
assert solver(eq) == expected
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
results = equation.solve()
--fcc-editable-region--
match len(results):
case 0:
result_list = ['No real roots']
case 1:
result_list = [f'x = {results[0]:+}']
case 2:
result_list = [f'x1 = {results[0]:+}', f'x2 = {results[1]:+}']
--fcc-editable-region--
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,157 @@
---
id: 66799c1a0204668cef35555d
title: Step 59
challengeType: 20
dashedName: step-59
---
# --description--
f-strings also enable you to set a specific precision to your numerical data by using the `.nf` format specifier, where `n` is the number of decimal digits to display.
Within the curly braces of the f-strings contained inside `result_list`, write the format specifier needed to display `3` decimal digits just after the `:+`.
# --hints--
You should modify the string contained in `result_list` in your `case 1` block into `f'x = {results[0]:+.3f}'`.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[1].find_case_body().is_equivalent("result_list = [f'x = {results[0]:+.3f}']")`)) })
```
You should modify the strings contained in `result_list` in your `case 2` block so that the results are displayed with `3` decimal digits.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[2].find_case_body().is_equivalent("result_list = [f'x1 = {results[0]:+.3f}', f'x2 = {results[1]:+.3f}']")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
results = equation.solve()
--fcc-editable-region--
match len(results):
case 0:
result_list = ['No real roots']
case 1:
result_list = [f'x = {results[0]:+}']
case 2:
result_list = [f'x1 = {results[0]:+}', f'x2 = {results[1]:+}']
for result in result_list:
output_string += f'{result:^24}\n'
--fcc-editable-region--
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,164 @@
---
id: 6679bf00da92e5c0db0ffdc3
title: Step 61
challengeType: 20
dashedName: step-61
---
# --description--
Right after your `for` loop, add another piece to your output. Create a string having the text `Details` centered. Use a `-` as a fill character and make your string begin with a single newline character and end with two newline characters.
# --hints--
The `solver` function should return a different string.
```js
({ test: () => runPython(`
eq = LinearEquation(4, 3)
expected = """
----Linear Equation-----
4x +3 = 0
-------Solutions--------
x = -0.750
--------Details---------
"""
assert solver(eq) == expected
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
results = equation.solve()
match results:
case []:
result_list = ['No real roots']
case [x]:
result_list = [f'x = {x:+.3f}']
case [x1, x2]:
result_list = [f'x1 = {x1:+.3f}', f'x2 = {x2:+.3f}']
--fcc-editable-region--
for result in result_list:
output_string += f'{result:^24}\n'
--fcc-editable-region--
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,150 @@
---
id: 6679bfe40a6d77c6a3c17e06
title: Step 62
challengeType: 20
dashedName: step-62
---
# --description--
Now, call the `analyze` method of `equation` and assign the result to a new variable named `details`.
# --hints--
You should declare a variable `details` and assign it the result of calling `equation.analyze()`.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").has_stmt("details = equation.analyze()")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
results = equation.solve()
match results:
case []:
result_list = ['No real roots']
case [x]:
result_list = [f'x = {x:+.3f}']
case [x1, x2]:
result_list = [f'x1 = {x1:+.3f}', f'x2 = {x2:+.3f}']
for result in result_list:
output_string += f'{result:^24}\n'
--fcc-editable-region--
output_string += f'\n{"Details":-^24}\n\n'
--fcc-editable-region--
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,197 @@
---
id: 667a7ce2a9925416e7b4781b
title: Step 60
challengeType: 20
dashedName: step-60
---
# --description--
The structural pattern matching enables you to verify that the subject has a specific structure. In addition to that, it binds names in the pattern to elements of the subject. For example:
```py
match my_list:
case [a]:
print(a)
case [a, b]:
print(a, b)
```
Modify your `match`/`case` construct to match `results` instead of `len(results)`. Then, modify each `case` to use a list with the appropriate number of elements. Use `x` for the case the list contains a single element, and `x1` and `x2` for the case the list contains two elements.
Finally, modify the f-strings to use the variable names used in each `case`.
# --hints--
You should modify your `match` statement to use `results` as the subject value.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_subject().is_equivalent("results")`)) })
```
You should modify your first `case` to use the pattern `[]`.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[0].find_case_pattern().is_equivalent("[]")`)) })
```
You should not modify your first `case` body.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[0].find_case_body().is_equivalent("result_list = ['No real roots']")`)) })
```
You should modify your second `case` to use the pattern `[x]`.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[1].find_case_pattern().is_equivalent("[x]")`)) })
```
You should modify the f-string contained inside `result_list` to use `x` in place of `result[0]`.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[1].find_case_body().is_equivalent("result_list = [f'x = {x:+.3f}']")`)) })
```
You should modify your third `case` to use a list containing `x1` and `x2` as the pattern.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[2].find_case_pattern().is_equivalent("[x1, x2]")`)) })
```
You should modify the f-strings contained inside `result_list` to use the bound variables from your pattern.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[0].find_match_cases()[2].find_case_body().is_equivalent("result_list = [f'x1 = {x1:+.3f}', f'x2 = {x2:+.3f}']")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
results = equation.solve()
--fcc-editable-region--
match len(results):
case 0:
result_list = ['No real roots']
case 1:
result_list = [f'x = {results[0]:+.3f}']
case 2:
result_list = [f'x1 = {results[0]:+.3f}', f'x2 = {results[1]:+.3f}']
--fcc-editable-region--
for result in result_list:
output_string += f'{result:^24}\n'
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,168 @@
---
id: 667a860c3b61f61b7a18930c
title: Step 63
challengeType: 20
dashedName: step-63
---
# --description--
Create another `match`/`case` construct to match the value of the `details` variable.
When the equation is linear, `details` is a dictionary having the form `{'slope': slope, 'intercept': intercept}`. Use it as the pattern for your first `case`.
Then, inside the `case` block, declare a variable named `details_list` and assign it a list containing two strings having the form `slope = <slope>` and `y-intercept = <intercept>`, respectively. Format the strings to display `3` decimal digits.
# --hints--
You should create a new `match` statement that uses `details` as the subject value.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[1].find_match_subject().is_equivalent("details")`)) })
```
You should create a new `case` with the pattern `{'slope': slope, 'intercept': intercept}`.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[1].find_match_cases()[0].find_case_pattern().is_equivalent("{'slope': slope, 'intercept': intercept}")`)) })
```
You should assign a list containing two f-strings having the form `slope = <slope>` and `y-intercept = <intercept>` to `details_list` inside the `case` body. Remember to format the numerical values to display `3` decimal digits.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[1].find_match_cases()[0].find_case_body().is_equivalent("details_list = [f'slope = {slope:.3f}', f'y-intercept = {intercept:.3f}']")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
results = equation.solve()
match results:
case []:
result_list = ['No real roots']
case [x]:
result_list = [f'x = {x:+.3f}']
case [x1, x2]:
result_list = [f'x1 = {x1:+.3f}', f'x2 = {x2:+.3f}']
for result in result_list:
output_string += f'{result:^24}\n'
output_string += f'\n{"Details":-^24}\n\n'
--fcc-editable-region--
details = equation.analyze()
--fcc-editable-region--
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,225 @@
---
id: 667a8d7a735cf221729570ff
title: Step 64
challengeType: 20
dashedName: step-64
---
# --description--
Add another `case` for when the equation is quadratic. Use a dictionary with the same format returned by the `analyze` method of `QuadraticEquation`.
Then, assign `details_list` a list containing two strings with the format `concavity = <concavity>` and `<min_max> = (<x>, <y>)`, respectively. Format `<x>` and `<y>` to display `3` decimal digits.
Finally, after the `match`/`case` block, iterate through `details_list` and add each item to the current value of `output_string`. Make sure that each string item ends with a newline character. Do not use any additional format option here.
# --hints--
You should not modify the subject value of your `match` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_matches()[1].find_match_subject().is_equivalent("details")`)) })
```
You should not modify your existing `case` block.
```js
({ test: () => runPython(`
case = _Node(_code).find_function("solver").find_matches()[1].find_match_cases()[0]
assert case.find_case_pattern().is_equivalent("{'slope': slope, 'intercept': intercept}")
assert case.find_case_body().is_equivalent("details_list = [f'slope = {slope:.3f}', f'y-intercept = {intercept:.3f}']")
`) })
```
You should create a new `case` block for when `equation` is a quadratic equation.
```js
({ test: () => assert(runPython(`len(_Node(_code).find_function("solver").find_matches()[1].find_match_cases()) == 2`)) })
```
You should create a `for` loop to iterate over `details_list`.
```js
({ test: () => assert(runPython(`_Node(_code).find_function("solver").find_for_loops()[1].find_for_iter().is_equivalent("details_list")`)) })
```
Your `solver` function should return a different string.
```js
({ test: () => runPython(`
expected1 = """
----Linear Equation-----
4x +3 = 0
-------Solutions--------
x = -0.750
--------Details---------
slope = 4.000
y-intercept = 3.000
"""
eq1 = LinearEquation(4, 3)
actual1 = solver(eq1)
assert expected1 == actual1
expected2 = """
---Quadratic Equation---
x**2 -3x +1 = 0
-------Solutions--------
x1 = +2.618
x2 = +0.382
--------Details---------
concavity = upwards
min = (1.500, -1.250)
"""
eq2 = QuadraticEquation(1, -3, 1)
actual2 = solver(eq2)
assert expected2 == actual2
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
results = equation.solve()
match results:
case []:
result_list = ['No real roots']
case [x]:
result_list = [f'x = {x:+.3f}']
case [x1, x2]:
result_list = [f'x1 = {x1:+.3f}', f'x2 = {x2:+.3f}']
for result in result_list:
output_string += f'{result:^24}\n'
output_string += f'\n{"Details":-^24}\n\n'
--fcc-editable-region--
details = equation.analyze()
match details:
case {'slope': slope, 'intercept': intercept}:
details_list = [f'slope = {slope:.3f}', f'y-intercept = {intercept:.3f}']
--fcc-editable-region--
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,196 @@
---
id: 667a965d5a4b5825ffb2e1d8
title: Step 65
challengeType: 20
dashedName: step-65
---
# --description--
Modify the strings contained inside `details_list` to right-align the numerical values of the slope and the intercept. The final output should look like this:
```py
----Linear Equation-----
2x +3 = 0
-------Solutions--------
x = -1.500
--------Details---------
slope = 2.000
y-intercept = 3.000
```
Note that the align option and the width should be placed between the colon and the precision format specifier.
# --hints--
The `solver` function should return a different string.
```js
({ test: () => runPython(`
eq = LinearEquation(44, 3)
expected = """
----Linear Equation-----
44x +3 = 0
-------Solutions--------
x = -0.068
--------Details---------
slope = 44.000
y-intercept = 3.000
"""
assert solver(eq) == expected, f'{solver(eq)}'
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
results = equation.solve()
match results:
case []:
result_list = ['No real roots']
case [x]:
result_list = [f'x = {x:+.3f}']
case [x1, x2]:
result_list = [f'x1 = {x1:+.3f}', f'x2 = {x2:+.3f}']
for result in result_list:
output_string += f'{result:^24}\n'
output_string += f'\n{"Details":-^24}\n\n'
details = equation.analyze()
match details:
case {'slope': slope, 'intercept': intercept}:
--fcc-editable-region--
details_list = [f'slope = {slope:.3f}', f'y-intercept = {intercept:.3f}']
--fcc-editable-region--
case {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}:
coord = f'({x:.3f}, {y:.3f})'
details_list = [f'concavity = {concavity}', f'{min_max} = {coord}']
for detail in details_list:
output_string += f'{detail}\n'
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
```

View File

@@ -0,0 +1,173 @@
---
id: 667a9c91a87bb453a355b63d
title: Step 66
challengeType: 20
dashedName: step-66
---
# --description--
Feel free to change the coefficients of your `lin_eq` to see how the output changes.
Then, delete your `print(solver(lin_eq))` call, and print the result of calling `solver()` with `quadr_eq` as the argument.
# --hints--
You should not have `print(solver(lin_eq))` in your code.
```js
({ test: () => assert.isFalse(runPython(`_Node(_code).has_call("print(solver(lin_eq))")`)) })
```
You should print `solver(quadr_eq)`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(solver(quadr_eq))")`)) })
```
# --hints--
Test 1
```js
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
results = equation.solve()
match results:
case []:
result_list = ['No real roots']
case [x]:
result_list = [f'x = {x:+.3f}']
case [x1, x2]:
result_list = [f'x1 = {x1:+.3f}', f'x2 = {x2:+.3f}']
for result in result_list:
output_string += f'{result:^24}\n'
output_string += f'\n{"Details":-^24}\n\n'
details = equation.analyze()
match details:
case {'slope': slope, 'intercept': intercept}:
details_list = [f'slope = {slope:>16.3f}', f'y-intercept = {intercept:>10.3f}']
case {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}:
coord = f'({x:.3f}, {y:.3f})'
details_list = [f'concavity = {concavity}', f'{min_max} = {coord}']
for detail in details_list:
output_string += f'{detail}\n'
return output_string
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(lin_eq))
--fcc-editable-region--
```

View File

@@ -0,0 +1,331 @@
---
id: 667aa056f1240f58fb9a2c17
title: Step 67
challengeType: 20
dashedName: step-67
---
# --description--
As a last step, modify the strings contained in `details_list` so that the text placed after the equal sign is right-aligned for each line. Your final output should look like this:
```py
---Quadratic Equation---
x**2 +2x +1 = 0
-------Solutions--------
x = -1.000
--------Details---------
concavity = upwards
min = (-1.000, 0.000)
```
With that, the project is complete!
# --hints--
The `solver` function should return a different string.
```js
({ test: () => runPython(`
eq = QuadraticEquation(-4, 3, 2)
expected = """
---Quadratic Equation---
-4x**2 +3x +2 = 0
-------Solutions--------
x1 = -0.425
x2 = +1.175
--------Details---------
concavity = downwards
max = (0.375, 2.562)
"""
assert solver(eq) == expected
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
results = equation.solve()
match results:
case []:
result_list = ['No real roots']
case [x]:
result_list = [f'x = {x:+.3f}']
case [x1, x2]:
result_list = [f'x1 = {x1:+.3f}', f'x2 = {x2:+.3f}']
for result in result_list:
output_string += f'{result:^24}\n'
output_string += f'\n{"Details":-^24}\n\n'
details = equation.analyze()
match details:
case {'slope': slope, 'intercept': intercept}:
details_list = [f'slope = {slope:>16.3f}', f'y-intercept = {intercept:>10.3f}']
case {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}:
coord = f'({x:.3f}, {y:.3f})'
--fcc-editable-region--
details_list = [f'concavity = {concavity}', f'{min_max} = {coord}']
--fcc-editable-region--
for detail in details_list:
output_string += f'{detail}\n'
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(quadr_eq))
```
# --solutions--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
type: str
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
if not hasattr(cls, "type"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'type'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return re.sub(r"(?<!\d)1(?=x)", "", equation_string.strip("+"))
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
type = 'Linear Equation'
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return [x]
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
type = 'Quadratic Equation'
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
if self.delta < 0:
return []
a, b, _ = self.coefficients.values()
x1 = (-b + (self.delta) ** 0.5) / (2 * a)
x2 = (-b - (self.delta) ** 0.5) / (2 * a)
if self.delta == 0:
return [x1]
return [x1, x2]
def analyze(self):
a, b, c = self.coefficients.values()
x = -b / (2 * a)
y = a * x**2 + b * x + c
if a > 0:
concavity = 'upwards'
min_max = 'min'
else:
concavity = 'downwards'
min_max = 'max'
return {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}
def solver(equation):
if not isinstance(equation, Equation):
raise TypeError("Argument must be an Equation object")
output_string = f'\n{equation.type:-^24}'
output_string += f'\n\n{equation!s:^24}\n\n'
output_string += f'{"Solutions":-^24}\n\n'
results = equation.solve()
match results:
case []:
result_list = ['No real roots']
case [x]:
result_list = [f'x = {x:+.3f}']
case [x1, x2]:
result_list = [f'x1 = {x1:+.3f}', f'x2 = {x2:+.3f}']
for result in result_list:
output_string += f'{result:^24}\n'
output_string += f'\n{"Details":-^24}\n\n'
details = equation.analyze()
match details:
case {'slope': slope, 'intercept': intercept}:
details_list = [f'slope = {slope:>16.3f}', f'y-intercept = {intercept>10:.3f}']
case {'x': x, 'y': y, 'min_max': min_max, 'concavity': concavity}:
coord = f'({x:.3f}, {y:.3f})'
details_list = [f'concavity = {concavity:>12}', f'{min_max} = {coord:>18}']
for detail in details_list:
output_string += f'{detail}\n'
return output_string
lin_eq = LinearEquation(2, 3)
quadr_eq = QuadraticEquation(1, 2, 1)
print(solver(quadr_eq))
```

View File

@@ -0,0 +1,116 @@
---
id: 667e623208053643ca9d3c6e
title: Step 15
challengeType: 20
dashedName: step-15
---
# --description--
Now, replace the `for` loop and `if` statement you added in the previous step with an `if` statement that uses the `any()` built-in function.
# --hints--
The condition of your new `if` statement should be a call to `any()`.
```js
({ test: () => runPython(`
cond = _Node(_code).find_class("Equation").find_function("__init__").find_ifs()[1].find_conditions()[0]
calls = _Node(str(cond)).find_calls("any")
assert len(calls) == 1
`) })
```
You should pass a generator expression as the argument to your `any()` call.
```js
({ test: () => runPython(`
import ast
argument = _Node(_code).find_class("Equation").find_function("__init__").find_ifs()[1].find_conditions()[0].find_call_args()[0]
assert isinstance(argument.tree, ast.GeneratorExp)
`) })
```
The generator expression passed to `any()` should iterate over `args`.
```js
({ test: () => runPython(`
import ast
argument = _Node(_code).find_class("Equation").find_function("__init__").find_ifs()[1].find_conditions()[0].find_call_args()[0]
iters = argument.find_comp_iters()
assert len(iters) == 1
assert iters[0].is_equivalent("args")
`) })
```
Your `if` statement should check if any of the arguments in `args` is not an instance of either `int` or `float`.
```js
({ test: () => runPython(`
import ast
argument = _Node(_code).find_class("Equation").find_function("__init__").find_ifs()[1].find_conditions()[0].find_call_args()[0]
target = argument.find_comp_targets()[0]
expr = argument.find_comp_expr()
solutions = [
f"not isinstance({target}, (int, float))",
f"not isinstance({target}, (float, int))",
f"not isinstance({target}, float) and not isinstance({target}, int)",
f"not isinstance({target}, int) and not isinstance({target}, float)",
]
assert any(expr.is_equivalent(sol) for sol in solutions)
`) })
```
You should use the provided string to raise a `TypeError` within your new `if` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").find_ifs()[1].find_bodies()[0].has_stmt("raise TypeError(\\"Coefficients must be of type 'int' or 'float'\\")")
`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'{self.__class__.__name__}' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
--fcc-editable-region--
for arg in args:
if not isinstance(arg, (int, float)):
raise TypeError("Coefficients must be of type 'int' or 'float'")
--fcc-editable-region--
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
```

View File

@@ -7,17 +7,17 @@ dashedName: step-74
# --description--
The dot product between two 3D vectors \\( \mathbf{a} \\) and \\( \mathbf{b} \\) can be computed as it follows:
The cross 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.
Implement the formula above to compute the cross 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.
The `cross()` method should return a new `R3Vector` instance resulting from the cross product computation.
```js
({ test: () => assert(runPython(`

View File

@@ -7,7 +7,7 @@ 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.
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 cross product.
With that, you have completed the vector space project. Well done!

View File

@@ -7,7 +7,7 @@ dashedName: step-1
# --description--
In this project, you will build a set of football team cards and learn about nested objects, object destructuring, default parameters, event listeners, and switch statements. All of the HTML and CSS for this project has been provided for you.
In this project, you will build a set of football team cards and learn about nested objects, object destructuring, and default parameters. All of the HTML and CSS for this project has been provided for you.
Start by accessing the `id` called `"team"` from the HTML document and storing it in a `const` variable called `teamName`.

View File

@@ -0,0 +1,30 @@
---
id: 662a6bc12cde72c32fb526f0
title: Step 1
challengeType: 20
dashedName: step-1
---
# --description--
An <dfn>interface</dfn> is like a blueprint for a class. An interface contains a set of methods and properties that a class should implement.
Start this project by declaring an empty class named `Equation`. You will use this class to define an interface, a blueprint for a generic equation.
# --hints--
You should define a new class named `Equation`.
```js
({ test: () => assert(runPython(`_Node(_code).has_class("Equation")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
--fcc-editable-region--
```

View File

@@ -0,0 +1,47 @@
---
id: 662bd456896f16d9bd03f1a6
title: Step 2
challengeType: 20
dashedName: step-2
---
# --description--
Within the `Equation` class, define two new instance methods named `solve` and `analyze`.
# --hints--
You should define a method named `solve` within the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").has_function("solve")`)) })
```
Your `solve` method should take one parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("solve").has_args("self")`)) })
```
You should define a method named `analyze` within the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").has_function("analyze")`)) })
```
Your `analyze` method should take one parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("analyze").has_args("self")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
class Equation:
pass
--fcc-editable-region--
```

View File

@@ -0,0 +1,40 @@
---
id: 662bd552e1c1d2db1b88ba47
title: Step 3
challengeType: 20
dashedName: step-3
---
# --description--
Now, define another class named `LinearEquation` and make it inherit from `Equation`. You'll use this class to represent linear equations.
# --hints--
You should define a class named `LinearEquation`.
```js
({ test: () => assert(runPython(`_Node(_code).has_class("LinearEquation")`)) })
```
Your `LinearEquation` class should inherit from the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").inherits_from("Equation")`)) })
```
# --seed--
## --seed-contents--
```py
class Equation:
def solve(self):
pass
def analyze(self):
pass
--fcc-editable-region--
--fcc-editable-region--
```

View File

@@ -0,0 +1,48 @@
---
id: 662bd8260da84bdd5feae419
title: Step 4
challengeType: 20
dashedName: step-4
---
# --description--
You want the `LinearEquation` class to implement and not simply inherit all the methods defined inside the `Equation` class, which should act as an interface.
Currently, the `Equation` class is simply the parent class of `LinearEquation`. In the next steps you will learn how to turn it into a formal interface.
For now, create an instance of `Equation` and assign it to a variable `eq`, and an instance of `LinearEquation` and assign it to a variable `lin_eq`.
# --hints--
You should declare a variable `eq` and assign it an instance of `Equation`.
```js
({ test: () => assert(runPython(`_Node(_code).has_stmt("eq = Equation()")`)) })
```
You should declare a variable `lin_eq` and assign it an instance of `LinearEquation`.
```js
({ test: () => assert(runPython(`_Node(_code).has_stmt("lin_eq = LinearEquation()")`)) })
```
# --seed--
## --seed-contents--
```py
class Equation:
def solve(self):
pass
def analyze(self):
pass
class LinearEquation(Equation):
pass
--fcc-editable-region--
--fcc-editable-region--
```

View File

@@ -0,0 +1,44 @@
---
id: 662bdd364bf2cde1487922a9
title: Step 5
challengeType: 20
dashedName: step-5
---
# --description--
Unlike other programming languages, Python does not implement interfaces in its core language, but the Python standard library allows you to define interfaces in a simple way.
For this project, you'll use utilities from the `abc` module. Therefore, import this module in your code.
# --hints--
You should import the `abc` module.
```js
({ test: () => assert(runPython(`_Node(_code).has_import("import abc")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
--fcc-editable-region--
class Equation:
def solve(self):
pass
def analyze(self):
pass
class LinearEquation(Equation):
pass
eq = Equation()
lin_eq = LinearEquation()
```

View File

@@ -0,0 +1,52 @@
---
id: 662bde88dc84f1e249801b1a
title: Step 6
challengeType: 20
dashedName: step-6
---
# --description--
`ABC` stands for *Abstract Base Classes*. The `ABC` class enables you to turn a regular class into an abstract class, which is a class that acts as a blueprint for concrete classes.
Modify your `import` statement to import just the `ABC` class from the `abc` module. You can import a specific object `x` from a module `y` following the import construct `from y import x`.
Then, turn your `Equation` class into an abstract class by making it inherit from `ABC`.
# --hints--
You should import `ABC` from the `abc` module.
```js
({ test: () => assert(runPython(`_Node(_code).has_import("from abc import ABC")`)) })
```
Your `Equation` class should inherit from `ABC`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").inherits_from("ABC")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
import abc
class Equation:
def solve(self):
pass
def analyze(self):
pass
class LinearEquation(Equation):
pass
eq = Equation()
lin_eq = LinearEquation()
--fcc-editable-region--
```

View File

@@ -0,0 +1,57 @@
---
id: 662f6d7c92381a3049e4c987
title: Step 8
challengeType: 20
dashedName: step-8
---
# --description--
An interface doesn't have to define only abstract methods, but it can also implement methods to be inherited by the concrete classes.
Before taking care of the actual implementation of `solve` and `analyze`, within the `Equation` class, define an `__init__` method. Do not use any decorator on it.
# --hints--
You should define an `__init__` method in your `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").has_function("__init__")`)) })
```
Your `__init__` method should take one parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").has_args("self")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
from abc import ABC, abstractmethod
class Equation(ABC):
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation()
--fcc-editable-region--
```

View File

@@ -0,0 +1,88 @@
---
id: 662f96576ef178927de87975
title: Step 7
challengeType: 20
dashedName: step-7
---
# --description--
In order to be recognized as an abstract method, a method should be decorated with the `@abstractmethod` decorator.
Modify your import statement to import the `abstractmethod` decorator and decorate both the `solve` and `analyze` methods of the `Equation` class. This will raise two exceptions.
Once a class inheriting from `ABC` has an abstract method, the class cannot be instantiated anymore. Therefore, delete the `Equation` instance to get rid of the error.
The other error occurs because the `LinearEquation` class must implement all the abstract methods defined in the interface. Make sure to define them inside the `LinearEquation` class, too. You must not use the `abstractmethod` decorator in the concrete class.
# --hints--
You should import `abstractmethod` from the `abc` module.
```js
({ test: () => assert(runPython(`
_Node(_code).has_import("from abc import ABC, abstractmethod") or \\
_Node(_code).has_import("from abc import abstractmethod, ABC") or \\
(_Node(_code).has_import("from abc import abstractmethod") and _Node(_code).has_import("from abc import ABC"))
`)) })
```
You should decorate with `@abstractmethod` the `solve` method within the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("solve").has_decorators("abstractmethod")`)) })
```
You should decorate with `@abstractmethod` the `analyze` method within the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("analyze").has_decorators("abstractmethod")`)) })
```
You should define a method named `solve` within the `LinearEquation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").has_function("solve")`)) })
```
Your `solve` method should take one parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").find_function("solve").has_args("self")`)) })
```
You should define a method named `analyze` within the `LinearEquation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").has_function("analyze")`)) })
```
Your `solve` method should take one parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").find_function("analyze").has_args("self")`)) })
```
# --seed--
## --seed-contents--
```py
--fcc-editable-region--
from abc import ABC
class Equation(ABC):
def solve(self):
pass
def analyze(self):
pass
class LinearEquation(Equation):
pass
eq = Equation()
lin_eq = LinearEquation()
--fcc-editable-region--
```

View File

@@ -0,0 +1,52 @@
---
id: 662fa2e2cf27c09f21f4f5d0
title: Step 9
challengeType: 20
dashedName: step-9
---
# --description--
In Python, data types are recognized during runtime (when the code is executed). Therefore, you don't have to specify the data type of a variable when you declare it. Nonetheless, you can annotate a variable to clarify that it will hold a specific data type with `variable: <data type> = value` or just `variable: <data type>`. Note that the Python interpreter does not enforce the types used to annotate variables, and normally you'd need external tools to do it.
Inside the `Equation` class, define a class attribute `degree`. Do not assign it a value. Instead use a type annotation of `int` to show that it will store an integer number inside the concrete classes.
Later on, you'll use this class attribute as a part of the validation process of the arguments passed to instantiate the equation objects.
# --hints--
You should define class attribute named `degree` and annotate it with `int` within the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_variable("degree").is_equivalent("degree: int")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
--fcc-editable-region--
class Equation(ABC):
def __init__(self):
pass
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
def solve(self):
pass
def analyze(self):
pass
--fcc-editable-region--
lin_eq = LinearEquation()
```

View File

@@ -0,0 +1,83 @@
---
id: 662fbcef5f05e1b84f541a0c
title: Step 13
challengeType: 20
dashedName: step-13
---
# --description--
Each equation object will be instantiated passing as many arguments as the coefficients of the equation, starting from n-th degree of \\( x \\) down to the zero-th degree, including the possible coefficient with the value of `0`.
For example, `LinearEquation(4, 5)` would represent the equation \\( 4x + 5 = 0 \\), with `4` being the coefficient of the first (highest here) degree and `5` the coefficient of the zero-th degree.
You need to check that the right number of arguments is passed to instantiate the equation object.
Inside the `__init__` method, create an `if` statement to check if the length of `args` is different from the number of coefficients the equation should have (`degree + 1`). If it is, raise a `TypeError` and use the following string to provide a custom message: `f"'{self.__class__.__name__}' object takes {self.degree + 1} positional arguments but {len(args)} were given"`.
Then, fix the error by passing the `2` and `3` to instantiate `lin_eq`.
# --hints--
You should create an `if` statement that checks if the number of coefficients used to instantiate the equation is different from `degree + 1`.
```js
({ test: () => assert(runPython(`
cond = _Node(_code).find_class("Equation").find_function("__init__").find_ifs()[0].find_conditions()[0]
cond.is_equivalent("(self.degree + 1) != len(args)") or cond.is_equivalent("len(args) != (self.degree + 1)")
`)) })
```
You should raise a `TypeError` within the new `if` statement and use the provided string to return a custom error message.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").find_ifs()[0].find_bodies()[0].has_stmt('raise TypeError(f"\\'{self.__class__.__name__}\\' object takes {self.degree + 1} positional arguments but {len(args)} were given")')
`)) })
```
You should pass `2` and `3` to instantiate `lin_eq`.
```js
({ test: () => assert(runPython(`_Node(_code).has_stmt("lin_eq = LinearEquation(2, 3)")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
--fcc-editable-region--
def __init__(self, *args):
pass
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation()
--fcc-editable-region--
```

View File

@@ -0,0 +1,87 @@
---
id: 662fc3eba556a6bf800d48c1
title: Step 14
challengeType: 20
dashedName: step-14
---
# --description--
The `isinstance()` built-in function takes two arguments and returns a Boolean indicating if the object passed as the first argument is an instance of the class passed as the second argument.
```py
isinstance(7, int) # True
```
Another thing you want to check is that every argument is a number. After your first `if`, create a `for` loop that iterates over `args` and checks if the argument at the current iteration is not an instance of `int` or `float`. Use the `isinstance()` function and pass it a tuple containing `int` and `float` as the second argument.
If the argument is not a number, raise a `TypeError` saying `"Coefficients must be of type 'int' or 'float'"`.
# --hints--
You should create a `for` loop that iterates over `args` after your `if` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").find_for_loops()[0].find_for_iter().is_equivalent("args")`)) })
```
You should create an `if` statement that checks if the current coefficient is not an instance of either `int` or `float` within the `for` loop.
```js
({ test: () => assert(runPython(`
var = str(_Node(_code).find_class("Equation").find_function("__init__").find_for_loops()[0].find_for_vars())
cond1 = f'not isinstance({var}, (int, float))'
cond2 = f'not isinstance({var}, (float, int))'
if_stmt = _Node(_code).find_class("Equation").find_function("__init__").find_for_loops()[0].find_ifs()[0].find_conditions()[0]
if_stmt.is_equivalent(cond1) or if_stmt.is_equivalent(cond2)
`)) })
```
You should use the provided string to raise a `TypeError` within the `if` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").find_for_loops()[0].find_ifs()[0].find_bodies()[0].has_stmt("raise TypeError(\\"Coefficients must be of type 'int' or 'float'\\")")
`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
--fcc-editable-region--
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'{self.__class__.__name__}' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
--fcc-editable-region--
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
```

View File

@@ -0,0 +1,74 @@
---
id: 6639f947d3a1818c9322c64a
title: Step 16
challengeType: 20
dashedName: step-16
---
# --description--
The last step of validating the coefficients is checking that the highest degree coefficient is different from zero. Remember that the highest degree coefficient should be passed as the first argument when instantiating the object.
Add an `if` statement for that and raise a `ValueError` using the following string to provide a custom message: `'Highest degree coefficient must be different from zero'`.
# --hints--
You should create an `if` statement that checks if the first coefficient passed to instantiate the equation is equal to zero.
```js
({ test: () => assert(runPython(`
cond = _Node(_code).find_class("Equation").find_function("__init__").find_ifs()[2].find_conditions()[0]
cond.is_equivalent("args[0] == 0") or cond.is_equivalent("0 == args[0]") or cond.is_equivalent("not args[0]")
`)) })
```
You should raise a `ValueError` within the new `if` statement and use the provided string to return a custom error message.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").find_ifs()[2].find_bodies()[0].has_stmt("raise ValueError('Highest degree coefficient must be different from zero')")
`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
--fcc-editable-region--
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
--fcc-editable-region--
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
```

View File

@@ -0,0 +1,94 @@
---
id: 6639fdcc701833a54c364211
title: Step 17
challengeType: 20
dashedName: step-17
---
# --description--
After validating the coefficients, you need to store them in an instance attribute. Use a dictionary comprehension to create a dictionary in which the key is the degree of the coefficient and the corresponding value is the coefficient, and assign it to an attribute named `coefficients`.
For example, a `LinearEquation` object instantiated with `2` and `4` should have the following `coefficients` attribute: `{1: 2, 0: 4}`, because `2` corresponds to the first degree of `x` and `4` corresponds to zero-th degree of `x`.
Create the key-value pairs in your new dictionary following the same order as in `args`.
# --hints--
You should declare an attribute named `coefficients` within your `__init__` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__init__").has_variable("self.coefficients")`)) })
```
You should use a dictionary comprehension to store your coefficients.
```js
({ test: () => runPython(`
import ast
node = _Node(_code).find_class("Equation").find_function("__init__").find_variable("self.coefficients")
assert isinstance(node.tree.value, ast.DictComp)
`) })
```
Your `coefficients` attribute should be a dictionary containing key-value pairs in the form degree-coefficient. Remember to follow the same order in which coefficients are stored inside `args`.
```js
({ test: () => runPython(`
actual1 = list(LinearEquation(1, 6).coefficients.items())
expected1 = list({1: 1, 0: 6}.items())
actual2 = list(LinearEquation(-3.5, 0).coefficients.items())
expected2 = list({1: -3.5, 0: 0}.items())
assert actual1 == expected1
assert actual2 == expected2
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
--fcc-editable-region--
--fcc-editable-region--
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
```

View File

@@ -0,0 +1,96 @@
---
id: 663a22ba7420c4d2f7fd2aec
title: Step 25
challengeType: 20
dashedName: step-25
---
# --description--
It's time to implement the `solve` method. Given a linear equation in the form \\( ax + b = 0 \\), the solution is \\(x = -\frac{b}{a}\\).
Unpack the coefficients stored in the `coefficients` attribute into the variables `a` and `b`. Note that you'll need to use the `.values()` method.
Then, declare a variable `x`, assign it the solution of the equation and return it from the `solve` method.
# --hints--
You should unpack the values stored inside the `coefficients` attribute into the variables `a` and `b`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").find_function("solve").has_stmt("a, b = self.coefficients.values()")`)) })
```
You should declare a variable named `x` and assign it the solution of the linear equation.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").find_function("solve").has_stmt("x = -b/a")`)) })
```
You should return `x` from your `solve` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").find_function("solve").has_return("x")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
continue
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+').strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
--fcc-editable-region--
def solve(self):
pass
--fcc-editable-region--
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,83 @@
---
id: 663a2dd1901cbeecc28748bd
title: Step 26
challengeType: 20
dashedName: step-26
---
# --description--
It's time to test the `solve` method. Call it on `lin_eq` and print the result.
# --hints--
You should call the `solve` method of your `lin_eq` object and print the result.
```js
({ test: () => assert(runPython(`
_Node(_code).has_call("print(lin_eq.solve())")
`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
pass
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
print(lin_eq)
--fcc-editable-region--
```

View File

@@ -0,0 +1,106 @@
---
id: 663a32735b317af9812eb0d7
title: Step 27
challengeType: 20
dashedName: step-27
---
# --description--
In linear equations in the form \\( ax + b = 0 \\), the slope is simply the coefficient \\( a \\), and the y-intercept is the coefficient \\( b \\).
<img alt="a plot of a linear function" src="https://cdn.freecodecamp.org/curriculum/python/linear-equation.png" style="background-color: white; height: 350px; width: auto; padding: 15px; display: block; margin-right: auto; margin-left: auto; margin-bottom: 1.2rem;" />
You are going to use the `analyze` method to provide additional information about the equation. Inside the `analyze` method, unpack the coefficients into the variables `slope` and `intercept`.
Then, return a dictionary with the keys `'slope'` and `'intercept'` and the values of the slope and the y-intercept, respectively. After that, call `analyze` on `lin_eq` and print the result.
# --hints--
You should unpack the values stored in the `coefficients` attribute into the variables `slope` and `intercept` inside the `analyze` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("LinearEquation").find_function("analyze").has_stmt("slope, intercept = self.coefficients.values()")`)) })
```
The `analyze` method should return a dictionary with the keys `'slope'` and `'intercept'` and the values of the slope and the y-intercept, respectively.
```js
({ test: () => runPython(`
eq = LinearEquation(2.2, 1.5)
a = eq.analyze()
assert a['slope'] == 2.2, "Expected different slope"
assert a['intercept'] == 1.5, "Expected different intercept"
`) })
```
You should call the `analyze` method of your `lin_eq` object.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(lin_eq.analyze())")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
--fcc-editable-region--
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
print(lin_eq.solve())
--fcc-editable-region--
```

View File

@@ -0,0 +1,116 @@
---
id: 663b7fefd437bd984e091cbf
title: Step 29
challengeType: 20
dashedName: step-29
---
# --description--
Next, create a new class named `QuadraticEquation` and make it inherit from `Equation`. You'll use this new class to represent quadratic equations, which are second-degree equations having the form $ax^2 + bx + c = 0$.
Inside your new class, define a `degree` class attribute with the value `2`, which is the degree of a quadratic equation. Also, define the `solve` and `analyze` methods. You will take care of the implementation in the following steps.
# --hints--
You should create a new class named `QuadraticEquation` and make it inherit from the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").inherits_from("Equation")`)) })
```
You should define a `solve` method within the `QuadraticEquation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").has_function("solve")`)) })
```
Your `solve` method should take a single parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").find_function("solve").has_args("self")`)) })
```
You should define an `analyze` method within the `QuadraticEquation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").has_function("analyze")`)) })
```
Your `analyze` method should take a single parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").find_function("analyze").has_args("self")`)) })
```
You should define a `degree` class attribute within the `QuadraticEquation` class and assign it the value `2`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").find_variable("degree").is_equivalent("degree = 2")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
--fcc-editable-region--
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,97 @@
---
id: 663b83a28943e6aa6275a514
title: Step 19
challengeType: 20
dashedName: step-19
---
# --description--
Still within the `Equation` class, define a `__str__` method to give a proper string representation to the equation objects you are going to create.
For now, within the `__str__` method, declare a variable `terms` and assign it an empty list. You'll use this variable to store each term (coefficient times \\( x^n \\)) of your equation.
Then, declare a variable `equation_string`, assign it the result of joining the elements in the `terms` list with a space. Finally, return `equation_string`.
# --hints--
You should define a `__str__` method within the `Equation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").has_function("__str__")`)) })
```
Your `__str__` method should take one parameter, `self`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").has_args("self")`)) })
```
You should declare a variable `terms` and assign it an empty list within the `__str__` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").has_stmt("terms = []")`)) })
```
You should declare a variable `equation_string` and assign it the result of joining the elements in `terms` with a space within the `__str__` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").has_stmt("equation_string = ' '.join(terms)")`)) })
```
You should return `equation_string` from your `__str__` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").has_return("equation_string")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
--fcc-editable-region--
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,110 @@
---
id: 663b93aee129b3c4cc07d0db
title: Step 20
challengeType: 20
dashedName: step-20
---
# --description--
Just after the `terms` list, create a `for` loop and use the `.items()` method to iterate over the keys and values stored in the `coefficients` attribute. Use `n` and `coefficient` as the loop variables.
Inside the loop, create an `if` statement that checks if the coefficient at the current iteration has a falsy value and skip the iteration in that case. This is because you don't want to represent coefficients with the value of zero.
# --hints--
You should create a `for` loop that iterates over `coefficients.items()`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_for_iter().is_equivalent("self.coefficients.items()")`)) })
```
Your `for` loop should use `n` and `coefficient` to iterate over `coefficients.items()`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_for_vars().is_equivalent("n, coefficient")`)) })
```
You should create an `if` statement to check if `coefficient` has a falsy value inside your `for` loop.
```js
({ test: () => assert(runPython(`
if_cond = _Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[0].find_conditions()[0]
conditions = ["not coefficient", "coefficient == 0", "0 == coefficient"]
any(if_cond.is_equivalent(condition) for condition in conditions)
`)) })
```
You should use the `continue` keyword inside your new `if` statement.
```js
({ test: () => assert(runPython(`
_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[0].find_bodies()[0].has_stmt("continue")
`)) })
```
Your `for` loop should be placed just after the declaration of `terms`.
```js
({ test: () => assert(runPython(`
loop = str(_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0])
_Node(_code).find_class("Equation").find_function("__str__").is_ordered("terms = []", loop, "equation_string = ' '.join(terms)", "return equation_string")
`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
--fcc-editable-region--
def __str__(self):
terms = []
--fcc-editable-region--
equation_string = ' '.join(terms)
return equation_string
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,82 @@
---
id: 663b95d65caeb3ca04c5fef4
title: Step 21
challengeType: 20
dashedName: step-21
---
# --description--
If the coefficient has a non-zero value, you can have different cases. If `n == 0`, the term is made by the coefficient itself.
After your `if` statement, create another `if` statement for this case and append a string containing the coefficient to the `terms` list. Use an f-string for that.
# --hints--
You should create an `if` statement to check if `n` is equal to `0` after your existing `if` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_conditions()[0].is_equivalent("n==0")`)) })
```
You should append `f'{coefficient}'` to the `terms` list within your new `if` statement.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_bodies()[0].is_equivalent("terms.append(f'{coefficient}')")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
--fcc-editable-region--
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
continue
equation_string = ' '.join(terms)
return equation_string
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,84 @@
---
id: 663c981b9b06922e13a97fe9
title: Step 22
challengeType: 20
dashedName: step-22
---
# --description--
Create an `elif` clause for the case `n == 1`. Within the `elif` clause, create an f-string containing the coefficient directly followed by a lowercase `x` and append it to the `terms` list.
# --hints--
You should create an `elif` clause to check if `n` is equal to `1`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_conditions()[1].is_equivalent("n==1")`)) })
```
You should append `f'{coefficient}x'` to the `terms` list within your new `elif` clause.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_bodies()[1].is_equivalent("terms.append(f'{coefficient}x')")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
--fcc-editable-region--
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
continue
if n == 0:
terms.append(f'{coefficient}')
equation_string = ' '.join(terms)
return equation_string
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,86 @@
---
id: 663c9f31306353460da54542
title: Step 23
challengeType: 20
dashedName: step-23
---
# --description--
As you can see, the `+` sign is missing from the output. The number sign is displayed by default only if negative. To change this behaviour, you can write a colon after the expression to be evaluated within the curly braces of your f-string, and specify the option `+`. This will allow you to display the sign both for positive and negative numbers.
Modify the string in your two conditional clauses by adding `:+` inside the curly braces after `coefficient`.
# --hints--
You should modify the string to append to the `terms` list within your `if` statement into `f'{coefficient:+}'`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_bodies()[0].is_equivalent("terms.append(f'{coefficient:+}')")`)) })
```
You should modify the string to insert into the `terms` list within your `elif` clause into `f'{coefficient:+}x'`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_bodies()[1].is_equivalent("terms.append(f'{coefficient:+}x')")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
--fcc-editable-region--
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
continue
if n == 0:
terms.append(f'{coefficient}')
elif n == 1:
terms.append(f'{coefficient}x')
equation_string = ' '.join(terms)
return equation_string
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,66 @@
---
id: 664c670069bae45fd060c25d
title: Step 18
challengeType: 20
dashedName: step-18
---
# --description--
Next, print your `lin_eq` instance.
# --hints--
You should print `lin_eq`.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(lin_eq)")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
--fcc-editable-region--
```

View File

@@ -0,0 +1,87 @@
---
id: 664cb04a16fe6938708967ef
title: Step 24
challengeType: 20
dashedName: step-24
---
# --description--
After joining the terms, concatenate the string `' = 0'` to `equation_string` to display the complete equation.
Also, to refine the output, remove any leading `+` sign from `equation_string`.
# --hints--
The `__str__` method should return a different string representation.
```js
({ test: () => assert(runPython(`
eq1 = LinearEquation(4, 2)
str(eq1) == '4x +2 = 0'
`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
continue
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
--fcc-editable-region--
equation_string = ' '.join(terms)
return equation_string
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,116 @@
---
id: 664e4a590b52ba8d2adff19f
title: Step 30
challengeType: 20
dashedName: step-30
---
# --description--
The discriminant of a quadratic equation in the form \\( ax^2 + bx + c = 0 \\), usually indicated by the capital Greek letter delta, is equal to \\( Δ = b^2 - 4ac \\).
Within the `QuadraticEquation` class, define an `__init__` method. Use `super()` to call the `__init__` method from the parent class. Then, define a new attribute named `delta`, which stores the value of the discriminant of the equation.
# --hints--
You should define an `__init__` method within the `QuadraticEquation` class.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").has_function("__init__")`)) })
```
Your `__init__` method should take two parameters, `self` and `*args`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").find_function("__init__").has_args("self, *args")`)) })
```
You should call `super().__init__(*args)` within your `__init__` method.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("QuadraticEquation").find_function("__init__").has_call("super().__init__(*args)")`)) })
```
You should declare a `delta` attribute within your `__init__` method and assign it the value of the discriminant of the equation.
```js
({ test: () => runPython(`
eq = QuadraticEquation(2, -3, -4)
assert eq.delta == 41
`) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
--fcc-editable-region--
--fcc-editable-region--
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
```

View File

@@ -0,0 +1,105 @@
---
id: 664e4e1b6c35a99cbba49e84
title: Step 31
challengeType: 20
dashedName: step-31
---
# --description--
Now, create an instance of the `QuadraticEquation` class to represent the equation \\( 11x^2 - x + 1 = 0 \\).
Assign the new instance to a variable `quadr_eq`, then print your new variable. Note that, at this point, the second degree term would be missing from the string representation of the equation.
# --hints--
You should declare a variable named `quadr_eq` and assign it an instance of `QuadraticEquation` passing it `11`, `-1`, and `1` as the arguments.
```js
({ test: () => assert(runPython(`_Node(_code).has_stmt("quadr_eq = QuadraticEquation(11, -1, 1)")`)) })
```
You should print your `quadr_eq` variable.
```js
({ test: () => assert(runPython(`_Node(_code).has_call("print(quadr_eq)")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
pass
def analyze(self):
pass
--fcc-editable-region--
lin_eq = LinearEquation(2, 3)
print(lin_eq)
--fcc-editable-region--
```

View File

@@ -0,0 +1,110 @@
---
id: 664ee8037f4bbe3c0944c35e
title: Step 32
challengeType: 20
dashedName: step-32
---
# --description--
As you can see, the second-degree term is missing from the string representation. Within the `__str__` method, create an `else` clause to handle the case in which the exponent of \\( x \\) is greater than `1`.
Append a string to the `terms` list so that the term is represented as `<coefficient>x**<exponent>`. Display the number sign both for positive and negative coefficients and make sure that the inserted string is suitable to represent equations of degree > 2, too.
# --hints--
You should create an `else` clause after your existing `elif` clause.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_conditions()[2].is_empty()`)) })
```
You should append `f'{coefficient:+}x**{n}'` to the `terms` list within your new `else` clause.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").find_for_loops()[0].find_ifs()[1].find_bodies()[2].is_equivalent("terms.append(f'{coefficient:+}x**{n}')")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
--fcc-editable-region--
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
--fcc-editable-region--
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(11, -1, 1)
print(quadr_eq)
```

View File

@@ -0,0 +1,105 @@
---
id: 664eec7f38234443b42c206f
title: Step 33
challengeType: 20
dashedName: step-33
---
# --description--
Your equation is currently represented as `11x**2 -1x +1 = 0`, but it would be nice not to display the coefficient multiplying \\( x \\) when it's equal to one. So that equation is represented as `11x**2 -x +1 = 0`.
Import the `re` module. You are going to use a regular expression to substitute the coefficients for this case during the next steps.
# --hints--
You should import the `re` module.
```js
({ test: () => assert(runPython(`_Node(_code).has_import("import re")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
--fcc-editable-region--
--fcc-editable-region--
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
return equation_string.strip('+')
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(11, -1, 1)
print(quadr_eq)
```

View File

@@ -0,0 +1,114 @@
---
id: 664eef158d792a509e8d708a
title: Step 34
challengeType: 20
dashedName: step-34
---
# --description--
The `sub` function from the `re` module enables you to replace text inside a string based on a regex pattern.
```py
verse = 'Always look on the bright side of life'
spam = re.sub('bright', 'spam', verse)
spam == 'Always look on the spam side of life' # True
```
It takes three arguments: the regex pattern to match, the replacement, and the string on which you want to perform the replacement.
From your `__str__` function, return a `sub()` call passing the string `'1'`, an empty string, and your existing `equation_string.strip('+')` call as the arguments. This will replace each `1` with an empty string. The result is not refined yet and you'll continue to work on the regex pattern in the next steps.
# --hints--
You should return a `re.sub()` call from your `__str__` method. Pass the string `'1'`, an empty string, and your existing `equation_string.strip('+')` call as the arguments to `re.sub()`.
```js
({ test: () => assert(runPython(`_Node(_code).find_class("Equation").find_function("__str__").has_return("re.sub('1', '', equation_string.strip('+'))")`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
--fcc-editable-region--
return equation_string.strip('+')
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(11, -1, 1)
print(quadr_eq)
```

View File

@@ -0,0 +1,124 @@
---
id: 664ef4623946e65e18d59764
title: Step 35
challengeType: 20
dashedName: step-35
---
# --description--
In a regex pattern, a *lookaround* is an assertion that matches a certain pattern without consuming characters in the string. One kind of lookaround is the lookbehind, which can be either positive or negative. They are denoted by `(?<=...)` and `(?<!...)`, respectively.
```py
spam = 'black back bat'
re.sub('(?<=l)a', 'o', spam) == 'block back bat' # True
re.sub('(?<!l)a', 'o', spam) == 'black bock bot' # True
```
In the example above, the pattern `(?<=l)a` contains a positive lookbehind, which is used to match the `a` character only when preceded by an `l`. In the last line of the example, the pattern `(?<!l)a` contains a negative lookbehind, which is used to match the `a` character only if it is **not** preceded by an `l`. Note how, in both cases, the character contained in the lookbehind is not consumed.
Modify your regex pattern to use a negative lookbehind so that the character `1` is substituted only if not preceded by a digit.
# --hints--
You should modify the pattern passed as the first argument to the `re.sub()` call using a negative lookbehind. TODO: add details/improve wording
```js
({ test: () => assert(runPython(`
node = _Node(_code).find_class("Equation").find_function("__str__")
values = [
"re.sub('(?<!\\d)1', '', equation_string.strip('+'))",
"re.sub(r'(?<!\\d)1', '', equation_string.strip('+'))",
"re.sub('(?<![0-9])1', '', equation_string.strip('+'))"
]
any(node.has_return(value) for value in values)
`)) })
```
# --seed--
## --seed-contents--
```py
from abc import ABC, abstractmethod
import re
class Equation(ABC):
degree: int
def __init__(self, *args):
if (self.degree + 1) != len(args):
raise TypeError(
f"'Equation' object takes {self.degree + 1} positional arguments but {len(args)} were given"
)
if any(not isinstance(arg, (int, float)) for arg in args):
raise TypeError("Coefficients must be of type 'int' or 'float'")
if args[0] == 0:
raise ValueError("Highest degree coefficient must be different from zero")
self.coefficients = {(len(args) - n - 1): arg for n, arg in enumerate(args)}
def __init_subclass__(cls):
if not hasattr(cls, "degree"):
raise AttributeError(
f"Cannot create '{cls.__name__}' class: missing required attribute 'degree'"
)
def __str__(self):
terms = []
for n, coefficient in self.coefficients.items():
if not coefficient:
coefficient
if n == 0:
terms.append(f'{coefficient:+}')
elif n == 1:
terms.append(f'{coefficient:+}x')
else:
terms.append(f"{coefficient:+}x**{n}")
equation_string = ' '.join(terms) + ' = 0'
--fcc-editable-region--
return re.sub('1', '', equation_string.strip('+'))
--fcc-editable-region--
@abstractmethod
def solve(self):
pass
@abstractmethod
def analyze(self):
pass
class LinearEquation(Equation):
degree = 1
def solve(self):
a, b = self.coefficients.values()
x = -b / a
return x
def analyze(self):
slope, intercept = self.coefficients.values()
return {'slope': slope, 'intercept': intercept}
class QuadraticEquation(Equation):
degree = 2
def __init__(self, *args):
super().__init__(*args)
a, b, c = self.coefficients.values()
self.delta = b**2 - 4 * a * c
def solve(self):
pass
def analyze(self):
pass
lin_eq = LinearEquation(2, 3)
print(lin_eq)
quadr_eq = QuadraticEquation(11, -1, 1)
print(quadr_eq)
```

Some files were not shown because too many files have changed in this diff Show More