Object Oriented Paradigm#

Initial Set-Up#

from dataclasses import dataclass
from abc import ABC, abstractmethod


class Operation(ABC):
    @abstractmethod
    def compute(self) -> float:
        ...

Predecessor and Successor#

@dataclass
class Predecessor(Operation):
    a: int

    def compute(self) -> int:
        return self.a - 1


assert Predecessor(1).compute() == 0
assert Predecessor(10).compute() == 9
@dataclass
class Successor(Operation):
    a: int

    def compute(self) -> int:
        return self.a + 1


assert Successor(0).compute() == 1
assert Successor(10).compute() == 11

Addition#

@dataclass
class Adder(Operation):
    addend_1: int
    addend_2: int

    def compute(self) -> int:
        result = self.addend_1
        for _ in range(self.addend_2):
            result = Successor(result).compute()
        return result


assert Adder(0, 0).compute() == 0
assert Adder(1, 0).compute() == 1
assert Adder(0, 1).compute() == 1
assert Adder(10, 10).compute() == 20

Multiplication#

@dataclass
class Multiplier(Operation):
    multiplier: int
    multiplicand: int

    def compute(self) -> int:
        result = 0
        for _ in range(self.multiplier):
            result = Adder(result, self.multiplicand).compute()
        return result


assert Multiplier(0, 0).compute() == 0
assert Multiplier(2, 0).compute() == 0
assert Multiplier(0, 2).compute() == 0
assert Multiplier(10, 10).compute() == 100

Exponentiation#

@dataclass
class Power(Operation):
    base: int
    exponent: int

    def compute(self) -> int:
        result = 1
        for _ in range(self.exponent):
            result = Multiplier(result, self.base).compute()
        return result


assert Power(1, 0).compute() == 1
assert Power(0, 1).compute() == 0
assert Power(3, 3).compute() == 27