from typing import List, Tuple import random NR_EQUATIONS = 2 VALUES_PER_EQUATION = 3 class Equation: """ An Equation holds a list of integers forming an `equation`, e.g. 3 + 6 - 4, and the respective `__solution`, e.g. 5. """ __equation: List[int] __solution: int def __init__(self, equation: List[int] = None): if equation: self.__equation = equation else: self.__equation = self.generate_random_equation() assert len(self.__equation) == VALUES_PER_EQUATION self.__solution = sum(self.__equation) @staticmethod def generate_random_equation(): while True: values = [random.randint(-9, 9) for _ in range(VALUES_PER_EQUATION)] if values[0] >= 0 and sum(values) >= 0: break return values def __str__(self): return self.to_task_string() + " " + str(self.__solution) def to_task_string(self): if not len(self.__equation): return "" head, *tail = self.__equation s = ["-" + str(abs(head))] if head < 0 else [str(head)] for v in tail: s.append("-") if v < 0 else s.append("+") s.append(str(abs(v))) s.append("=") return " ".join(s) def get_solution(self) -> int: return self.__solution class ArithmeticTask: """ An ArithmeticTask holds two `__equations`, e.g. 3 + 6 - 4 = 5 and 8 - 7 + 1 = 2 The `__solution` is the min of all `__equations` subtracted by the max, e.g. 5 - 2 = 3. """ __equations: Tuple[Equation, Equation] __solution: int def __init__(self, equations: Tuple[Equation, Equation] = None): """ Create an ArithmeticTask from two given `__equations` or generate random ones """ if equations: self.__equations = equations else: self.__equations = self.generate_random_equations() assert len(self.__equations) == NR_EQUATIONS results_of_equations = [e.get_solution() for e in self.__equations] self.__solution = max(results_of_equations) - min(results_of_equations) @staticmethod def generate_random_equations() -> Tuple[Equation, Equation]: return tuple(Equation() for _ in range(NR_EQUATIONS)) def __str__(self) -> str: return ", ".join([str(e) for e in self.__equations]) def get_solution(self) -> int: return self.__solution def get_equations(self) -> Tuple[Equation, Equation]: return self.__equations def get_equations_as_string(self) -> Tuple[str, str]: return [e.to_task_string() for e in self.__equations] def is_correct(self, answer) -> bool: if not isinstance(answer, (float, int)): return False if answer != self.__solution: return False return True class ArithmeticTaskFactory: @staticmethod def get_example_tasks() -> List[ArithmeticTask]: example1 = ArithmeticTask((Equation([7, 3, -8]), Equation([8, 9, -8]))) example2 = ArithmeticTask((Equation([4, 6, -2]), Equation([5, 3, 4]))) return [example1, example2] @staticmethod def get_comprehension_tasks() -> List[ArithmeticTask]: t1 = ArithmeticTask((Equation([9, -3, -4]), Equation([7, 5, 1]))) t2 = ArithmeticTask((Equation([8, 4, -7]), Equation([1, -5, 6]))) t3 = ArithmeticTask((Equation([9, 9, -5]), Equation([4, -6, 7]))) t4 = ArithmeticTask((Equation([3, 2, 6]), Equation([7, 9, -1]))) t5 = ArithmeticTask((Equation([1, 9, 2]), Equation([3, -5, 9]))) return [t1, t2, t3, t4, t5] @staticmethod def get_working_tasks(n: int = 100) -> List[ArithmeticTask]: return [ArithmeticTask() for i in range(n)]