From 0ab1acec3bc4a629f4c5a3129ca8c9d4ff1b4c09 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Mon, 20 Oct 2025 12:34:48 +0100 Subject: [PATCH 1/2] These are the changes i have made on the laptop allocation exercise --- prep exercises/laptop-allocation/laptops.py | 84 +++++++++++++++++++++ 1 file changed, 84 insertions(+) create mode 100644 prep exercises/laptop-allocation/laptops.py diff --git a/prep exercises/laptop-allocation/laptops.py b/prep exercises/laptop-allocation/laptops.py new file mode 100644 index 0000000..4c7b0e8 --- /dev/null +++ b/prep exercises/laptop-allocation/laptops.py @@ -0,0 +1,84 @@ +from dataclasses import dataclass +from enum import Enum +from typing import List + +class OperatingSystem(Enum): + MACOS= "macOS" + ARCH= "Arch Linux" + UBUNTU= "Ubuntu" + WINDOWS = "windows" + +@dataclass(frozen=True) +class Person: + name: str + age: int + preferred_operating_system: OperatingSystem + +@dataclass(frozen=True) +class Laptop: + id: 1 + manufacturer: str + model: str + screen_size_in_inches: float + operating_system: OperatingSystem + +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="Dell", model="XPS", screen_size_in_inches=15, operating_system=OperatingSystem.UBUNTU), + Laptop(id=4, manufacturer="Apple", model="macBook", screen_size_in_inches=13, operating_system=OperatingSystem.MACOS), +] + + +def user_details(): + user_name = input("Please enter your name: ") + user_age = int(input("Please enter your age: ")) + user_preferred_operating_system = input("Now tell us your preferred operating system in capital letters, 'MACOS', 'ARCH', or 'UBUNTU': ") + + os_in_enum = OperatingSystem[user_preferred_operating_system] + + return Person(name=user_name, age=user_age, preferred_operating_system=os_in_enum) + + +user = user_details() + +def find_possible_laptops(laptops): + possible_laptops = [] + + print(user.preferred_operating_system) + + for laptop in laptops: + if user.preferred_operating_system == laptop.operating_system: + possible_laptops.append(laptop) + + return possible_laptops + +def find_most_common_os(laptops: List[Laptop]) -> OperatingSystem: + os_count = {} + + for laptop in laptops: + os = laptop.operating_system + os_count[os] = os_count.get(os, 0) + 1 + + most_common_os = max(os_count.items(), key=lambda x: x[1]) + + return most_common_os[0] + +# find_possible_laptops(laptops) + +def tell_user_outcome(): + possible_laptops = find_possible_laptops(laptops) + most_common_os = find_most_common_os(laptops) + + + if len(possible_laptops) >= 1: + print(f"You're in luck, we have a laptop with your preferred os {user.preferred_operating_system.value}") + + elif any(laptop.operating_system == most_common_os for laptop in possible_laptops): + print(f"You're in luck, we have a laptop with your preferred os {user.preferred_operating_system.value}, we also have laptops operating {most_common_os.value}") + + else: + print(f"Sorry, there are no longer laptops with {user.preferred_operating_system.value} available, but we are in position to lend you one with {most_common_os.value}") + + +tell_user_outcome() \ No newline at end of file From b43686e789981c3ceb891d6955aec30a89179687 Mon Sep 17 00:00:00 2001 From: Gabriel Date: Tue, 10 Mar 2026 16:44:35 +0000 Subject: [PATCH 2/2] This is the implementation of laptops to multiple people --- prep exercises/laptop-allocation/laptops.py | 103 +++++++++----------- 1 file changed, 48 insertions(+), 55 deletions(-) diff --git a/prep exercises/laptop-allocation/laptops.py b/prep exercises/laptop-allocation/laptops.py index 4c7b0e8..0b0b635 100644 --- a/prep exercises/laptop-allocation/laptops.py +++ b/prep exercises/laptop-allocation/laptops.py @@ -1,84 +1,77 @@ from dataclasses import dataclass from enum import Enum -from typing import List +from functools import lru_cache +from typing import Dict, List, Tuple class OperatingSystem(Enum): - MACOS= "macOS" - ARCH= "Arch Linux" - UBUNTU= "Ubuntu" + MACOS = "macOS" + ARCH = "Arch Linux" + UBUNTU = "Ubuntu" WINDOWS = "windows" @dataclass(frozen=True) class Person: name: str age: int - preferred_operating_system: OperatingSystem + preferred_operating_systems: Tuple[OperatingSystem, ...] + + def __post_init__(self) -> None: + object.__setattr__( + self, + "preferred_operating_systems", + tuple(self.preferred_operating_systems), + ) @dataclass(frozen=True) class Laptop: - id: 1 + id: int manufacturer: str model: str screen_size_in_inches: float operating_system: OperatingSystem -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="Dell", model="XPS", screen_size_in_inches=15, operating_system=OperatingSystem.UBUNTU), - Laptop(id=4, manufacturer="Apple", model="macBook", screen_size_in_inches=13, operating_system=OperatingSystem.MACOS), -] - - -def user_details(): - user_name = input("Please enter your name: ") - user_age = int(input("Please enter your age: ")) - user_preferred_operating_system = input("Now tell us your preferred operating system in capital letters, 'MACOS', 'ARCH', or 'UBUNTU': ") - - os_in_enum = OperatingSystem[user_preferred_operating_system] - - return Person(name=user_name, age=user_age, preferred_operating_system=os_in_enum) - - -user = user_details() - -def find_possible_laptops(laptops): - possible_laptops = [] - - print(user.preferred_operating_system) - - for laptop in laptops: - if user.preferred_operating_system == laptop.operating_system: - possible_laptops.append(laptop) +def sadness_for_allocation(person: Person, laptop: Laptop) -> int: + try: + return person.preferred_operating_systems.index(laptop.operating_system) + except ValueError: + return 100 - return possible_laptops -def find_most_common_os(laptops: List[Laptop]) -> OperatingSystem: - os_count = {} - - for laptop in laptops: - os = laptop.operating_system - os_count[os] = os_count.get(os, 0) + 1 +def allocate_laptops(people: List[Person], laptops: List[Laptop]) -> Dict[Person, Laptop]: + if len(laptops) < len(people): + raise ValueError("Not enough laptops to allocate exactly one per person") - most_common_os = max(os_count.items(), key=lambda x: x[1]) + people_tuple: Tuple[Person, ...] = tuple(people) + laptops_tuple: Tuple[Laptop, ...] = tuple(laptops) - return most_common_os[0] + @lru_cache(maxsize=None) + def best_from(person_index: int, used_mask: int) -> Tuple[int, Tuple[int, ...]]: + if person_index == len(people_tuple): + return 0, tuple() -# find_possible_laptops(laptops) + best_total_sadness = float("inf") + best_choice: Tuple[int, ...] = tuple() -def tell_user_outcome(): - possible_laptops = find_possible_laptops(laptops) - most_common_os = find_most_common_os(laptops) + for laptop_index, laptop in enumerate(laptops_tuple): + if used_mask & (1 << laptop_index): + continue + current_sadness = sadness_for_allocation(people_tuple[person_index], laptop) + remaining_sadness, remaining_choices = best_from( + person_index + 1, + used_mask | (1 << laptop_index), + ) + candidate_total = current_sadness + remaining_sadness - if len(possible_laptops) >= 1: - print(f"You're in luck, we have a laptop with your preferred os {user.preferred_operating_system.value}") - - elif any(laptop.operating_system == most_common_os for laptop in possible_laptops): - print(f"You're in luck, we have a laptop with your preferred os {user.preferred_operating_system.value}, we also have laptops operating {most_common_os.value}") + if candidate_total < best_total_sadness: + best_total_sadness = candidate_total + best_choice = (laptop_index,) + remaining_choices - else: - print(f"Sorry, there are no longer laptops with {user.preferred_operating_system.value} available, but we are in position to lend you one with {most_common_os.value}") + return best_total_sadness, best_choice + _, selected_laptop_indexes = best_from(0, 0) -tell_user_outcome() \ No newline at end of file + return { + person: laptops_tuple[laptop_index] + for person, laptop_index in zip(people_tuple, selected_laptop_indexes) + } \ No newline at end of file