mirror of
https://github.com/freeCodeCamp/freeCodeCamp.git
synced 2026-04-30 16:01:14 -04:00
chore(i18n,learn): processed translations (#55488)
This commit is contained in:
committed by
GitHub
parent
8ca1f764a6
commit
a1b40fecb9
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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()
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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()
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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())
|
||||
|
||||
```
|
||||
@@ -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())
|
||||
|
||||
```
|
||||
@@ -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())
|
||||
|
||||
```
|
||||
@@ -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())
|
||||
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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()
|
||||
```
|
||||
@@ -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()
|
||||
```
|
||||
@@ -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()
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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))
|
||||
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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(`
|
||||
|
||||
@@ -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!
|
||||
|
||||
|
||||
@@ -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`.
|
||||
|
||||
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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()
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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()
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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)
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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--
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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)
|
||||
|
||||
```
|
||||
@@ -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
Reference in New Issue
Block a user