Skip to content

Commit 7b7aafa

Browse files
committed
Refactor: eliminate redundant loops & total sadness calculation into single loop
1 parent 9c62e05 commit 7b7aafa

1 file changed

Lines changed: 30 additions & 20 deletions

File tree

prep-exercises/laptop_allocation.py

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -44,33 +44,41 @@ def allocate_laptops(people: List[Person], laptops: List[Laptop]) -> Dict[Person
4444
if len(people) != len(laptops):
4545
raise ValueError("Number of people must equal number of laptops")
4646

47-
# Greedy approach: Sort people by how limited their good options are
48-
# Then allocate their best available choice
4947
allocation: Dict[Person, Laptop] = {}
50-
available_laptops = list(laptops)
48+
available_laptops = set(laptops) # Use set for O(1) lookup and removal
5149

52-
# Create a priority queue of (person, laptop, sadness) tuples
53-
# Sort by sadness to allocate best matches first
54-
preferences = []
55-
for person in people:
50+
# Helper to find best available laptop for a person
51+
def find_best_available(person: Person) -> tuple[Laptop, int] | None:
52+
"""Returns (best_laptop, sadness) or None if no laptops available."""
53+
best_laptop = None
54+
best_sadness = float('inf')
55+
5656
for laptop in available_laptops:
5757
sadness = calculate_sadness(person, laptop)
58-
preferences.append((sadness, person, laptop))
58+
if sadness < best_sadness:
59+
best_sadness = sadness
60+
best_laptop = laptop
61+
# Early exit if we found a perfect match (sadness 0)
62+
if sadness == 0:
63+
break
64+
65+
return (best_laptop, best_sadness) if best_laptop else None
5966

60-
preferences.sort(key=lambda x: x[0])
67+
# Sort people by how limited their good options are
68+
# (by counting how many laptops match their preferences - less matches = higher priority)
69+
def count_good_matches(person: Person) -> int:
70+
"""Count how many laptops have sadness < 100 (i.e., OS is in their preferences)."""
71+
return sum(1 for laptop in laptops if calculate_sadness(person, laptop) < 100)
6172

62-
# Greedy allocation: try to give everyone their best available choice
63-
allocated_people = []
64-
allocated_laptops = []
73+
sorted_people = sorted(people, key=count_good_matches)
6574

66-
for sadness, person, laptop in preferences:
67-
if person not in allocated_people and laptop not in allocated_laptops:
75+
# Greedy allocation: for each person, find their best available laptop
76+
for person in sorted_people:
77+
result = find_best_available(person)
78+
if result:
79+
laptop, _ = result
6880
allocation[person] = laptop
69-
allocated_people.append(person)
70-
allocated_laptops.append(laptop)
71-
72-
if len(allocation) == len(people):
73-
break
81+
available_laptops.remove(laptop) # O(1) removal
7482

7583
return allocation
7684

@@ -96,9 +104,11 @@ def calculate_total_sadness(allocation: Dict[Person, Laptop]) -> int:
96104
allocation = allocate_laptops(people, laptops)
97105

98106
print("Laptop Allocation:")
107+
total_sadness = 0
99108
for person, laptop in allocation.items():
100109
sadness = calculate_sadness(person, laptop)
110+
total_sadness += sadness
101111
print(f"{person.name} -> {laptop.manufacturer} {laptop.model} ({laptop.operating_system.value}) - Sadness: {sadness}")
102112

103-
print(f"\nTotal Sadness: {calculate_total_sadness(allocation)}")
113+
print(f"\nTotal Sadness: {total_sadness}")
104114

0 commit comments

Comments
 (0)