1+ import sys
12from dataclasses import dataclass
23from enum import Enum
3- from typing import List
4+ from typing import List , Dict
45
56class OperatingSystem (Enum ):
67 MACOS = "macOS"
@@ -12,7 +13,7 @@ class Person:
1213 name : str
1314 age : int
1415 # Sorted in order of preference, most preferred is first.
15- preferred_operating_system : List [OperatingSystem ]
16+ preferred_operating_systems : List [OperatingSystem ]
1617
1718
1819@dataclass (frozen = True )
@@ -23,5 +24,83 @@ class Laptop:
2324 screen_size_in_inches : float
2425 operating_system : OperatingSystem
2526
27+ # In the prep, there was an exercise around finding possible laptops for a group of people.
2628
27- def allocate_laptops (people : List [Person ], laptops : List [Laptop ]) -> Dict [Person , Laptop ]:
29+ # Your exercise is to extend this to actually allocate laptops to the people.
30+ # Every person should be allocated exactly one laptop.
31+
32+ # If we define “sadness” as the number of places down in someone’s ranking the operating system the ended
33+ # up with (i.e. if your preferences were [UBUNTU, ARCH, MACOS] and you were allocated a MACOS
34+ # machine your sadness would be 2), we want to minimise the total sadness of all people.
35+ # If we allocate someone a laptop with an operating system not in their preferred list,
36+ # treat them as having a sadness of 100.
37+
38+ laptops_list : List [Laptop ] = [
39+ Laptop (id = 1 , manufacturer = "Dell" , model = "XPS" , screen_size_in_inches = 13 , operating_system = OperatingSystem .ARCH ),
40+ Laptop (id = 2 , manufacturer = "Dell" , model = "XPS" , screen_size_in_inches = 15 , operating_system = OperatingSystem .UBUNTU ),
41+ Laptop (id = 3 , manufacturer = "Dell" , model = "XPS" , screen_size_in_inches = 15 , operating_system = OperatingSystem .UBUNTU ),
42+ Laptop (id = 4 , manufacturer = "Apple" , model = "MacBook" , screen_size_in_inches = 13 , operating_system = OperatingSystem .MACOS ),
43+ Laptop (id = 5 , manufacturer = "Apple" , model = "MacBook Air" , screen_size_in_inches = 13 , operating_system = OperatingSystem .MACOS ),
44+ Laptop (id = 6 , manufacturer = "Lenovo" , model = "ThinkPad" , screen_size_in_inches = 14 , operating_system = OperatingSystem .ARCH ),
45+ Laptop (id = 7 , manufacturer = "Asus" , model = "ZenBook" , screen_size_in_inches = 13 , operating_system = OperatingSystem .UBUNTU ),
46+ Laptop (id = 8 , manufacturer = "HP" , model = "Spectre" , screen_size_in_inches = 14 , operating_system = OperatingSystem .MACOS ),
47+ Laptop (id = 9 , manufacturer = "Apple" , model = "MacBook Pro" , screen_size_in_inches = 16 , operating_system = OperatingSystem .MACOS ),
48+ ]
49+
50+ people : List [Person ] = [
51+ Person (name = "Imran" , age = 18 , preferred_operating_systems = [OperatingSystem .UBUNTU , OperatingSystem .ARCH ]),
52+ Person (name = "Eliza" , age = 34 , preferred_operating_systems = [OperatingSystem .ARCH , OperatingSystem .MACOS ]),
53+ Person (name = "Luke" , age = 26 , preferred_operating_systems = [OperatingSystem .MACOS , OperatingSystem .UBUNTU , OperatingSystem .ARCH ]),
54+ Person (name = "Abby" , age = 30 , preferred_operating_systems = [OperatingSystem .MACOS ]),
55+ Person (name = "Ger" , age = 51 , preferred_operating_systems = [OperatingSystem .UBUNTU , OperatingSystem .MACOS ]),
56+ ]
57+
58+ def user_prompt () -> Person :
59+ try :
60+ # strip() whitespace before processing (no need for str type here as input always returns a string)
61+ name = input ("Please enter your first name: " ).strip ()
62+ if not name .isalpha ():
63+ raise ValueError ("Name must contain only alphabetic characters." )
64+
65+ # strip() before converting to integer
66+ age = int (input ("Please enter your age: " ).strip ())
67+ minimum_age = 18
68+ if age < minimum_age :
69+ raise ValueError ("Age must be 18 or over." )
70+
71+
72+ # define valid OS options
73+ valid_os = [os .value for os in OperatingSystem ]
74+
75+ # prompt the user to enter OS preferences in order of preference (no need for str type here)
76+ preferred_os = input (f"Please enter your preferred operating systems in order of preference, separated by commas (e.g., { ', ' .join (valid_os )} ): " ).strip ()
77+
78+ # split and validate the OS
79+ preferred_os_list = [os .strip () for os in preferred_os .split ("," )]
80+ preferred_os_enum = []
81+ for os_name in preferred_os_list :
82+ if os_name not in valid_os :
83+ raise ValueError (f"Invalid operating system: { os_name } " )
84+ # convert to enum
85+ preferred_os_enum .append (OperatingSystem (os_name ))
86+
87+ return Person (name = name , age = age , preferred_operating_systems = preferred_os_enum )
88+
89+ # throw an error and exit for invalid age and os input
90+ except ValueError as error :
91+ print (f"Invalid input: { error } " , file = sys .stderr )
92+ sys .exit (1 )
93+
94+
95+ def find_possible_laptops (available_laptops : List [Laptop ], current_person : Person ) -> List [Laptop ]:
96+ return [
97+ laptop for laptop in available_laptops
98+ if laptop .operating_system in current_person .preferred_operating_systems
99+ ]
100+
101+ # allocated sequentially, in a first come first served order
102+ def allocate_laptops_sequentially (people : List [Person ], laptops : List [Laptop ]) -> Dict [Person , Laptop ]:
103+ """
104+ Allocate laptops to people sequentially based on the order in the people list.
105+ This approach respects the 'wait your turn' principle.
106+ """
0 commit comments