-
-
Notifications
You must be signed in to change notification settings - Fork 50.3k
feat(other): add basic BankAccount OOP class #14543
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
c93841e
07539cb
3fb7cf3
15f5588
cee29eb
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,63 @@ | ||
| """ | ||
| Utilities related to repunits and a classical repunit divisibility theorem. | ||
|
|
||
| A repunit of length ``k`` is the number made of ``k`` ones: | ||
| ``R_k = 11...1``. | ||
|
|
||
| For every positive integer ``n`` with ``gcd(n, 10) = 1``, | ||
| there exists a repunit ``R_k`` divisible by ``n``. | ||
| """ | ||
|
|
||
| from math import gcd | ||
|
|
||
|
|
||
| def has_repunit_multiple(divisor: int) -> bool: | ||
| """ | ||
| Check whether a divisor admits a repunit multiple. | ||
|
|
||
| >>> has_repunit_multiple(7) | ||
| True | ||
| >>> has_repunit_multiple(13) | ||
| True | ||
| >>> has_repunit_multiple(2) | ||
| False | ||
| >>> has_repunit_multiple(25) | ||
| False | ||
| """ | ||
| if divisor <= 0: | ||
| raise ValueError("divisor must be a positive integer") | ||
| return gcd(divisor, 10) == 1 | ||
|
|
||
|
|
||
| def least_repunit_length(divisor: int) -> int: | ||
| """ | ||
| Return the smallest length ``k`` such that repunit ``R_k`` is divisible by divisor. | ||
|
|
||
| Uses modular arithmetic to avoid constructing huge integers. | ||
|
|
||
| >>> least_repunit_length(3) | ||
| 3 | ||
| >>> least_repunit_length(7) | ||
| 6 | ||
| >>> least_repunit_length(41) | ||
| 5 | ||
| """ | ||
| if divisor <= 0: | ||
| raise ValueError("divisor must be a positive integer") | ||
| if not has_repunit_multiple(divisor): | ||
| raise ValueError("divisor must be coprime to 10") | ||
|
|
||
| remainder = 0 | ||
| for length in range(1, divisor + 1): | ||
| remainder = (remainder * 10 + 1) % divisor | ||
| if remainder == 0: | ||
| return length | ||
|
|
||
| # Unreachable when gcd(divisor, 10) == 1 (pigeonhole principle theorem). | ||
| raise ArithmeticError("no repunit length found for divisor") | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| import doctest | ||
|
|
||
| doctest.testmod() | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,60 @@ | ||
| """ | ||
| Simple BankAccount class demonstrating core OOP concepts. | ||
| """ | ||
|
|
||
|
|
||
| class BankAccount: | ||
| """ | ||
| Basic bank account model with encapsulated account number and balance. | ||
|
|
||
| >>> account = BankAccount("ACC-1001", initial_balance=100.0) | ||
| >>> account.balance | ||
| 100.0 | ||
| >>> account.deposit(50) | ||
| 150.0 | ||
| >>> account.withdraw(20) | ||
| 130.0 | ||
| >>> account.account_number | ||
| 'ACC-1001' | ||
| """ | ||
|
|
||
| def __init__(self, account_number: str, initial_balance: float = 0.0) -> None: | ||
| if not account_number: | ||
| raise ValueError("account_number must be provided") | ||
| if initial_balance < 0: | ||
| raise ValueError("initial_balance cannot be negative") | ||
|
|
||
| self.__account_number = account_number | ||
| self._balance = float(initial_balance) | ||
|
Comment on lines
+21
to
+28
|
||
|
|
||
| @property | ||
| def account_number(self) -> str: | ||
| """Read-only public accessor for the encapsulated account number.""" | ||
| return self.__account_number | ||
|
|
||
| @property | ||
| def balance(self) -> float: | ||
| """Current account balance.""" | ||
| return self._balance | ||
|
|
||
| def deposit(self, amount: float) -> float: | ||
| """Deposit a positive amount and return updated balance.""" | ||
| if amount <= 0: | ||
| raise ValueError("deposit amount must be positive") | ||
| self._balance += amount | ||
| return self._balance | ||
|
|
||
| def withdraw(self, amount: float) -> float: | ||
| """Withdraw a positive amount and return updated balance.""" | ||
| if amount <= 0: | ||
| raise ValueError("withdraw amount must be positive") | ||
| if amount > self._balance: | ||
| raise ValueError("insufficient funds") | ||
| self._balance -= amount | ||
| return self._balance | ||
|
Comment on lines
+40
to
+54
|
||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| import doctest | ||
|
|
||
| doctest.testmod() | ||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
PR description/title focus on adding
BankAccount, but this change set also adds a new maths module (maths/repunit_theorem.py) and a new knapsack implementation. Please either update the PR description/title to reflect the additional features or split these into separate PRs to keep the change scoped and reviewable.