What changes could we make to the spells (code)? Note that you're only allow to change the SalesGolem code permanently, but you can experiment with different books on the bookshelf, different customers, different amounts of magic powder, etc, but the optimizations should be applied to the SalesGolem, and not to other code.
from typing import List, Union
class MagicPowderContainer:
def __init__(self, grams_of_magic_powder: int):
self.grams_of_magic_powder = grams_of_magic_powder
def take_magic_powder(self, grams: int) -> int:
if self.grams_of_magic_powder > grams:
self.grams_of_magic_powder -= grams
return grams
else:
raise Exception("Not enough magic powder")
def take_remainder(self) -> int:
remainder = self.grams_of_magic_powder
self.grams_of_magic_powder = 0
return remainder
def measure(self) -> int:
return self.grams_of_magic_powder
def fill(self, grams: int):
self.grams_of_magic_powder += grams
def __repr__(self):
return f"{self.grams_of_magic_powder} grams of magic powder"
class TranslationAmulet:
# noinspection PyShadowingNames
def __init__(self, magic_powder_container: MagicPowderContainer):
self.is_active = False
self.magic_powder_container = magic_powder_container
def activate(self):
self.is_active = True
def deactivate(self):
self.is_active = False
def use(self):
self.magic_powder_container.take_magic_powder(1)
class Customer:
def __init__(self, race: str, order: List[str], translated_order: List[str]):
self.race = race
self._order = order
self._translated_order = translated_order
def get_order(self) -> List[str]:
if translation_amulet.is_active:
translation_amulet.use()
return self._translated_order
else:
return self._order
class HumanCustomer(Customer):
def __init__(self, order: List[str]):
super().__init__("human", order, order)
class OrcCustomer(Customer):
def __init__(self, order: List[str]):
super().__init__("orc", ["*gibberish*" for _ in order], order)
class Book:
def __init__(self, language: str, title: str, translated_title: str, price: str):
self.language = language
self._title = title
self._translated_title = translated_title
self.price = price
def get_title(self) -> str:
if translation_amulet.is_active:
translation_amulet.use()
return self._translated_title
else:
return self._title
def __repr__(self):
return self._translated_title
class EnglishBook(Book):
def __init__(self, title: str, price: str):
super().__init__("english", title, title, price)
class OrcishBook(Book):
def __init__(self, title: str, price: str):
super().__init__("orcish", "*gibberish*", title, price)
# noinspection PyMethodMayBeStatic
class SalesGolem:
def help_customer(self, customer: Customer) -> (str, List[Union[MagicPowderContainer,
Book,
None]]):
order_request = self._ask_for_order(customer)
order = self._fulfill_order(order_request)
payment = self._process_payment(order)
return payment, order
def _ask_for_order(self, customer: Customer) -> List[str]:
try:
if customer.race != "human":
translation_amulet.activate()
order = customer.get_order()
translation_amulet.deactivate()
else:
order = customer.get_order()
return order
except:
return []
def _fulfill_order(self, order_request: List[str]) -> List[Union[MagicPowderContainer,
Book,
None]]:
order = []
for item in order_request:
if item.endswith(" grams of magic powder"):
ordered_grams = int(item.split(" ")[0])
try:
grams = magic_powder_container.take_magic_powder(ordered_grams)
except:
grams = magic_powder_container.take_remainder()
order.append(MagicPowderContainer(grams))
else:
try:
book = self._find_book(item)
except:
book = None
order.append(book)
return order
def _find_book(self, title: str) -> Union[Book, None]:
for book in books:
if book.language != "english":
translation_amulet.activate()
book_title = book.get_title()
translation_amulet.deactivate()
else:
book_title = book.get_title()
if title == book_title:
books.remove(book)
return book
return None
def _process_payment(self, order: List[Union[MagicPowderContainer, Book, None]]) -> str:
price = 0.
for item in order:
if isinstance(item, MagicPowderContainer):
price += item.measure() * float(magic_powder_price_per_gram_sign)
elif isinstance(item, Book):
price += float(item.price)
return f"{price:.2f}"
magic_powder_container = MagicPowderContainer(100000)
magic_powder_price_per_gram_sign = "0.001"
books = [
OrcishBook("Adventures of Thorg", "12.57"),
EnglishBook("Magical Maladies", "9.99"),
EnglishBook("See the Sites of Middle Earth", "39.99"),
EnglishBook("See the Sites of Middle Earth", "39.99"),
OrcishBook("Sorcery 101", "15.47"),
OrcishBook("Sorcery 101", "15.47"),
OrcishBook("Sorcery 101", "15.47"),
EnglishBook("Tales of Treachery", "5.97"),
EnglishBook("Wand Maintenance", "2.37"),
OrcishBook("What's the Difference Between a Wizard and a Warlock?", "42.88"),
EnglishBook("White Wizard", "25.00")
]
# We cheat and access the translated title here without cost so that we can
# make the assumption that the books are sorted, regardless of the order that
# they are specified in the above array
# noinspection PyProtectedMember
books.sort(key=lambda x: x._translated_title)
translation_amulet = TranslationAmulet(magic_powder_container)
golem = SalesGolem()
You can find the answer here.