|
| 1 | +# --- Exercise --- |
| 2 | +# Write a program which: |
| 3 | + |
| 4 | +# 1. Already has a list of Laptops that a library has to lend out. |
| 5 | +# 2. Accepts user input to create a new Person - it should use the input function to read a person’s name, age, and preferred operating system. |
| 6 | +# 3. Tells the user how many laptops the library has that have that operating system. |
| 7 | +# 4. If there is an operating system that has more laptops available, tells the user that if they’re willing to accept that operating system they’re more likely to get a laptop. |
| 8 | + |
| 9 | +# You should convert the age and preferred operating system input from the user into more constrained types as quickly as possible, and should output errors to stderr and terminate the program with a non-zero exit code if the user input bad values. |
| 10 | + |
| 11 | +# --- Solution --- |
| 12 | +from dataclasses import dataclass |
| 13 | +from enum import Enum |
| 14 | +from typing import List |
| 15 | +import sys |
| 16 | + |
| 17 | + |
| 18 | +class OperatingSystem(Enum): |
| 19 | + MACOS = "macOS" |
| 20 | + ARCH = "Arch Linux" |
| 21 | + UBUNTU = "Ubuntu" |
| 22 | + |
| 23 | + |
| 24 | +@dataclass(frozen=True) |
| 25 | +class Person: |
| 26 | + name: str |
| 27 | + age: int |
| 28 | + preferred_operating_system: OperatingSystem |
| 29 | + |
| 30 | + |
| 31 | +@dataclass(frozen=True) |
| 32 | +class Laptop: |
| 33 | + id: int |
| 34 | + manufacturer: str |
| 35 | + model: str |
| 36 | + screen_size_in_inches: float |
| 37 | + operating_system: OperatingSystem |
| 38 | + |
| 39 | + |
| 40 | +def find_possible_laptops(laptops: List[Laptop], person: Person) -> List[Laptop]: |
| 41 | + return [ |
| 42 | + laptop |
| 43 | + for laptop in laptops |
| 44 | + if laptop.operating_system == person.preferred_operating_system |
| 45 | + ] |
| 46 | + |
| 47 | + |
| 48 | +def read_person_from_input() -> Person: |
| 49 | + try: |
| 50 | + name = input("Enter name: ").strip() |
| 51 | + if not name: |
| 52 | + raise ValueError("Name cannot be empty") |
| 53 | + |
| 54 | + age_input = input("Enter age: ").strip() |
| 55 | + age = int(age_input) |
| 56 | + if age < 0: |
| 57 | + raise ValueError("Age must be non-negative") |
| 58 | + |
| 59 | + os_input = input( |
| 60 | + "Enter preferred operating system (macOS, Arch Linux, Ubuntu): " |
| 61 | + ).strip() |
| 62 | + |
| 63 | + preferred_os = OperatingSystem(os_input) |
| 64 | + |
| 65 | + return Person( |
| 66 | + name=name, |
| 67 | + age=age, |
| 68 | + preferred_operating_system=preferred_os, |
| 69 | + ) |
| 70 | + |
| 71 | + except ValueError as e: |
| 72 | + print(f"Error: {e}", file=sys.stderr) |
| 73 | + sys.exit(1) |
| 74 | + |
| 75 | + |
| 76 | +LAPTOPS: List[Laptop] = [ |
| 77 | + Laptop(id=1, manufacturer="Dell", model="XPS", screen_size_in_inches=13, operating_system=OperatingSystem.ARCH), |
| 78 | + Laptop(id=2, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system=OperatingSystem.UBUNTU), |
| 79 | + Laptop(id=3, manufacturer="Lenovo", model="T14 G6", screen_size_in_inches=14, operating_system=OperatingSystem.UBUNTU), |
| 80 | + Laptop(id=4, manufacturer="Apple", model="MacBook Air", screen_size_in_inches=13, operating_system=OperatingSystem.MACOS), |
| 81 | + Laptop(id=5, manufacturer="Lenovo", model="X1 Carbon", screen_size_in_inches=13, operating_system=OperatingSystem.ARCH), |
| 82 | + Laptop(id=6, manufacturer="HP", model="Pavilion", screen_size_in_inches=16, operating_system=OperatingSystem.UBUNTU), |
| 83 | + Laptop(id=7, manufacturer="ASUS", model="ExpertBook B1", screen_size_in_inches=14, operating_system=OperatingSystem.ARCH), |
| 84 | + Laptop(id=8, manufacturer="Apple", model="MacBook Pro", screen_size_in_inches=14, operating_system=OperatingSystem.MACOS), |
| 85 | +] |
| 86 | + |
| 87 | + |
| 88 | +def main() -> None: |
| 89 | + person = read_person_from_input() |
| 90 | + |
| 91 | + matching_laptops = find_possible_laptops(LAPTOPS, person) |
| 92 | + print( |
| 93 | + f"\nNumber of laptops available with " |
| 94 | + f"{person.preferred_operating_system.value}: " |
| 95 | + f"{len(matching_laptops)}" |
| 96 | + ) |
| 97 | + |
| 98 | + laptops_per_os: dict[OperatingSystem, int] = {} |
| 99 | + for laptop in LAPTOPS: |
| 100 | + laptops_per_os[laptop.operating_system] = ( |
| 101 | + laptops_per_os.get(laptop.operating_system, 0) + 1 |
| 102 | + ) |
| 103 | + |
| 104 | + most_available_os = max( |
| 105 | + laptops_per_os.items(), |
| 106 | + key=lambda item: item[1], |
| 107 | + )[0] |
| 108 | + |
| 109 | + if most_available_os != person.preferred_operating_system: |
| 110 | + print( |
| 111 | + f"If you're willing to accept {most_available_os.value}, " |
| 112 | + "you're more likely to get a laptop." |
| 113 | + ) |
| 114 | + |
| 115 | + |
| 116 | +if __name__ == "__main__": |
| 117 | + main() |
0 commit comments