|
| 1 | +from dataclasses import dataclass |
| 2 | +from enum import Enum |
| 3 | +import sys |
| 4 | +from typing import List |
| 5 | + |
| 6 | + |
| 7 | +class OperatingSystem(Enum): |
| 8 | + MACOS = "macOS" |
| 9 | + ARCH = "Arch Linux" |
| 10 | + UBUNTU = "Ubuntu" |
| 11 | + |
| 12 | + |
| 13 | +@dataclass(frozen=True) |
| 14 | +class Person: |
| 15 | + name: str |
| 16 | + age: int |
| 17 | + preferred_operating_system: OperatingSystem |
| 18 | + |
| 19 | + |
| 20 | +@dataclass(frozen=True) |
| 21 | +class Laptop: |
| 22 | + id: int |
| 23 | + manufacturer: str |
| 24 | + model: str |
| 25 | + screen_size_in_inches: float |
| 26 | + operating_system: OperatingSystem |
| 27 | + |
| 28 | + |
| 29 | +def find_possible_laptops(laptops: List[Laptop], person: Person) -> List[Laptop]: |
| 30 | + possible_laptops = [] |
| 31 | + for laptop in laptops: |
| 32 | + if laptop.operating_system == person.preferred_operating_system: |
| 33 | + possible_laptops.append(laptop) |
| 34 | + return possible_laptops |
| 35 | + |
| 36 | + |
| 37 | +def parse_age(raw_age: str) -> int: |
| 38 | + age = int(raw_age) |
| 39 | + if age <= 0: |
| 40 | + raise ValueError("Age must be a positive integer") |
| 41 | + return age |
| 42 | + |
| 43 | + |
| 44 | +def parse_operating_system(raw_operating_system: str) -> OperatingSystem: |
| 45 | + normalised_value = raw_operating_system.strip().lower() |
| 46 | + for operating_system in OperatingSystem: |
| 47 | + if normalised_value == operating_system.value.lower() or normalised_value == operating_system.name.lower(): |
| 48 | + return operating_system |
| 49 | + |
| 50 | + valid_values = ", ".join(operating_system.value for operating_system in OperatingSystem) |
| 51 | + raise ValueError(f"Preferred operating system must be one of: {valid_values}") |
| 52 | + |
| 53 | + |
| 54 | +def create_person_from_input() -> Person: |
| 55 | + name = input("Name: ").strip() |
| 56 | + if not name: |
| 57 | + raise ValueError("Name cannot be empty") |
| 58 | + |
| 59 | + raw_age = input("Age: ").strip() |
| 60 | + raw_operating_system = input("Preferred operating system (Ubuntu, Arch Linux, macOS): ").strip() |
| 61 | + |
| 62 | + age = parse_age(raw_age) |
| 63 | + preferred_operating_system = parse_operating_system(raw_operating_system) |
| 64 | + |
| 65 | + return Person(name=name, age=age, preferred_operating_system=preferred_operating_system) |
| 66 | + |
| 67 | + |
| 68 | +def count_laptops_for_operating_system(laptops: List[Laptop], operating_system: OperatingSystem) -> int: |
| 69 | + return sum(1 for laptop in laptops if laptop.operating_system == operating_system) |
| 70 | + |
| 71 | + |
| 72 | +def find_most_available_operating_system(laptops: List[Laptop]) -> OperatingSystem: |
| 73 | + counts = { |
| 74 | + operating_system: count_laptops_for_operating_system(laptops, operating_system) |
| 75 | + for operating_system in OperatingSystem |
| 76 | + } |
| 77 | + return max(counts, key=lambda operating_system: counts[operating_system]) |
| 78 | + |
| 79 | +def main() -> None: |
| 80 | + laptops = [ |
| 81 | + Laptop(id=1, manufacturer="Dell", model="XPS", screen_size_in_inches=13, operating_system=OperatingSystem.ARCH), |
| 82 | + Laptop(id=2, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system=OperatingSystem.UBUNTU), |
| 83 | + Laptop(id=3, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system=OperatingSystem.UBUNTU), |
| 84 | + Laptop(id=4, manufacturer="Apple", model="macBook", screen_size_in_inches=13, operating_system=OperatingSystem.MACOS), |
| 85 | + ] |
| 86 | + |
| 87 | + try: |
| 88 | + person = create_person_from_input() |
| 89 | + except ValueError as error: |
| 90 | + print(error, file=sys.stderr) |
| 91 | + raise SystemExit(1) |
| 92 | + |
| 93 | + possible_laptops = find_possible_laptops(laptops, person) |
| 94 | + preferred_count = len(possible_laptops) |
| 95 | + print(f"The library has {preferred_count} laptop(s) with {person.preferred_operating_system.value}.") |
| 96 | + |
| 97 | + best_operating_system = find_most_available_operating_system(laptops) |
| 98 | + best_count = count_laptops_for_operating_system(laptops, best_operating_system) |
| 99 | + |
| 100 | + if best_operating_system != person.preferred_operating_system and best_count > preferred_count: |
| 101 | + print( |
| 102 | + f"If you're willing to accept {best_operating_system.value}, " |
| 103 | + f"you're more likely to get a laptop ({best_count} available)." |
| 104 | + ) |
| 105 | + |
| 106 | + |
| 107 | +if __name__ == "__main__": |
| 108 | + main() |
0 commit comments