Learn Interfaces by Building an Equation Solver - Step 60

Tell us what’s happening:

Use x for the case it says this but at the start it says use a list for the case using appropriate number what does this mean?

Your code so far

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:
                continue
            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()

# User Editable Region

    match 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}']

# User 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))

Your browser information:

User Agent is: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/128.0.0.0 Safari/537.36

Challenge Information:

Learn Interfaces by Building an Equation Solver - Step 60

here you need to use the more advanced method for matching,

it say “appropriate number of elements”, you should not use a number here, but use variables (when needed) inside the list syntax as pattern matching

if you need more explanation, there are various article on the internet, this one for example: Python: Unlocking the Power of Structural Pattern Matching | by Pravash | Medium

1 Like

Hi @OCode

When you have updated the cases …

Finally, modify the f-strings to use the variable names used in each case.

Happy coding

1 Like

so essentially what i have learned, from this article is ill need to use a list [“x”,0]?
it doesn’t specify why i should do this, also i don’t understand the “quit|quit|quit”, it’s been a couple days since i’ve done them steps as i’ve been stuck on alot of steps

i have got this

match results:
        case [0]:
            result_list = ['No real roots']
        case ['x',1]:
            result_list = [f'x = {results[0]:+.3f}']
        case ['x1'|'x2'|2]:
            result_list = [f'x1 = {results[0]:+.3f}', f'x2 = {results[1]:+.3f}']

[] This is a list in Python. This is actually an empty list.
[0] This is a list with 1 element, which is a 0.
['x',1] This is a list with 2 elements, the string ‘x’ (not the variable) and the number 1.

The first case has no roots, so the list would be empty.
How many elements should the 2nd case have?

Remember to use this syntax in the example. Notice the use of a variable and not a string:

case [a]:
        print(a)

And the VARIABLE in the instruction:

Use x for the case the list contains a single element

1 Like

the second case should have two elements

match results:
        case [0]:
            result_list = ['No real roots']
        case [x]:
            result_list = [f'x = {results[0]:+.3f}']
        case [x1|x2|2]:
            result_list = [f'x1 = {results[0]:+.3f}', f'x2 = {results[1]:+.3f}']

i was thinking of not using a string x but i just get a syntax error
“SyntaxError: name capture ‘x1’ makes remaining patterns unreachable”

No, but you’ve coded it correctly anyways? The second case has 1 element which is an x-value:

case [x]:
            result_list = [f'x = {results[0]:+.3f}']

because the result_list has 1 element.

Let’s do the first case now. How many elements should the first case have?

1 Like

oh right i thought you meant case 2 for some reason,and the first case list should be empty as it has no elements, but im still getting syntax error
EDIT: i think its because i have’t updated the f strings

how tho? update the results_list variables to what x =?

match results:
        case []:
            result_list = ['No real roots']
        case [x]:
            result_list =[f'x = {x:+.3f}']
        case [x1,x2]:
            result_list = [f'x1 = {x:+.3f}', f'x2 = {results[1]:+.3f}']

i can almost taste it that’s how close i am
I have done it

2 Likes

in this case you don’t have the x variable available, you only have the variables you put in the case pattern matching, x1 and x2