Exemple #1
0
 def ft_pow():
     if (isinstance(self.right, X_class.X)
             and self.right.power) or isinstance(self.right, Operator):
         ft_error("Error : Invalid power term.")
     if isinstance(self.right, X_class.X):
         self.right = float(self.right.factor)
     self.value = self.left**self.right
Exemple #2
0
 def __truediv__(self, other):
     if not other or (isinstance(other, X_class.X) and not other.factor):
         ft_error("Error : division by zero.")
     if isinstance(other, X_class.X) or isinstance(other, float):
         return self.left / other + self.right / other
     if isinstance(other, Operator) and self == other:
         return X_class.X(power=0.0)
     else:
         ft_error("Equation non reductible and hence unsolvable.")
Exemple #3
0
 def __pow__(self, other):
     if other % 1.0:
         ft_error("Error : power of operations must be integer.")
     if other == 1:
         return self
     elif other == 0:
         return X_class.X(power=0.0)
     elif other < 0:
         return X_class.X(power=0.0) / (self**(-other))
     elif isinstance(other, float):
         return self * self.__pow__(other - 1)
Exemple #4
0
	def __truediv__(self, other):
		if isinstance(other, X) and not other.factor:
			ft_error("Error : division by zero.")
		if isinstance(other, X):
			new_obj = X()
			new_obj.factor = self.factor / other.factor
			new_obj.power = self.power - other.power
			return new_obj
		if isinstance(other, float):
			self.factor = self.factor / other
			return self
		ft_error("Equation non reductible and unsolvable.")
		return None
Exemple #5
0
    def build_trees(self):
        """
		Method which builds the left and right trees from the input string, using a syntactic binary tree
		through the shunting_yard algorithm
		"""

        operator_stack = deque()
        list_eq = self.equation_str.split(
            '=')[0] + '-' + '(' + self.equation_str.split('=')[1] + ')'
        list_eq = list_eq.replace('(+', '(0+').replace('(-', '(0-')
        j = 0
        while j < len(list_eq):
            n = ''
            while j < len(list_eq) and ('0' <= list_eq[j] <= '9'
                                        or list_eq[j] == '.'):
                n = n + list_eq[j]
                j += 1
            if n:
                j -= 1
                self.tree.append(X(factor=float(n), power=0.0))
            elif list_eq[j] == 'X':
                self.tree.append(X())
            elif list_eq[j] in dic_precedence.keys():
                while operator_stack and operator_stack[-1] != '('\
                  and dic_precedence[operator_stack[-1].oper] >= dic_precedence[list_eq[j]]:
                    self.tree.append(operator_stack.pop())
                operator_stack.append(Operator(list_eq[j]))
            elif list_eq[j] == '(':
                operator_stack.append(list_eq[j])
            elif list_eq[j] == ')':
                while operator_stack and operator_stack[-1] != '(':
                    self.tree.append(operator_stack.pop())
                if not operator_stack:
                    ft_error("Error : mismatched parentheses.")
                if operator_stack[-1] == '(':
                    operator_stack.pop()
            j += 1
        while operator_stack:
            if operator_stack[-1] == '(':
                ft_error("Error : mismatched parentheses.")
            else:
                self.tree.append(operator_stack.pop())

        return None
Exemple #6
0
    def parsing_errors(self):
        if not self.equation_str:
            ft_error("Syntax error : please provide a valid equation.")
        self.equation_str = self.equation_str.replace(' ', '')
        if '=' not in self.equation_str:
            ft_error("Syntax error : please provide a valid equation.")

        dic_error = {
            r"(^=|=$|=.*=)": "Syntax error : please provide a valid equation.",
            r"[^X\+0-9\(\)=\^\*\-\./]":
            "Syntax error : unauthorized token in equation.",
            r"(^[\*\^/]|=[\*\^/])":
            "Syntax error : first element is a wrong operator (ony + and - allowed)",
            r"[\*\^/\+\-=]$":
            "Syntax error : last element is not a valid token to end the equation.",
            r"([X0-9]\(|\)[X0-9])":
            "Syntax error : missing operator around parentheses",
            r"(\.[^0-9]|[^0-9]\.)":
            "Syntax error : need a digit before and after a dot.",
            r"([0-9]X|X[0-9])":
            "Syntax error : an operator has to precede or succeed an X element.",
            r"([=\(\-\+\^\*/][\*/\^]|[\*\^\+\-/\(]=|[\-\+\^\*/][\+\-\*/\^])":
            "Syntax error : two operators side by side which cannot be combined.",
            r"\(\)": "Syntax error : empty parentheses.",
            r"(\([^\)]*=|.*=[^\(]*\))": "Syntax error : error in parentheses.",
        }

        for k, v in dic_error.items():
            reg = re.compile(k)
            if reg.search(self.equation_str):
                ft_error(v)

        return None
