-
-
Notifications
You must be signed in to change notification settings - Fork 42
Sheffield | 25-SDC-Nov | Hassan Osman | Sprint 5 | Implement Laptop Allocation #294
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
d40d30e
5856dd0
a7f4634
3b84ade
8366a7a
78ff572
18106de
2405f09
fc69d05
9ffb839
658bbdb
73156dd
f599d9b
f39df4a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,42 @@ | ||
| In the prep, there was an exercise around finding possible laptops for a group of people. | ||
|
|
||
| Your exercise is to extend this to actually allocate laptops to the people. | ||
|
|
||
| Given these class definitions: | ||
|
|
||
| from dataclasses import dataclass | ||
| from enum import Enum | ||
| from typing import List | ||
|
|
||
| class OperatingSystem(Enum): | ||
| MACOS = "macOS" | ||
| ARCH = "Arch Linux" | ||
| UBUNTU = "Ubuntu" | ||
|
|
||
| @dataclass(frozen=True) | ||
| class Person: | ||
| name: str | ||
| age: int | ||
| # Sorted in order of preference, most preferred is first. | ||
| preferred_operating_system: List[OperatingSystem] | ||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class Laptop: | ||
| id: int | ||
| manufacturer: str | ||
| model: str | ||
| screen_size_in_inches: float | ||
| operating_system: OperatingSystem | ||
| Write a function with this signature: | ||
|
|
||
| def allocate_laptops(people: List[Person], laptops: List[Laptop]) -> Dict[Person, Laptop]: | ||
| Every person should be allocated exactly one laptop. | ||
|
|
||
| If we define "sadness" as the number of places down in someone's ranking the operating system the ended up with (i.e. if your preferences were [UBUNTU, ARCH, MACOS] and you were allocated a MACOS machine your sadness would be 2), we want to minimise the total sadness of all people. If we allocate someone a laptop with an operating system not in their preferred list, treat them as having a sadness of 100. | ||
|
|
||
| Maximum time in hours | ||
| 3 | ||
|
|
||
| How to submit | ||
| Submit a PR to this repo containing your function (and any supporting code). | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| from dataclasses import dataclass | ||
| from enum import Enum | ||
| from typing import List, Dict | ||
| from itertools import permutations | ||
|
|
||
|
|
||
| class OperatingSystem(Enum): | ||
| MACOS = "macOS" | ||
| ARCH = "Arch Linux" | ||
| UBUNTU = "Ubuntu" | ||
|
|
||
| @dataclass(frozen=True) | ||
| class Person: | ||
| name: str | ||
| age: int | ||
| # Sorted in order of preference, most preferred is first. | ||
| preferred_operating_system: List[OperatingSystem] | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. As a general naming tip, if you have something which is a list or an array, give it a plural name. So preferred_operating_systems in this case. Helps the reader understand the use of the code |
||
|
|
||
|
|
||
| @dataclass(frozen=True) | ||
| class Laptop: | ||
| id: int | ||
| manufacturer: str | ||
| model: str | ||
| screen_size_in_inches: float | ||
| operating_system: OperatingSystem | ||
|
|
||
|
|
||
| def sadness(person: Person, laptop: Laptop) ->int: | ||
| try: | ||
| return person.preferred_operating_system.index(laptop.operating_system) | ||
| except ValueError: | ||
| return 100 | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I like the way you have separated this into a separate function, that's good. However it's bad practice to use exceptions in "normal" code execution, as they are very expensive in terms of processing time. They're great for error handling and have particular strengths there. On the next Saturday session, whether it's me or someone else, ask whoever's running it to talk about when using exceptions is a good or a bad idea, it would be a good discussion for the wider group to take part in. How would you implement this function without try/except? |
||
|
|
||
|
|
||
| def allocate_laptops(people: List[Person], laptops: List[Laptop]) -> Dict[Person, Laptop]: | ||
|
|
||
| best_scenario_assignment = None | ||
| best_total_sadness = float("inf") | ||
|
|
||
| for scenario in permutations(laptops): | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Wow! OK, if you've got 5 laptops you're looking at 120 possibilities here, that's manageable. How else could you do this? |
||
| total_sadness = 0 | ||
|
|
||
| #find the sadness level for each scenario | ||
| for person, laptop in zip(people, scenario): | ||
| total_sadness += sadness(person, laptop) | ||
|
|
||
| #Check if this is the best scenario so far | ||
| if total_sadness < best_total_sadness: | ||
| best_total_sadness = total_sadness | ||
| best_scenario_assignment = scenario | ||
|
|
||
| # Convert best_scenario_assignment into Dict[Person, Laptop] | ||
| return {person: laptop for person, laptop in zip(people, best_scenario_assignment)} | ||
|
|
||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Including the problem statement as a readme really helps me as a reviewer, so I don't have to go and find it. Thanks!