1+ from dataclasses import dataclass , field
2+ from enum import Enum
3+ from typing import Dict , List
4+
5+ class OperatingSystem (Enum ):
6+ MACOS = "macOS"
7+ ARCH = "Arch Linux"
8+ UBUNTU = "Ubuntu"
9+
10+ @dataclass (frozen = True )
11+ class Person :
12+ name : str
13+ age : int
14+ # Sorted in order of preference, most preferred is first.
15+ preferred_operating_system : List [OperatingSystem ]
16+
17+ def __hash__ (self ):
18+ return hash ((self .name , self .age ))
19+
20+
21+ @dataclass (frozen = True )
22+ class Laptop :
23+ id : int
24+ manufacturer : str
25+ model : str
26+ screen_size_in_inches : float
27+ operating_system : OperatingSystem
28+
29+ def allocate_laptops (people : List [Person ], laptops : List [Laptop ]) -> Dict [Person , Laptop ]:
30+ if len (people ) > len (laptops ):
31+ raise Exception ("Sorry, there are not enough laptops." )
32+ alloc_dict = {}
33+ # people with fewer options choose first, because they potentially can generate most sadness
34+ people .sort (key = lambda person : len (person .preferred_operating_system ))
35+ for person in people :
36+ for laptop in laptops :
37+ is_match = False
38+ # if it a last chance to get a laptop, it used anyway
39+ if laptops .index (laptop ) == len (laptops ) - 1 :
40+ alloc_dict [person ] = laptop
41+ break
42+ for sys in person .preferred_operating_system :
43+ if sys == laptop .operating_system :
44+ alloc_dict [person ] = laptop
45+ laptops .pop (laptops .index (laptop ))
46+ is_match = True
47+ break
48+ if is_match :
49+ break
50+ return alloc_dict
51+
52+ def calcSadness (person : Person , laptop : Laptop ) -> int :
53+ sadness = 0
54+ is_sys_matched = False
55+ for i in range (len (person .preferred_operating_system )):
56+ if person .preferred_operating_system [i ] == laptop .operating_system :
57+ is_sys_matched = True
58+ sadness += i
59+ break
60+ if not is_sys_matched :
61+ sadness = 100
62+ return sadness
63+
64+ def print_allocation (alloc_dict : Dict [Person , Laptop ]) -> None :
65+ for person in alloc_dict .keys ():
66+ print (f"{ person .name } gets: { alloc_dict [person ].model } with { alloc_dict [person ].operating_system .name } ." )
67+
68+ def main () -> None :
69+ people_five = [
70+ Person (name = "Alice" , age = 28 ,
71+ preferred_operating_system = [OperatingSystem .MACOS , OperatingSystem .UBUNTU ]),
72+ Person (name = "Bob" , age = 34 ,
73+ preferred_operating_system = [OperatingSystem .ARCH ]),
74+ Person (name = "Charlie" , age = 22 ,
75+ preferred_operating_system = [OperatingSystem .ARCH , OperatingSystem .UBUNTU , OperatingSystem .MACOS ]),
76+ Person ( name = "Dana" , age = 41 ,
77+ preferred_operating_system = [OperatingSystem .MACOS ]),
78+ Person (name = "Eli" , age = 25 ,
79+ preferred_operating_system = [OperatingSystem .ARCH , OperatingSystem .MACOS ])
80+ ]
81+ laptops_five = [
82+ Laptop (id = 1 , manufacturer = "Apple" , model = "MacBook Pro 14" , screen_size_in_inches = 14.2 , operating_system = OperatingSystem .MACOS ),
83+ Laptop (id = 2 , manufacturer = "Framework" , model = "Laptop 13" , screen_size_in_inches = 13.5 , operating_system = OperatingSystem .ARCH ),
84+ Laptop (id = 3 , manufacturer = "Dell" , model = "XPS 13 Developer Edition" , screen_size_in_inches = 13.4 , operating_system = OperatingSystem .UBUNTU ),
85+ Laptop (id = 4 , manufacturer = "Apple" , model = "MacBook Air" , screen_size_in_inches = 13.6 , operating_system = OperatingSystem .MACOS ),
86+ Laptop (id = 5 , manufacturer = "Lenovo" , model = "ThinkPad X1 Carbon" , screen_size_in_inches = 14.0 , operating_system = OperatingSystem .ARCH )
87+ ]
88+ people_ten = [
89+ Person (name = "Alice" , age = 28 ,
90+ preferred_operating_system = [OperatingSystem .MACOS , OperatingSystem .UBUNTU ]),
91+ Person (name = "Bob" , age = 34 ,
92+ preferred_operating_system = [OperatingSystem .ARCH ]),
93+ Person (name = "Charlie" , age = 22 ,
94+ preferred_operating_system = [OperatingSystem .ARCH , OperatingSystem .UBUNTU , OperatingSystem .MACOS ]),
95+ Person ( name = "Dana" , age = 41 ,
96+ preferred_operating_system = [OperatingSystem .MACOS ]),
97+ Person (name = "Eli" , age = 25 ,
98+ preferred_operating_system = [OperatingSystem .ARCH , OperatingSystem .MACOS ]),
99+ Person (name = "Fiona" , age = 30 ,
100+ preferred_operating_system = [OperatingSystem .UBUNTU , OperatingSystem .ARCH ]),
101+ Person (name = "George" , age = 27 ,
102+ preferred_operating_system = [OperatingSystem .MACOS , OperatingSystem .ARCH ]),
103+ Person (name = "Hannah" , age = 29 ,
104+ preferred_operating_system = [OperatingSystem .ARCH ]),
105+ Person (name = "Ian" , age = 38 ,
106+ preferred_operating_system = [OperatingSystem .MACOS , OperatingSystem .UBUNTU ]),
107+ Person (name = "Julia" , age = 24 ,
108+ preferred_operating_system = [OperatingSystem .ARCH , OperatingSystem .UBUNTU ])
109+ ]
110+ laptops_ten = [
111+ Laptop (id = 1 , manufacturer = "Apple" , model = "MacBook Pro 14" , screen_size_in_inches = 14.2 , operating_system = OperatingSystem .MACOS ),
112+ Laptop (id = 2 , manufacturer = "Framework" , model = "Laptop 13" , screen_size_in_inches = 13.5 , operating_system = OperatingSystem .ARCH ),
113+ Laptop (id = 3 , manufacturer = "Dell" , model = "XPS 13 Developer Edition" , screen_size_in_inches = 13.4 , operating_system = OperatingSystem .UBUNTU ),
114+ Laptop (id = 4 , manufacturer = "Apple" , model = "MacBook Air" , screen_size_in_inches = 13.6 , operating_system = OperatingSystem .MACOS ),
115+ Laptop (id = 5 , manufacturer = "Lenovo" , model = "ThinkPad X1 Carbon" , screen_size_in_inches = 14.0 , operating_system = OperatingSystem .ARCH ),
116+ Laptop (id = 6 , manufacturer = "System76" , model = "Lemur Pro" , screen_size_in_inches = 14.1 , operating_system = OperatingSystem .UBUNTU ),
117+ Laptop (id = 7 , manufacturer = "Apple" , model = "MacBook Pro 16" , screen_size_in_inches = 16.2 , operating_system = OperatingSystem .MACOS ),
118+ Laptop (id = 8 , manufacturer = "Razer" , model = "Blade 14" , screen_size_in_inches = 14.0 , operating_system = OperatingSystem .ARCH ),
119+ Laptop (id = 9 , manufacturer = "HP" , model = "Dev One" , screen_size_in_inches = 14.0 , operating_system = OperatingSystem .UBUNTU ),
120+ Laptop (id = 10 , manufacturer = "ASUS" , model = "ROG Zephyrus G14" , screen_size_in_inches = 14.0 , operating_system = OperatingSystem .ARCH )
121+ ]
122+ laptops_twenty = [
123+ Laptop (1 , "Apple" , "MacBook Pro 14" , 14.2 , OperatingSystem .MACOS ),
124+ Laptop (2 , "Framework" , "Laptop 13" , 13.5 , OperatingSystem .ARCH ),
125+ Laptop (3 , "Dell" , "XPS 13" , 13.4 , OperatingSystem .UBUNTU ),
126+ Laptop (4 , "Apple" , "MacBook Air M3" , 13.6 , OperatingSystem .MACOS ),
127+ Laptop (5 , "Lenovo" , "ThinkPad X1 Carbon" , 14.0 , OperatingSystem .ARCH ),
128+ Laptop (6 , "System76" , "Lemur Pro" , 14.1 , OperatingSystem .UBUNTU ),
129+ Laptop (7 , "Apple" , "MacBook Pro 16" , 16.2 , OperatingSystem .MACOS ),
130+ Laptop (8 , "Razer" , "Blade 14" , 14.0 , OperatingSystem .ARCH ),
131+ Laptop (9 , "HP" , "Dev One" , 14.0 , OperatingSystem .UBUNTU ),
132+ Laptop (10 , "ASUS" , "ROG Zephyrus G14" , 14.0 , OperatingSystem .ARCH ),
133+ Laptop (11 , "Apple" , "MacBook Air M2" , 15.3 , OperatingSystem .MACOS ),
134+ Laptop (12 , "Star Labs" , "StarBook" , 14.0 , OperatingSystem .ARCH ),
135+ Laptop (13 , "Lenovo" , "ThinkPad P16" , 16.0 , OperatingSystem .UBUNTU ),
136+ Laptop (14 , "Microsoft" , "Surface Laptop (Linux Mod)" , 13.5 , OperatingSystem .ARCH ),
137+ Laptop (15 , "Apple" , "MacBook Pro 13" , 13.3 , OperatingSystem .MACOS ),
138+ Laptop (16 , "Framework" , "Laptop 16" , 16.0 , OperatingSystem .ARCH ),
139+ Laptop (17 , "Dell" , "Precision 5570" , 15.6 , OperatingSystem .UBUNTU ),
140+ Laptop (18 , "System76" , "Pangolin" , 15.6 , OperatingSystem .UBUNTU ),
141+ Laptop (19 , "Apple" , "MacBook Air" , 13.3 , OperatingSystem .MACOS ),
142+ Laptop (20 , "Tuxedo" , "InfinityBook Pro" , 14.0 , OperatingSystem .ARCH )
143+ ]
144+ people_twenty = [
145+ Person ("Alice" , 25 , [OperatingSystem .ARCH ]),
146+ Person ("Bob" , 32 , [OperatingSystem .MACOS , OperatingSystem .UBUNTU ]),
147+ Person ("Charlie" , 19 , [OperatingSystem .ARCH , OperatingSystem .UBUNTU ]),
148+ Person ("Diana" , 45 , [OperatingSystem .MACOS ]),
149+ Person ("Edward" , 28 , [OperatingSystem .ARCH , OperatingSystem .MACOS , OperatingSystem .UBUNTU ]),
150+ Person ("Fiona" , 31 , [OperatingSystem .UBUNTU , OperatingSystem .ARCH ]),
151+ Person ("George" , 27 , [OperatingSystem .ARCH ]),
152+ Person ("Hannah" , 22 , [OperatingSystem .MACOS , OperatingSystem .ARCH ]),
153+ Person ("Ian" , 35 , [OperatingSystem .MACOS ]),
154+ Person ("Julia" , 29 , [OperatingSystem .ARCH , OperatingSystem .MACOS ]),
155+ Person ("Kevin" , 24 , [OperatingSystem .ARCH ]),
156+ Person ("Laura" , 33 , [OperatingSystem .MACOS , OperatingSystem .UBUNTU ]),
157+ Person ("Mason" , 26 , [OperatingSystem .ARCH , OperatingSystem .UBUNTU , OperatingSystem .MACOS ]),
158+ Person ("Nora" , 40 , [OperatingSystem .MACOS ]),
159+ Person ("Oliver" , 21 , [OperatingSystem .ARCH ]),
160+ Person ("Paige" , 30 , [OperatingSystem .UBUNTU ]),
161+ Person ("Quinn" , 23 , [OperatingSystem .ARCH , OperatingSystem .MACOS ]),
162+ Person ("Riley" , 38 , [OperatingSystem .MACOS , OperatingSystem .UBUNTU ]),
163+ Person ("Sam" , 25 , [OperatingSystem .ARCH ]),
164+ Person ("Tina" , 29 , [OperatingSystem .MACOS , OperatingSystem .ARCH ])
165+ ]
166+ # inside allocation function .pop() function is used when laptop selected -
167+ # so copy of original list is passed to avoid mutation
168+ result_dict_5 = allocate_laptops (people = people_five , laptops = laptops_five .copy ())
169+ result_dict_10 = allocate_laptops (people = people_ten , laptops = laptops_ten .copy ())
170+ result_dict_20 = allocate_laptops (people = people_twenty , laptops = laptops_twenty .copy ())
171+ print ("####################################result for 5 people and 5 laptops#####################################" )
172+ print_allocation (alloc_dict = result_dict_5 )
173+ sadness_5 = 0
174+ for person in result_dict_5 .keys ():
175+ sadness_5 += calcSadness (person , result_dict_5 [person ])
176+ print (f"Total sadness: { sadness_5 } " )
177+ print ("###################################result for 10 people and 10 laptops####################################" )
178+ print_allocation (alloc_dict = result_dict_10 )
179+ sadness_10 = 0
180+ for person in result_dict_10 .keys ():
181+ sadness_10 += calcSadness (person , result_dict_10 [person ])
182+ print (f"Total sadness: { sadness_10 } " )
183+ print ("###################################result for 20 people and 20 laptops####################################" )
184+ print_allocation (alloc_dict = result_dict_20 )
185+ sadness_20 = 0
186+ for person in result_dict_20 .keys ():
187+ sadness_20 += calcSadness (person , result_dict_20 [person ])
188+ print (f"Total sadness: { sadness_20 } " )
189+
190+ if __name__ == "__main__" :
191+ main ()
0 commit comments