Exemple #7
0
    def solve_equation(self):
        def deal_negatives():
            new_dico_elem = {}
            for k, v in self.reduced_elem.items():
                new_dico_elem[k -
                              self.min_degree] = v * X(power=-self.min_degree)
            self.reduced_elem = new_dico_elem
            self.ft_getdegree()
            self.new_reduced_str = self.reduced_equation_str()
            print(
                "There is at least one degree strictly lower than 0. Therefore, we multiply each element by the "
                "absolute value of the lowest degree to try to solve this equation.\n"
            )
            print(f"New reduced form : {self.new_reduced_str}")
            print(
                f"Polynomial degree of the new equation : {self.max_degree}\n")
            return None

        a = 0
        b = 0
        c = 0
        if Equation.flag_n:
            if self.min_degree < 0:
                deal_negatives()
        elif self.min_degree < 0:
            ft_error(
                "There exists a degree strictly lower than 0. This cannot be solved. Use -n flag to try to solve this equation.\n"
            )
        if self.max_degree > 2:
            ft_error(
                "This equation is of a degree higher than 2. This algorithm is not built to solve it.\n"
            )
        for k, v in self.reduced_elem.items():
            if k == 2:
                a = v.factor
            elif k == 1:
                b = v.factor
            elif k == 0:
                c = v.factor
        if not a and not b and not c:
            if 'X' not in self.equation_str:
                print("Always true.\n")
            else:
                print("Always true. All real numbers are solutions.\n")
            sys.exit(0)
        elif not a and not b and c:
            ft_error("Impossible equation. No solution.\n")
        elif (not a and b and not c) or (a and not b and not c):
            self.solution1 = 0
            self.solution1_str = f"X = {self.solution1}"
        elif not a and b and c:
            self.solution1 = -c / b
            self.solution1_str = f"X = -({self.num_format(c)}) / {self.num_format(b)} = {self.num_format(self.solution1)}"
        else:
            self.delta = b**2 - 4 * a * c
            self.delta_str = f"Δ = {self.num_format(b)}^2 - 4 * {self.num_format(a)} * {self.num_format(c)} = {self.num_format(self.delta)}"

            if self.delta == 0:
                self.solution1 = -b / (2 * a)
                self.solution1_str = f"X = -({self.num_format(b)}) / (2 * {self.num_format(a)}) = {self.num_format(self.solution1)}"

            elif self.delta > 0:
                sq_delta_pos = sqrt(self.delta)
                self.solution1 = (-b - sq_delta_pos) / (2 * a)
                self.solution2 = (-b + sq_delta_pos) / (2 * a)
                self.solution1_str = (
                    f"X1 = (-({self.num_format(b)}) - sqrt({self.num_format(self.delta)}) / (2 * {a}) = "
                    f"(-({self.num_format(b)}) - {self.num_format(sq_delta_pos)} / (2 * {self.num_format(a)}) = {self.num_format(self.solution1)}"
                )
                self.solution2_str = (
                    f"X2 = (-({self.num_format(b)}) + sqrt({self.num_format(self.delta)}) / (2 * {self.num_format(a)}) = "
                    f"(-({self.num_format(b)}) + {self.num_format(sq_delta_pos)} / (2 * {self.num_format(a)}) = {self.num_format(self.solution2)}"
                )

            elif self.delta < 0:
                sq_delta = sqrt(-self.delta)
                if not b:
                    factor = sq_delta / (2 * a)
                    if factor == 1:
                        self.solution1 = "-i"
                        self.solution2 = "i"
                    else:
                        self.solution1 = f"-i * {self.num_format(factor)}"
                        self.solution2 = f"i * {self.num_format(factor)}"
                else:
                    self.solution1 = f"({self.num_format(-b)} - i * {self.num_format(sq_delta)}) / {self.num_format(2 * a)}"
                    self.solution2 = f"({self.num_format(-b)} + i * {self.num_format(sq_delta)}) / {self.num_format(2 * a)}"
                self.solution1_str = (
                    f"X1 = (-({self.num_format(b)}) - i * sqrt({self.num_format(-self.delta)}) / (2 * {self.num_format(a)}) "
                    f"= (-({self.num_format(b)}) - i * {self.num_format(sq_delta)}) / {self.num_format(2 * a)} = {self.num_format(self.solution1)}"
                )
                self.solution2_str = (
                    f"X2 = (-({self.num_format(b)}) + i * sqrt({self.num_format(-self.delta)}) / (2 * {self.num_format(a)}) "
                    f"= (-({self.num_format(b)}) + i * {self.num_format(sq_delta)} / {self.num_format(2 * a)} = {self.num_format(self.solution2)}"
                )

        return None