Skip to content
Open
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
81 changes: 81 additions & 0 deletions laptop-allocation.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
from dataclasses import dataclass
from enum import Enum
from typing import List, Dict, Tuple

class OperatingSystem(Enum):
MACOS = "macOS"
ARCH = "Arch Linux"
UBUNTU = "Ubuntu"

@dataclass(frozen=True)
class Person:
name: str
age: int
preferred_operating_systems: Tuple[OperatingSystem, ...]

@dataclass(frozen=True)
class Laptop:
id: int
manufacturer: str
model: str
screen_size_in_inches: float
operating_system: OperatingSystem


# Assign each person the best available laptop according to their preference list
# Minimise sadness locally (not globally optimal, but simple and valid for this exercise)
# If no matching OS is available → they get the “least bad” remaining laptop (sadness = 100)

def sadness(person: Person, laptop: Laptop) -> int:
# Return sadness score for assigning this laptop to this person
if laptop.operating_system in person.preferred_operating_systems:
return person.preferred_operating_systems.index(laptop.operating_system)
return 100


def allocate_laptops(people: List[Person], laptops: List[Laptop]) -> Dict[Person, Laptop]:
if len(people) != len(laptops):
raise ValueError("Number of people must equal number of laptops.")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why does the number of people need to equal the number of laptops?

Copy link
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In this implementation, the number of people must equal the number of laptops because the algorithm assumes a one to one assignment, every person receives exactly one laptop and every laptop is assigned to exactly one person.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I disagree. Everyone needs a laptop, but spare laptops aren't a problem.


# Clone list so we can remove laptops as they are assigned
available_laptops = laptops.copy()

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good spot!


# Creating an empty dictionary
# what the dictionary should contain
allocation: Dict[Person, Laptop] = {}

# stores the single Laptop object that gives the lowest sadness for that person
for person in people:
# Pick the laptop with the minimum sadness for this person
best_laptop = min(
available_laptops, # This is a list of laptops that have not been allocated yet
key=lambda laptop: sadness(person, laptop) # calculates how "sad" the person would be if they got that laptop
) # min() returns the laptop with the smallest sadness value.

# assigns that laptop to the person and removes it from the pool of available laptops
allocation[person] = best_laptop
available_laptops.remove(best_laptop)

return allocation

people = [
Person(name="Imran", age=22, preferred_operating_systems=(OperatingSystem.UBUNTU, OperatingSystem.ARCH)),
Person(name="Eliza", age=34, preferred_operating_systems=(OperatingSystem.ARCH, OperatingSystem.UBUNTU)),
Person(name="Fatma", age=18, preferred_operating_systems=(OperatingSystem.MACOS,)),
]

laptops = [
Laptop(id=1, manufacturer="Dell", model="XPS", screen_size_in_inches=13, operating_system=OperatingSystem.ARCH),
Laptop(id=2, manufacturer="Dell", model="XPS", screen_size_in_inches=15, operating_system=OperatingSystem.UBUNTU),
Laptop(id=3, manufacturer="Apple", model="macBook", screen_size_in_inches=13, operating_system=OperatingSystem.UBUNTU),
]


if __name__ == "__main__":
allocation = allocate_laptops(people, laptops)

print("\nLaptop Allocation Results:\n")
for person, laptop in allocation.items():
sad = sadness(person, laptop)
print(f"{person.name} → Laptop {laptop.id} ({laptop.operating_system.value}) | Sadness = {sad}")