Домашни > Another brick in the wall > Решения > Решението на Станислава Желязкова

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

8 точки общо

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

  1class Material:
  2    def __init__(self, mass):
  3        self.mass = mass
  4        self._used = False  
  5
  6    @property
  7    def volume(self):
  8        return self.mass / self._density
  9
 10    def mark_used(self):
 11        if self._used:
 12            raise AssertionError("Material already used.")
 13        self._used = True
 14
 15
 16class Concrete(Material):
 17    _density = 2500
 18
 19
 20class Brick(Material):
 21    _density = 2000
 22
 23
 24class Stone(Material):
 25    _density = 1600
 26
 27
 28class Wood(Material):
 29    _density = 600
 30
 31
 32class Steel(Material):
 33    _density = 7700
 34
 35
 36class Factory:
 37    _registry = { "Concrete": Concrete,
 38    "Brick": Brick,
 39    "Stone": Stone,
 40    "Wood": Wood,
 41    "Steel": Steel,}
 42
 43    _all_factories = []
 44
 45    def __init__(self):
 46        self.materials = []
 47        Factory._all_factories.append(self)
 48
 49    def __call__(self, *args, **kwargs): 
 50        if args and kwargs:
 51            raise ValueError("Cannot mix positional and keyword arguments.")
 52        if not args and not kwargs:
 53            raise ValueError("Must provide either positional or keyword arguments.")
 54
 55        if kwargs:
 56            return self._handle_named_args(kwargs)
 57        else:
 58            return self._handle_positional_args(args)
 59
 60    def _handle_named_args(self, kwargs):
 61        results = []
 62        for name, mass in kwargs.items():
 63            if name not in Factory._registry:
 64                raise ValueError(f"Invalid material name: {name}")
 65            material_class = Factory._registry[name]
 66            instance = material_class(mass)
 67            self.materials.append(instance)
 68            results.append(instance)
 69        return tuple(results)
 70
 71    def _handle_positional_args(self, args):
 72        for material in args:
 73            material.mark_used()
 74
 75        material_classes = []
 76        for material in args:
 77            if "_" in material.__class__.__name__:  
 78                material_classes.extend(material.__class__.__name__.split("_"))
 79            else:
 80                material_classes.append(material.__class__.__name__)
 81    
 82    
 83        class_name = "_".join(sorted(set(material_classes)))
 84
 85        if class_name not in Factory._registry:
 86            densities = [cls._density for cls in set(type(material) for material in args)]
 87            avg_density = sum(densities) / len(densities)
 88
 89            class DynamicMaterial(Material):
 90                _density = avg_density
 91
 92            DynamicMaterial.__name__ = class_name
 93            Factory._registry[class_name] = DynamicMaterial
 94
 95        new_material_class = Factory._registry[class_name]
 96        total_mass = sum(material.mass for material in args)
 97        instance = new_material_class(total_mass)
 98        self.materials.append(instance)
 99        return instance
100
101    def can_build(self, volume):
102        total_volume = sum(material.volume for material in self.materials if not material._used)
103        return total_volume >= volume
104
105    @classmethod
106    def can_build_together(cls, volume):
107        total_volume = sum(
108            material.volume
109            for factory in cls._all_factories 
110            for material in factory.materials
111            if not material._used
112        )
113        return total_volume >= volume

