-
-
Notifications
You must be signed in to change notification settings - Fork 90
Birmingham | 2026-MAR-SDC | Joy Opachavalit | Sprint 5 |Prep exercises #510
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
Open
enjoy15
wants to merge
9
commits into
CodeYourFuture:main
Choose a base branch
from
enjoy15:sprint5-prep-excercises
base: main
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
63f1a43
Type Checking Exercise
enjoy15 17560c8
Classes and objects exercise
enjoy15 3eeccb9
Methods exercise
enjoy15 47becca
dataclasses exercise
enjoy15 93e5244
generics exercise
enjoy15 c8a5d2c
Type Guided Refactorings
enjoy15 59163b5
enums
enjoy15 891839a
inheritance exercise
enjoy15 3778151
Update gitignore
enjoy15 File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1 +1,2 @@ | ||
| node_modules | ||
| **/.venv/ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,22 @@ | ||
| class Person: | ||
| def __init__(self, name: str, age: int, preferred_operating_system: str) -> None: | ||
| self.name = name | ||
| self.age = age | ||
| self.preferred_operating_system = preferred_operating_system | ||
|
|
||
|
|
||
| def is_adult(person: Person) -> bool: | ||
| return person.age >= 18 | ||
|
|
||
|
|
||
| def get_postal_address(person: Person) -> str: | ||
| return person.address | ||
|
|
||
|
|
||
| imran = Person("Imran", 22, "Ubuntu") | ||
| eliza = Person("Eliza", 34, "Arch Linux") | ||
|
|
||
| print(imran.name) | ||
| print(eliza.name) | ||
| print(is_adult(imran)) | ||
| print(is_adult(eliza)) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| from dataclasses import dataclass | ||
| from datetime import date | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class Person: | ||
| name: str | ||
| date_of_birth: date | ||
| preferred_operating_system: str | ||
|
|
||
| def is_adult(self) -> bool: | ||
| today = date.today() | ||
| has_had_birthday_this_year = (today.month, today.day) >= ( | ||
| self.date_of_birth.month, | ||
| self.date_of_birth.day, | ||
| ) | ||
| age = today.year - self.date_of_birth.year | ||
| if not has_had_birthday_this_year: | ||
| age -= 1 | ||
| return age >= 18 | ||
|
|
||
|
|
||
| imran = Person("Imran", date(2002, 6, 15), "Ubuntu") | ||
| imran2 = Person("Imran", date(2002, 6, 15), "Ubuntu") | ||
| eliza = Person("Eliza", date(1990, 11, 20), "Arch Linux") | ||
|
|
||
| print(imran) | ||
| print(imran == imran2) | ||
| print(imran.is_adult()) | ||
| print(eliza.is_adult()) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,108 @@ | ||
| from dataclasses import dataclass | ||
| from enum import Enum | ||
| import sys | ||
| from typing import List | ||
|
|
||
|
|
||
| class OperatingSystem(Enum): | ||
| MACOS = "macOS" | ||
| ARCH = "Arch Linux" | ||
| UBUNTU = "Ubuntu" | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class Person: | ||
| name: str | ||
| age: int | ||
| preferred_operating_system: OperatingSystem | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class Laptop: | ||
| id: int | ||
| manufacturer: str | ||
| model: str | ||
| screen_size_in_inches: float | ||
| operating_system: OperatingSystem | ||
|
|
||
|
|
||
| def find_possible_laptops(laptops: List[Laptop], person: Person) -> List[Laptop]: | ||
| possible_laptops = [] | ||
| for laptop in laptops: | ||
| if laptop.operating_system == person.preferred_operating_system: | ||
| possible_laptops.append(laptop) | ||
| return possible_laptops | ||
|
|
||
|
|
||
| def parse_age(raw_age: str) -> int: | ||
| age = int(raw_age) | ||
| if age <= 0: | ||
| raise ValueError("Age must be a positive integer") | ||
| return age | ||
|
|
||
|
|
||
| def parse_operating_system(raw_operating_system: str) -> OperatingSystem: | ||
| normalised_value = raw_operating_system.strip().lower() | ||
| for operating_system in OperatingSystem: | ||
| if normalised_value == operating_system.value.lower() or normalised_value == operating_system.name.lower(): | ||
| return operating_system | ||
|
|
||
| valid_values = ", ".join(operating_system.value for operating_system in OperatingSystem) | ||
| raise ValueError(f"Preferred operating system must be one of: {valid_values}") | ||
|
|
||
|
|
||
| def create_person_from_input() -> Person: | ||
| name = input("Name: ").strip() | ||
| if not name: | ||
| raise ValueError("Name cannot be empty") | ||
|
|
||
| raw_age = input("Age: ").strip() | ||
| raw_operating_system = input("Preferred operating system (Ubuntu, Arch Linux, macOS): ").strip() | ||
|
|
||
| age = parse_age(raw_age) | ||
| preferred_operating_system = parse_operating_system(raw_operating_system) | ||
|
|
||
| return Person(name=name, age=age, preferred_operating_system=preferred_operating_system) | ||
|
|
||
|
|
||
| def count_laptops_for_operating_system(laptops: List[Laptop], operating_system: OperatingSystem) -> int: | ||
| return sum(1 for laptop in laptops if laptop.operating_system == operating_system) | ||
|
|
||
|
|
||
| def find_most_available_operating_system(laptops: List[Laptop]) -> OperatingSystem: | ||
| counts = { | ||
| operating_system: count_laptops_for_operating_system(laptops, operating_system) | ||
| for operating_system in OperatingSystem | ||
| } | ||
| return max(counts, key=lambda operating_system: counts[operating_system]) | ||
|
|
||
| def main() -> None: | ||
| laptops = [ | ||
| Laptop(id=1, manufacturer="Dell", model="XPS", screen_size_in_inches=13, operating_system=OperatingSystem.ARCH), | ||
| Laptop(id=2, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system=OperatingSystem.UBUNTU), | ||
| Laptop(id=3, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system=OperatingSystem.UBUNTU), | ||
| Laptop(id=4, manufacturer="Apple", model="macBook", screen_size_in_inches=13, operating_system=OperatingSystem.MACOS), | ||
| ] | ||
|
|
||
| try: | ||
| person = create_person_from_input() | ||
| except ValueError as error: | ||
| print(error, file=sys.stderr) | ||
| raise SystemExit(1) | ||
|
|
||
| possible_laptops = find_possible_laptops(laptops, person) | ||
| preferred_count = len(possible_laptops) | ||
| print(f"The library has {preferred_count} laptop(s) with {person.preferred_operating_system.value}.") | ||
|
|
||
| best_operating_system = find_most_available_operating_system(laptops) | ||
| best_count = count_laptops_for_operating_system(laptops, best_operating_system) | ||
|
|
||
| if best_operating_system != person.preferred_operating_system and best_count > preferred_count: | ||
| print( | ||
| f"If you're willing to accept {best_operating_system.value}, " | ||
| f"you're more likely to get a laptop ({best_count} available)." | ||
| ) | ||
|
|
||
|
|
||
| if __name__ == "__main__": | ||
| main() |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,35 @@ | ||
| from dataclasses import dataclass | ||
| from datetime import date | ||
| from typing import List | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class Person: | ||
| name: str | ||
| date_of_birth: date | ||
| children: List["Person"] | ||
|
|
||
| @property | ||
| def age(self) -> int: | ||
| today = date.today() | ||
| has_had_birthday_this_year = (today.month, today.day) >= ( | ||
| self.date_of_birth.month, | ||
| self.date_of_birth.day, | ||
| ) | ||
| years = today.year - self.date_of_birth.year | ||
| if not has_had_birthday_this_year: | ||
| years -= 1 | ||
| return years | ||
|
|
||
|
|
||
| fatma = Person(name="Fatma", date_of_birth=date(2017, 5, 3), children=[]) | ||
| aisha = Person(name="Aisha", date_of_birth=date(2019, 9, 12), children=[]) | ||
|
|
||
| imran = Person(name="Imran", date_of_birth=date(1991, 2, 10), children=[fatma, aisha]) | ||
|
|
||
| def print_family_tree(person: Person) -> None: | ||
| print(person.name) | ||
| for child in person.children: | ||
| print(f"- {child.name} ({child.age})") | ||
|
|
||
| print_family_tree(imran) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,47 @@ | ||
| class Parent: | ||
| def __init__(self, first_name: str, last_name: str): | ||
| self.first_name = first_name | ||
| self.last_name = last_name | ||
|
|
||
| def get_name(self) -> str: | ||
| return f"{self.first_name} {self.last_name}" | ||
|
|
||
|
|
||
| class Child(Parent): | ||
| def __init__(self, first_name: str, last_name: str): | ||
| super().__init__(first_name, last_name) | ||
| self.previous_last_names: list[str] = [] | ||
|
|
||
| def change_last_name(self, last_name: str) -> None: | ||
| self.previous_last_names.append(self.last_name) | ||
| self.last_name = last_name | ||
|
|
||
| def get_full_name(self) -> str: | ||
| suffix = "" | ||
| if len(self.previous_last_names) > 0: | ||
| suffix = f" (née {self.previous_last_names[0]})" | ||
| return f"{self.first_name} {self.last_name}{suffix}" | ||
|
|
||
| person1 = Child("Elizaveta", "Alekseeva") | ||
| print(person1.get_name()) | ||
| print(person1.get_full_name()) | ||
| person1.change_last_name("Tyurina") | ||
| print(person1.get_name()) | ||
| print(person1.get_full_name()) | ||
|
|
||
| person2 = Parent("Elizaveta", "Alekseeva") | ||
| print(person2.get_name()) | ||
| if isinstance(person2, Child): | ||
| print(person2.get_full_name()) | ||
| person2.change_last_name("Tyurina") | ||
| print(person2.get_name()) | ||
| print(person2.get_full_name()) | ||
| else: | ||
| print("Parent does not have get_full_name() or change_last_name().") | ||
|
|
||
| # Predictions vs actual output (play computer): | ||
| # 1) Child inherits get_name() from Parent. | ||
| # 2) Child-specific get_full_name() shows the maiden name after changing last name. | ||
| # 3) Parent supports get_name() only; Child-only methods are unavailable on Parent. | ||
|
|
||
| """ When I played computer, I predicted that Child would inherit get_name() from Parent, so person1.get_name() should work exactly like in Parent, while person1.get_full_name() would only exist on Child and add extra detail after a last-name change. Running the code confirmed this: before changing the name, both methods show “Elizaveta Alekseeva”, and after change_last_name("Tyurina"), get_full_name() includes the maiden-name suffix (née Alekseeva). For person2 (a Parent), only get_name() is available, which shows that inheritance gives Child all parent behavior plus additional child-specific methods, but not the other way around. """ |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,28 @@ | ||
| from datetime import date | ||
|
|
||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The explanations of methods vs functions is missing |
||
|
|
||
| class Person: | ||
| def __init__(self, name: str, date_of_birth: date, preferred_operating_system: str) -> None: | ||
| self.name = name | ||
| self.date_of_birth = date_of_birth | ||
| self.preferred_operating_system = preferred_operating_system | ||
|
|
||
| def is_adult(self) -> bool: | ||
| today = date.today() | ||
| has_had_birthday_this_year = (today.month, today.day) >= ( | ||
| self.date_of_birth.month, | ||
| self.date_of_birth.day, | ||
| ) | ||
| age = today.year - self.date_of_birth.year | ||
| if not has_had_birthday_this_year: | ||
| age -= 1 | ||
| return age >= 18 | ||
|
|
||
|
|
||
| imran = Person("Imran", date(2002, 6, 15), "Ubuntu") | ||
| eliza = Person("Eliza", date(1990, 11, 20), "Arch Linux") | ||
|
|
||
| print(imran.name) | ||
| print(imran.is_adult()) | ||
| print(eliza.name) | ||
| print(eliza.is_adult()) | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,30 @@ | ||
| def open_account(balances: dict[str, int], name: str, amount: int) -> None: | ||
| balances[name] = amount | ||
|
|
||
| def sum_balances(accounts: dict[str, int]) -> int: | ||
| total = 0 | ||
| for name, pence in accounts.items(): | ||
| print(f"{name} had balance {pence}") | ||
| total += pence | ||
| return total | ||
|
|
||
| def format_pence_as_string(total_pence: int) -> str: | ||
| if total_pence < 100: | ||
| return f"{total_pence}p" | ||
| pounds = int(total_pence / 100) | ||
| pence = total_pence % 100 | ||
| return f"£{pounds}.{pence:02d}" | ||
|
|
||
| balances = { | ||
| "Sima": 700, | ||
| "Linn": 545, | ||
| "Georg": 831, | ||
| } | ||
|
|
||
| open_account(balances, "Tobi", 913) | ||
| open_account(balances, "Olya", 713) | ||
|
|
||
| total_pence = sum_balances(balances) | ||
| total_string = format_pence_as_string(total_pence) | ||
|
|
||
| print(f"The bank accounts total {total_string}") |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| from dataclasses import dataclass | ||
| from typing import List | ||
|
|
||
| @dataclass(frozen=True) | ||
| class Person: | ||
| name: str | ||
| age: int | ||
| preferred_operating_systems: List[str] | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class Laptop: | ||
| id: int | ||
| manufacturer: str | ||
| model: str | ||
| screen_size_in_inches: float | ||
| operating_system: str | ||
|
|
||
|
|
||
| def find_possible_laptops(laptops: List[Laptop], person: Person) -> List[Laptop]: | ||
| possible_laptops = [] | ||
| for laptop in laptops: | ||
| if laptop.operating_system in person.preferred_operating_systems: | ||
| possible_laptops.append(laptop) | ||
| return possible_laptops | ||
|
|
||
|
|
||
| people = [ | ||
| Person(name="Imran", age=22, preferred_operating_systems=["Ubuntu", "Arch Linux"]), | ||
| Person(name="Eliza", age=34, preferred_operating_systems=["Arch Linux", "Ubuntu"]), | ||
| ] | ||
|
|
||
| laptops = [ | ||
| Laptop(id=1, manufacturer="Dell", model="XPS", screen_size_in_inches=13, operating_system="Arch Linux"), | ||
| Laptop(id=2, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system="Ubuntu"), | ||
| Laptop(id=3, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system="ubuntu"), | ||
| Laptop(id=4, manufacturer="Apple", model="macBook", screen_size_in_inches=13, operating_system="macOS"), | ||
| ] | ||
|
|
||
| for person in people: | ||
| possible_laptops = find_possible_laptops(laptops, person) | ||
| print(f"Possible laptops for {person.name}: {possible_laptops}") |
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
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.
Good idea to separate out useful helper functions for parsing inputs