Домашни > Another brick in the wall > Решения > Решението на Оля Иванова

Резултати
7 точки от тестове
1 точки от учител

8 точки общо

7 успешни теста
3 неуспешни теста
Код
Скрий всички коментари

  1class Material:
  2    def __init__(self, mass: int):
  3        self.mass = mass
  4
  5    @property
  6    def volume(self):
  7        return self.mass / self.density
  8
  9
 10class Concrete(Material):
 11    density = 2500 
 12
 13
 14class Brick(Material):
 15    density = 2000  
 16
 17
 18class Stone(Material):
 19    density = 1600  
 20
 21
 22class Wood(Material):
 23    density = 600  
 24
 25
 26class Steel(Material):
 27    density = 7700
 28    
 29
 30class Factory:
 31    all_factories = []
 32    used_instances = []
 33
 34    dynamic_classes = {
 35        "Concrete": Concrete, 
 36        "Brick": Brick, 
 37        "Stone": Stone, 
 38        "Wood": Wood, 
 39        "Steel": Steel
 40    }
 41
 42    def __init__(self):
 43        self.created_instances = []
 44        Factory.all_factories.append(self)
 45
 46    def __call__(self, *args, **kwargs):
 47        if args and kwargs:
 48            raise ValueError("Cannot mix positional and keyword arguments.")
 49        if not args and not kwargs:
 50            raise ValueError("Factory requires arguments.")
 51
 52        if kwargs:
 53            return self._create_named_materials(**kwargs)
 54        return self._create_alloy(*args)
 55
 56    def _create_named_materials(self, **kwargs):
 57        results = []
 58        for name, mass in kwargs.items():
 59            cls = globals().get(name)
 60            if cls is None or not issubclass(cls, Material):
 61                raise ValueError(f"Invalid material name: {name}")
 62            
 63            instance = cls(mass)
 64            self.created_instances.append(instance)
 65            results.append(instance)
 66            
 67        return tuple(results)
 68
 69    def _create_alloy(self, *args):
 70        for instance in args:
 71            if instance in self.used_instances:
 72                raise AssertionError("This material instance has already been used.")
 73            self.used_instances.append(instance)
 74
 75        materials = []
 76        for base in args:
 77            arr = type(base).__name__.split("_")
 78            materials.extend(arr)
 79
 80        base_classes = sorted(set(self.dynamic_classes[material] for material in materials), key=lambda cls: cls.__name__)
 81        class_name = "_".join(base.__name__ for base in base_classes)
 82        
 83        if class_name not in self.dynamic_classes:
 84            density = sum(cls.density for cls in base_classes) / len(base_classes)
 85            new_class = type(
 86                class_name,
 87                (Material,),
 88                {"density": density}
 89            )
 90            self.dynamic_classes[class_name] = new_class
 91
 92        total_mass = sum(instance.mass for instance in args)
 93        new_instance = self.dynamic_classes[class_name](total_mass)
 94        self.created_instances.append(new_instance)
 95        return new_instance
 96
 97    def can_build(self, target_volume):
 98        total_volume = sum(instance.volume for instance in self.created_instances if instance not in self.used_instances)
 99        return total_volume >= target_volume
100
101    @classmethod
102    def can_build_together(cls, target_volume):
103        total_volume = 0
104        for factory in cls.all_factories:
105            total_volume += sum(
106                instance.volume for instance in factory.created_instances if instance not in factory.used_instances
107            )
108
109        return total_volume >= target_volume

..E.EF....
======================================================================
ERROR: test_materials_between_factories (test.TestFactory.test_materials_between_factories)
Test materials sharing.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 156, in test_materials_between_factories
result2, = self.factory2(Brick_Concrete_Steel_Stone_Wood=2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 53, in __call__
return self._create_named_materials(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 61, in _create_named_materials
raise ValueError(f"Invalid material name: {name}")
ValueError: Invalid material name: Brick_Concrete_Steel_Stone_Wood

======================================================================
ERROR: test_named_arguments_with_dynamically_created_classes (test.TestFactory.test_named_arguments_with_dynamically_created_classes)
Test dynamically created classes uniqueness.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 145, in test_named_arguments_with_dynamically_created_classes
result2, = self.factory1(Brick_Concrete_Steel_Stone_Wood=2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 53, in __call__
return self._create_named_materials(**kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 61, in _create_named_materials
raise ValueError(f"Invalid material name: {name}")
ValueError: Invalid material name: Brick_Concrete_Steel_Stone_Wood

======================================================================
FAIL: test_positional_arguments_multiple_argument_from_initial_set (test.TestFactory.test_positional_arguments_multiple_argument_from_initial_set)
Test calling a factory using multiple positional arguments.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 116, in test_positional_arguments_multiple_argument_from_initial_set
concrete_wood = self.factory1(concrete, wood)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 54, in __call__
return self._create_alloy(*args)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 72, in _create_alloy
raise AssertionError("This material instance has already been used.")
AssertionError: This material instance has already been used.

----------------------------------------------------------------------
Ran 10 tests in 0.012s

FAILED (failures=1, errors=2)

Дискусия
История
Това решение има само една версия.