.....FF...
======================================================================
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 58, in __call__
return self._handle_positional_args(args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 73, in _handle_positional_args
material.mark_used()
File "/tmp/solution.py", line 12, in mark_used
raise AssertionError("Material already used.")
AssertionError: Material already used.

======================================================================
FAIL: 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 130, in test_positional_arguments_multiple_argument_with_dynamics
self.assertAlmostEqual(mega_material.volume, 6.77, places=2) # mass=19500, density=2880
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
AssertionError: 5.661290322580645 != 6.77 within 2 places (1.1087096774193546 difference)

----------------------------------------------------------------------
Ran 10 tests in 0.010s

FAILED (failures=2)

Дискусия
Виктор Бечев
26.11.2024 17:20

Отвъд горните дребни забелжки - кодът изглежда добре и се чете прилично.
Георги Кунчев
25.11.2024 22:40

Качвам решението ръчно поради (все още) незнаен проблем.
Виктор Бечев
25.11.2024 22:14

Файлът, който си качила е нечетим. Провери дали случайно не е с грешното разширение (например да си качила някое `.pyc` или нещо подобно). Освен ако не се опитваш да ни хакнеш сайта, тогава хем не изглежда да е успешно, хем ще получиш 0 точки на домашното. :grin:
История

f1class Material:f1class Material:
2    def __init__(self, mass):2    def __init__(self, mass):
3        self.mass = mass3        self.mass = mass
4        self._used = False  4        self._used = False  
55
6    @property6    @property
7    def volume(self):7    def volume(self):
8        return self.mass / self._density8        return self.mass / self._density
99
10    def mark_used(self):10    def mark_used(self):
11        if self._used:11        if self._used:
12            raise AssertionError("Material already used.")12            raise AssertionError("Material already used.")
13        self._used = True13        self._used = True
1414
1515
16class Concrete(Material):16class Concrete(Material):
17    _density = 250017    _density = 2500
1818
1919
20class Brick(Material):20class Brick(Material):
21    _density = 200021    _density = 2000
2222
2323
24class Stone(Material):24class Stone(Material):
25    _density = 160025    _density = 1600
2626
2727
28class Wood(Material):28class Wood(Material):
29    _density = 60029    _density = 600
3030
3131
32class Steel(Material):32class Steel(Material):
33    _density = 770033    _density = 7700
3434
3535
36class Factory:36class Factory:
37    _registry = { "Concrete": Concrete,37    _registry = { "Concrete": Concrete,
38    "Brick": Brick,38    "Brick": Brick,
39    "Stone": Stone,39    "Stone": Stone,
40    "Wood": Wood,40    "Wood": Wood,
41    "Steel": Steel,}41    "Steel": Steel,}
4242
43    _all_factories = []43    _all_factories = []
4444
45    def __init__(self):45    def __init__(self):
46        self.materials = []46        self.materials = []
47        Factory._all_factories.append(self)47        Factory._all_factories.append(self)
4848
49    def __call__(self, *args, **kwargs): 49    def __call__(self, *args, **kwargs): 
50        if args and kwargs:50        if args and kwargs:
51            raise ValueError("Cannot mix positional and keyword arguments.")51            raise ValueError("Cannot mix positional and keyword arguments.")
52        if not args and not kwargs:52        if not args and not kwargs:
53            raise ValueError("Must provide either positional or keyword arguments.")53            raise ValueError("Must provide either positional or keyword arguments.")
5454
55        if kwargs:55        if kwargs:
56            return self._handle_named_args(kwargs)56            return self._handle_named_args(kwargs)
57        else:57        else:
58            return self._handle_positional_args(args)58            return self._handle_positional_args(args)
5959
60    def _handle_named_args(self, kwargs):60    def _handle_named_args(self, kwargs):
61        results = []61        results = []
62        for name, mass in kwargs.items():62        for name, mass in kwargs.items():
63            if name not in Factory._registry:63            if name not in Factory._registry:
64                raise ValueError(f"Invalid material name: {name}")64                raise ValueError(f"Invalid material name: {name}")
65            material_class = Factory._registry[name]65            material_class = Factory._registry[name]
66            instance = material_class(mass)66            instance = material_class(mass)
67            self.materials.append(instance)67            self.materials.append(instance)
68            results.append(instance)68            results.append(instance)
69        return tuple(results)69        return tuple(results)
7070
71    def _handle_positional_args(self, args):71    def _handle_positional_args(self, args):
72        for material in args:72        for material in args:
73            material.mark_used()73            material.mark_used()
7474
n75        material_classes = sorted(set(type(material) for material in args), key=lambda cls: cls.__name__)n75        material_classes = []
76        for material in args:
77            if "_" in material.__class__.__name__:  
78                material_classes.extend(material.__class__.__name__.split("_"))
79            else:
80                material_classes.append(material.__class__.__name__)
81    
82    
76        class_name = "_".join(sorted(cls.__name__ for cls in material_classes))83        class_name = "_".join(sorted(set(material_classes)))
7784
78        if class_name not in Factory._registry:85        if class_name not in Factory._registry:
n79            densities = [cls._density for cls in material_classes]n86            densities = [cls._density for cls in set(type(material) for material in args)]
80            avg_density = sum(densities) / len(densities)87            avg_density = sum(densities) / len(densities)
8188
82            class DynamicMaterial(Material):89            class DynamicMaterial(Material):
83                _density = avg_density90                _density = avg_density
8491
85            DynamicMaterial.__name__ = class_name92            DynamicMaterial.__name__ = class_name
86            Factory._registry[class_name] = DynamicMaterial93            Factory._registry[class_name] = DynamicMaterial
8794
88        new_material_class = Factory._registry[class_name]95        new_material_class = Factory._registry[class_name]
89        total_mass = sum(material.mass for material in args)96        total_mass = sum(material.mass for material in args)
90        instance = new_material_class(total_mass)97        instance = new_material_class(total_mass)
91        self.materials.append(instance)98        self.materials.append(instance)
92        return instance99        return instance
93100
94    def can_build(self, volume):101    def can_build(self, volume):
95        total_volume = sum(material.volume for material in self.materials if not material._used)102        total_volume = sum(material.volume for material in self.materials if not material._used)
96        return total_volume >= volume103        return total_volume >= volume
97104
98    @classmethod105    @classmethod
99    def can_build_together(cls, volume):106    def can_build_together(cls, volume):
100        total_volume = sum(107        total_volume = sum(
101            material.volume108            material.volume
102            for factory in cls._all_factories 109            for factory in cls._all_factories 
103            for material in factory.materials110            for material in factory.materials
104            if not material._used111            if not material._used
105        )112        )
106        return total_volume >= volume113        return total_volume >= volume
107114
tt115 
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1class Material:f1class Material:
2    def __init__(self, mass):2    def __init__(self, mass):
3        self.mass = mass3        self.mass = mass
n4        self._used = Falsen4        self._used = False  
55
6    @property6    @property
7    def volume(self):7    def volume(self):
8        return self.mass / self._density8        return self.mass / self._density
99
10    def mark_used(self):10    def mark_used(self):
11        if self._used:11        if self._used:
12            raise AssertionError("Material already used.")12            raise AssertionError("Material already used.")
13        self._used = True13        self._used = True
1414
1515
16class Concrete(Material):16class Concrete(Material):
17    _density = 250017    _density = 2500
1818
1919
20class Brick(Material):20class Brick(Material):
21    _density = 200021    _density = 2000
2222
2323
24class Stone(Material):24class Stone(Material):
25    _density = 160025    _density = 1600
2626
2727
28class Wood(Material):28class Wood(Material):
29    _density = 60029    _density = 600
3030
3131
32class Steel(Material):32class Steel(Material):
33    _density = 770033    _density = 7700
3434
3535
36class Factory:36class Factory:
37    _registry = { "Concrete": Concrete,37    _registry = { "Concrete": Concrete,
38    "Brick": Brick,38    "Brick": Brick,
39    "Stone": Stone,39    "Stone": Stone,
40    "Wood": Wood,40    "Wood": Wood,
41    "Steel": Steel,}41    "Steel": Steel,}
4242
43    _all_factories = []43    _all_factories = []
4444
45    def __init__(self):45    def __init__(self):
46        self.materials = []46        self.materials = []
47        Factory._all_factories.append(self)47        Factory._all_factories.append(self)
4848
n49    def __call__(self, *args, **kwargs):n49    def __call__(self, *args, **kwargs): 
50        if args and kwargs:50        if args and kwargs:
51            raise ValueError("Cannot mix positional and keyword arguments.")51            raise ValueError("Cannot mix positional and keyword arguments.")
52        if not args and not kwargs:52        if not args and not kwargs:
53            raise ValueError("Must provide either positional or keyword arguments.")53            raise ValueError("Must provide either positional or keyword arguments.")
5454
55        if kwargs:55        if kwargs:
56            return self._handle_named_args(kwargs)56            return self._handle_named_args(kwargs)
57        else:57        else:
58            return self._handle_positional_args(args)58            return self._handle_positional_args(args)
5959
60    def _handle_named_args(self, kwargs):60    def _handle_named_args(self, kwargs):
61        results = []61        results = []
62        for name, mass in kwargs.items():62        for name, mass in kwargs.items():
63            if name not in Factory._registry:63            if name not in Factory._registry:
64                raise ValueError(f"Invalid material name: {name}")64                raise ValueError(f"Invalid material name: {name}")
65            material_class = Factory._registry[name]65            material_class = Factory._registry[name]
66            instance = material_class(mass)66            instance = material_class(mass)
67            self.materials.append(instance)67            self.materials.append(instance)
68            results.append(instance)68            results.append(instance)
69        return tuple(results)69        return tuple(results)
7070
71    def _handle_positional_args(self, args):71    def _handle_positional_args(self, args):
72        for material in args:72        for material in args:
73            material.mark_used()73            material.mark_used()
7474
75        material_classes = sorted(set(type(material) for material in args), key=lambda cls: cls.__name__)75        material_classes = sorted(set(type(material) for material in args), key=lambda cls: cls.__name__)
76        class_name = "_".join(sorted(cls.__name__ for cls in material_classes))76        class_name = "_".join(sorted(cls.__name__ for cls in material_classes))
7777
78        if class_name not in Factory._registry:78        if class_name not in Factory._registry:
79            densities = [cls._density for cls in material_classes]79            densities = [cls._density for cls in material_classes]
80            avg_density = sum(densities) / len(densities)80            avg_density = sum(densities) / len(densities)
8181
82            class DynamicMaterial(Material):82            class DynamicMaterial(Material):
83                _density = avg_density83                _density = avg_density
8484
85            DynamicMaterial.__name__ = class_name85            DynamicMaterial.__name__ = class_name
86            Factory._registry[class_name] = DynamicMaterial86            Factory._registry[class_name] = DynamicMaterial
8787
88        new_material_class = Factory._registry[class_name]88        new_material_class = Factory._registry[class_name]
89        total_mass = sum(material.mass for material in args)89        total_mass = sum(material.mass for material in args)
90        instance = new_material_class(total_mass)90        instance = new_material_class(total_mass)
91        self.materials.append(instance)91        self.materials.append(instance)
92        return instance92        return instance
9393
94    def can_build(self, volume):94    def can_build(self, volume):
95        total_volume = sum(material.volume for material in self.materials if not material._used)95        total_volume = sum(material.volume for material in self.materials if not material._used)
96        return total_volume >= volume96        return total_volume >= volume
9797
98    @classmethod98    @classmethod
99    def can_build_together(cls, volume):99    def can_build_together(cls, volume):
100        total_volume = sum(100        total_volume = sum(
101            material.volume101            material.volume
n102            for factory in cls._all_factoriesn102            for factory in cls._all_factories 
103            for material in factory.materials103            for material in factory.materials
104            if not material._used104            if not material._used
105        )105        )
106        return total_volume >= volume106        return total_volume >= volume
107107
t108factory = Factory()t
109brick, wood = factory(Brick=10, Wood=5)
110concreate, = factory(Concrete=10)
111brick_wood = factory(brick, wood)
112 
113another_brick_wood, = factory(Brick_Wood=10)  # Валидно инстанциране на ново парче сплав с маса 10 и тип Brick_Wood, който е създаден на предишния ред
114 
115brick_concrete_wood = factory(brick_wood, concreate)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

f1class Material:f1class Material:
2    def __init__(self, mass):2    def __init__(self, mass):
3        self.mass = mass3        self.mass = mass
n4        self._used = False  n4        self._used = False
55
6    @property6    @property
7    def volume(self):7    def volume(self):
8        return self.mass / self._density8        return self.mass / self._density
99
10    def mark_used(self):10    def mark_used(self):
11        if self._used:11        if self._used:
12            raise AssertionError("Material already used.")12            raise AssertionError("Material already used.")
13        self._used = True13        self._used = True
1414
1515
16class Concrete(Material):16class Concrete(Material):
17    _density = 250017    _density = 2500
1818
1919
20class Brick(Material):20class Brick(Material):
21    _density = 200021    _density = 2000
2222
2323
24class Stone(Material):24class Stone(Material):
25    _density = 160025    _density = 1600
2626
2727
28class Wood(Material):28class Wood(Material):
29    _density = 60029    _density = 600
3030
3131
32class Steel(Material):32class Steel(Material):
33    _density = 770033    _density = 7700
3434
3535
36class Factory:36class Factory:
37    _registry = { "Concrete": Concrete,37    _registry = { "Concrete": Concrete,
38    "Brick": Brick,38    "Brick": Brick,
39    "Stone": Stone,39    "Stone": Stone,
40    "Wood": Wood,40    "Wood": Wood,
41    "Steel": Steel,}41    "Steel": Steel,}
4242
43    _all_factories = []43    _all_factories = []
4444
45    def __init__(self):45    def __init__(self):
46        self.materials = []46        self.materials = []
47        Factory._all_factories.append(self)47        Factory._all_factories.append(self)
4848
n49    def __call__(self, *args, **kwargs): n49    def __call__(self, *args, **kwargs):
50        if args and kwargs:50        if args and kwargs:
51            raise ValueError("Cannot mix positional and keyword arguments.")51            raise ValueError("Cannot mix positional and keyword arguments.")
52        if not args and not kwargs:52        if not args and not kwargs:
53            raise ValueError("Must provide either positional or keyword arguments.")53            raise ValueError("Must provide either positional or keyword arguments.")
5454
55        if kwargs:55        if kwargs:
56            return self._handle_named_args(kwargs)56            return self._handle_named_args(kwargs)
57        else:57        else:
58            return self._handle_positional_args(args)58            return self._handle_positional_args(args)
5959
60    def _handle_named_args(self, kwargs):60    def _handle_named_args(self, kwargs):
61        results = []61        results = []
62        for name, mass in kwargs.items():62        for name, mass in kwargs.items():
63            if name not in Factory._registry:63            if name not in Factory._registry:
64                raise ValueError(f"Invalid material name: {name}")64                raise ValueError(f"Invalid material name: {name}")
65            material_class = Factory._registry[name]65            material_class = Factory._registry[name]
66            instance = material_class(mass)66            instance = material_class(mass)
67            self.materials.append(instance)67            self.materials.append(instance)
68            results.append(instance)68            results.append(instance)
69        return tuple(results)69        return tuple(results)
7070
71    def _handle_positional_args(self, args):71    def _handle_positional_args(self, args):
72        for material in args:72        for material in args:
73            material.mark_used()73            material.mark_used()
7474
75        material_classes = sorted(set(type(material) for material in args), key=lambda cls: cls.__name__)75        material_classes = sorted(set(type(material) for material in args), key=lambda cls: cls.__name__)
76        class_name = "_".join(sorted(cls.__name__ for cls in material_classes))76        class_name = "_".join(sorted(cls.__name__ for cls in material_classes))
7777
78        if class_name not in Factory._registry:78        if class_name not in Factory._registry:
79            densities = [cls._density for cls in material_classes]79            densities = [cls._density for cls in material_classes]
80            avg_density = sum(densities) / len(densities)80            avg_density = sum(densities) / len(densities)
8181
82            class DynamicMaterial(Material):82            class DynamicMaterial(Material):
83                _density = avg_density83                _density = avg_density
8484
85            DynamicMaterial.__name__ = class_name85            DynamicMaterial.__name__ = class_name
86            Factory._registry[class_name] = DynamicMaterial86            Factory._registry[class_name] = DynamicMaterial
8787
88        new_material_class = Factory._registry[class_name]88        new_material_class = Factory._registry[class_name]
89        total_mass = sum(material.mass for material in args)89        total_mass = sum(material.mass for material in args)
90        instance = new_material_class(total_mass)90        instance = new_material_class(total_mass)
91        self.materials.append(instance)91        self.materials.append(instance)
92        return instance92        return instance
9393
94    def can_build(self, volume):94    def can_build(self, volume):
95        total_volume = sum(material.volume for material in self.materials if not material._used)95        total_volume = sum(material.volume for material in self.materials if not material._used)
96        return total_volume >= volume96        return total_volume >= volume
9797
98    @classmethod98    @classmethod
99    def can_build_together(cls, volume):99    def can_build_together(cls, volume):
100        total_volume = sum(100        total_volume = sum(
101            material.volume101            material.volume
n102            for factory in cls._all_factories n102            for factory in cls._all_factories
103            for material in factory.materials103            for material in factory.materials
104            if not material._used104            if not material._used
105        )105        )
106        return total_volume >= volume106        return total_volume >= volume
107107
108factory = Factory()108factory = Factory()
109brick, wood = factory(Brick=10, Wood=5)109brick, wood = factory(Brick=10, Wood=5)
110concreate, = factory(Concrete=10)110concreate, = factory(Concrete=10)
111brick_wood = factory(brick, wood)111brick_wood = factory(brick, wood)
112112
113another_brick_wood, = factory(Brick_Wood=10)  # Валидно инстанциране на ново парче сплав с маса 10 и тип Brick_Wood, който е създаден на предишния ред113another_brick_wood, = factory(Brick_Wood=10)  # Валидно инстанциране на ново парче сплав с маса 10 и тип Brick_Wood, който е създаден на предишния ред
114114
t115brick_concrete_wood = factory(brick_wood, concreate) t115brick_concrete_wood = factory(brick_wood, concreate)
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op