Домашни > Another brick in the wall > Решения > Решението на Михаела Гаврилова

Резултати
3 точки от тестове
0 точки от учител

3 точки общо

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

  1class Material:
  2    def __init__(self, mass):
  3        self.mass = mass
  4
  5    @property
  6    def density(self) -> float:
  7        return 1
  8
  9    @property
 10    def volume(self) -> float:
 11        if self.density == 0:
 12            return float('inf') #to make sure no zero division will happen
 13        return self.mass / self.density
 14
 15
 16class Concrete(Material):
 17    @property
 18    def density(self):
 19        return 2500
 20
 21class Brick(Material):
 22    @property
 23    def density(self):
 24        return 2000
 25
 26class Stone(Material):
 27    @property
 28    def density(self):
 29        return 1600
 30
 31class Wood(Material):
 32    @property
 33    def density(self):
 34        return 600
 35
 36class Steel(Material):
 37    @property
 38    def density(self):
 39        return 7700
 40
 41class Factory:
 42    already_existing = {}
 43    produced = []
 44
 45    def __call__(self, *args, **kwargs):
 46        if not args and not kwargs:
 47            raise ValueError("Should pass some arguments!")
 48
 49        if args and kwargs:
 50            raise ValueError("Can't pass both positional and keyword arguments!")
 51
 52        if args:
 53            return self.handle_args(args)
 54        if kwargs:
 55            return self.handle_kwargs(kwargs)
 56
 57    def handle_kwargs(self, kwargs):
 58        materials = []
 59        for name, mass in kwargs.items():
 60            material_class = globals().get(name)
 61            if material_class is None or not issubclass(material_class, Material):
 62                raise ValueError("Invalid material")
 63            material = material_class(mass)
 64            materials.append(material)
 65
 66        self.produced.extend(materials)
 67        return tuple(materials)
 68
 69    def handle_args(self, args):
 70        classes = {type(arg) for arg in args}
 71        for each_object in args:
 72            if not isinstance(each_object, Material):
 73                raise ValueError("Invalid object!")
 74            if hasattr(each_object, "_used") and each_object._used:
 75                raise AssertionError("Material has already been used!")
 76
 77            each_object._used = True #mark it as used
 78
 79        composite_name = "_".join(sorted(cls.__name__ for cls in classes))
 80        if composite_name in self.already_existing:
 81            composite_class = self.already_existing[composite_name]
 82        else:
 83            densities = [cls.density for cls in classes]
 84            composite_density = sum(densities) / len(densities)
 85
 86            #this is how we create a dynamic class, tova ne znaeh, che se pravi taka
 87            composite_class = type(composite_name,(Material,),{"density": composite_density},)
 88            self.already_existing[composite_name] = composite_class
 89
 90        mass_in_total = sum(each_obj.mass for each_obj in args)
 91        composite = composite_class(mass_in_total)
 92        self.produced.append(composite)
 93        return composite
 94
 95    def can_build(self, required_volume: float):
 96        unused_materials = [material for material in self.produced if not getattr(material, "_used", False)]
 97
 98        if not unused_materials:
 99            return False
100
101        total_volume = sum(material.volume for material in unused_materials)
102
103        return total_volume >= required_volume
104
105    @classmethod
106    def can_build_together(cls, required_volume: float):
107
108        unused_materials = [
109            material for factory in cls.already_existing.values()
110            for material in factory.produced if not getattr(material, "_used", False)
111        ]
112
113        if not unused_materials:
114            return False
115
116        total_volume = sum(material.volume for material in unused_materials)
117
118        return total_volume >= required_volume

.EE.EEEEE.
======================================================================
ERROR: test_can_build (test.TestFactory.test_can_build)
Test can_build methods.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 172, in test_can_build
brick_wood = self.factory2(brick, wood)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 53, in __call__
return self.handle_args(args)
^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 84, in handle_args
composite_density = sum(densities) / len(densities)
^^^^^^^^^^^^^^
TypeError: unsupported operand type(s) for +: 'int' and 'property'

======================================================================
ERROR: test_materials_between_factories (test.TestFactory.test_materials_between_factories)
Test materials sharing.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 155, in test_materials_between_factories
result1 = self.factory1(*materials)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 53, in __call__
return self.handle_args(args)
^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 84, in handle_args
composite_density = sum(densities) / len(densities)
^^^^^^^^^^^^^^
TypeError: unsupported operand type(s) for +: 'int' and 'property'

======================================================================
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 144, in test_named_arguments_with_dynamically_created_classes
result1 = self.factory1(*materials)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 53, in __call__
return self.handle_args(args)
^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 84, in handle_args
composite_density = sum(densities) / len(densities)
^^^^^^^^^^^^^^
TypeError: unsupported operand type(s) for +: 'int' and 'property'

======================================================================
ERROR: 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 93, in test_positional_arguments_multiple_argument_from_initial_set
result = self.factory1(wood, brick, concrete)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 53, in __call__
return self.handle_args(args)
^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 84, in handle_args
composite_density = sum(densities) / len(densities)
^^^^^^^^^^^^^^
TypeError: unsupported operand type(s) for +: 'int' and 'property'

======================================================================
ERROR: test_positional_arguments_multiple_argument_with_dynamics (test.TestFactory.test_positional_arguments_multiple_argument_with_dynamics)
Test calling a factory using multiple positional arguments.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 124, in test_positional_arguments_multiple_argument_with_dynamics
brick_concrete_stone = self.factory1(*materials)
^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 53, in __call__
return self.handle_args(args)
^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 84, in handle_args
composite_density = sum(densities) / len(densities)
^^^^^^^^^^^^^^
TypeError: unsupported operand type(s) for +: 'int' and 'property'

======================================================================
ERROR: test_positional_arguments_single_argument (test.TestFactory.test_positional_arguments_single_argument)
Test calling a factory using a sigle positional argument.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 79, in test_positional_arguments_single_argument
concrete2 = self.factory1(concrete1)
^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 53, in __call__
return self.handle_args(args)
^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 84, in handle_args
composite_density = sum(densities) / len(densities)
^^^^^^^^^^^^^^
TypeError: unsupported operand type(s) for +: 'int' and 'property'

======================================================================
ERROR: test_positional_arguments_singletons (test.TestFactory.test_positional_arguments_singletons)
Test dynamically created classes uniqueness.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 135, in test_positional_arguments_singletons
brick_concrete_wood1 = self.factory1(*materials1)
^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 53, in __call__
return self.handle_args(args)
^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 84, in handle_args
composite_density = sum(densities) / len(densities)
^^^^^^^^^^^^^^
TypeError: unsupported operand type(s) for +: 'int' and 'property'

----------------------------------------------------------------------
Ran 10 tests in 0.038s

FAILED (errors=7)

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