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

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

0 точки общо

8 успешни теста
2 неуспешни теста
Код

  1CONCRETE_DENSITY = 2500
  2BRICK_DENSITY = 2000
  3STONE_DENSITY = 1600
  4WOOD_DENSITY = 600
  5STEEL_DENSITY = 7700
  6
  7SHARED_CLASSES = {
  8    "Concrete": lambda mass: Concrete(mass),
  9    "Brick": lambda mass: Brick(mass),
 10    "Stone": lambda mass: Stone(mass),
 11    "Wood": lambda mass: Wood(mass),
 12    "Steel": lambda mass: Steel(mass),
 13}
 14
 15ALL_FACTORIES = []
 16
 17class Material:
 18    def __init__(self, mass: int, density: int):
 19        self.mass = mass
 20        self._is_valid = True
 21        self.base_densities = [density]
 22
 23    @property
 24    def is_valid(self) -> bool:
 25        return self._is_valid
 26
 27    def invalidate(self):
 28        self._is_valid = False
 29
 30    @property
 31    def density(self):
 32        return sum(self.base_densities) / len(self.base_densities)
 33
 34    @property
 35    def volume(self) -> float:
 36        return self.mass / self.density
 37
 38class Concrete(Material):
 39    def __init__(self, mass: int):
 40        super().__init__(mass, CONCRETE_DENSITY)
 41
 42class Brick(Material):
 43    def __init__(self, mass: int):
 44        super().__init__(mass, BRICK_DENSITY)
 45
 46class Stone(Material):
 47    def __init__(self, mass: int):
 48        super().__init__(mass, STONE_DENSITY)
 49
 50class Wood(Material):
 51    def __init__(self, mass: int):
 52        super().__init__(mass, WOOD_DENSITY)
 53
 54class Steel(Material):
 55    def __init__(self, mass: int):
 56        super().__init__(mass, STEEL_DENSITY)
 57
 58class Factory:
 59    _all_factories = []
 60
 61    def __init__(self):
 62        self.materials = []
 63        Factory._all_factories.append(self)
 64
 65    def __call__(self, *args, **kwargs):
 66        if args and kwargs:
 67            raise ValueError("Cannot mix positional and keyword arguments.")
 68        if not args and not kwargs:
 69            raise ValueError("Factory must be called with arguments.")
 70        if kwargs:
 71            return self._create_from_kwargs(kwargs)
 72        if args:
 73            return self._create_from_args(args)
 74
 75    def _create_from_kwargs(self, kwargs):
 76        result = []
 77        for material_name, mass in kwargs.items():
 78            if material_name not in SHARED_CLASSES:
 79                raise ValueError(f"Invalid material: {material_name}")
 80            material_creator = SHARED_CLASSES[material_name]
 81            material = material_creator(mass)
 82            self.materials.append(material)
 83            result.append(material)
 84        return tuple(result)
 85
 86    def _create_from_args(self, args):
 87        for arg in args:
 88            assert arg.is_valid, "Material has already been used and is invalid."
 89            arg.invalidate()
 90        material_classes = sorted(arg.__class__.__name__ for arg in args)
 91        class_name = "_".join(material_classes)
 92        if class_name in SHARED_CLASSES:
 93            alloy_class = SHARED_CLASSES[class_name]
 94        else:
 95            combined_densities = self._get_combined_densities(args)
 96            alloy_class = self._create_alloy_class(class_name, combined_densities)
 97        total_mass = sum(arg.mass for arg in args)
 98        alloy_instance = alloy_class(total_mass)
 99        self.materials.append(alloy_instance)
100        return alloy_instance
101
102    def _get_combined_densities(self, args):
103        combined_densities = []
104        for arg in args:
105            combined_densities.extend(arg.base_densities)
106        return combined_densities
107
108    def _create_alloy_class(self, class_name, combined_densities):
109        average_density = sum(combined_densities) / len(combined_densities)
110        class Alloy(Material):
111            def __init__(self, mass: int):
112                super().__init__(mass, average_density)
113        Alloy.__name__ = class_name
114        SHARED_CLASSES[class_name] = lambda mass: Alloy(mass)
115        return Alloy
116
117    def can_build(self, required_volume: int) -> bool:
118        total_volume = sum(material.volume for material in self.materials if material.is_valid)
119        return total_volume >= required_volume
120
121    @classmethod
122    def can_build_together(cls, required_volume: int) -> bool:
123        total_volume = sum(
124            material.volume
125            for factory in cls._all_factories
126            for material in factory.materials
127            if material.is_valid
128        )
129        return total_volume >= required_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 73, in __call__
return self._create_from_args(args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 88, in _create_from_args
assert arg.is_valid, "Material has already been used and is invalid."
^^^^^^^^^^^^
AssertionError: Material has already been used and is invalid.

======================================================================
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 128, in test_positional_arguments_multiple_argument_with_dynamics
self.assertEqual(mega_material.__class__.__name__,
AssertionError: 'Brick_Concrete_Stone_Steel_Wood' != 'Brick_Concrete_Steel_Stone_Wood'
- Brick_Concrete_Stone_Steel_Wood
? ------
+ Brick_Concrete_Steel_Stone_Wood
? ++++++

----------------------------------------------------------------------
Ran 10 tests in 0.016s

FAILED (failures=2)

Дискусия
Димитър Илиев
23.11.2024 14:46

Благодаря за препоръките!
История

f1CONCRETE_DENSITY = 2500f1CONCRETE_DENSITY = 2500
2BRICK_DENSITY = 20002BRICK_DENSITY = 2000
3STONE_DENSITY = 16003STONE_DENSITY = 1600
4WOOD_DENSITY = 6004WOOD_DENSITY = 600
5STEEL_DENSITY = 77005STEEL_DENSITY = 7700
66
7SHARED_CLASSES = {7SHARED_CLASSES = {
8    "Concrete": lambda mass: Concrete(mass),8    "Concrete": lambda mass: Concrete(mass),
9    "Brick": lambda mass: Brick(mass),9    "Brick": lambda mass: Brick(mass),
10    "Stone": lambda mass: Stone(mass),10    "Stone": lambda mass: Stone(mass),
11    "Wood": lambda mass: Wood(mass),11    "Wood": lambda mass: Wood(mass),
12    "Steel": lambda mass: Steel(mass),12    "Steel": lambda mass: Steel(mass),
13}13}
1414
15ALL_FACTORIES = []15ALL_FACTORIES = []
1616
n17 n
18class Material:17class Material:
n19    def __init__(self, mass: int, base_densities: list):n18    def __init__(self, mass: int, density: int):
20        self.mass = mass19        self.mass = mass
21        self._is_valid = True20        self._is_valid = True
n22        self.base_densities = base_densitiesn21        self.base_densities = [density]
2322
24    @property23    @property
25    def is_valid(self) -> bool:24    def is_valid(self) -> bool:
26        return self._is_valid25        return self._is_valid
2726
28    def invalidate(self):27    def invalidate(self):
29        self._is_valid = False28        self._is_valid = False
3029
31    @property30    @property
32    def density(self):31    def density(self):
n33        """Calculate the density based on base densities."""n
34        return sum(self.base_densities) / len(self.base_densities)32        return sum(self.base_densities) / len(self.base_densities)
n35 n
36 
37class Concrete(Material):
38    def __init__(self, mass: int):
39        super().__init__(mass, [CONCRETE_DENSITY])
4033
41    @property34    @property
42    def volume(self) -> float:35    def volume(self) -> float:
43        return self.mass / self.density36        return self.mass / self.density
4437
nn38class Concrete(Material):
39    def __init__(self, mass: int):
40        super().__init__(mass, CONCRETE_DENSITY)
4541
46class Brick(Material):42class Brick(Material):
47    def __init__(self, mass: int):43    def __init__(self, mass: int):
n48        super().__init__(mass, [BRICK_DENSITY])n44        super().__init__(mass, BRICK_DENSITY)
49 
50    @property
51    def volume(self) -> float:
52        return self.mass / self.density
53 
5445
55class Stone(Material):46class Stone(Material):
56    def __init__(self, mass: int):47    def __init__(self, mass: int):
n57        super().__init__(mass, [STONE_DENSITY])n48        super().__init__(mass, STONE_DENSITY)
58 
59    @property
60    def volume(self) -> float:
61        return self.mass / self.density
62 
6349
64class Wood(Material):50class Wood(Material):
65    def __init__(self, mass: int):51    def __init__(self, mass: int):
n66        super().__init__(mass, [WOOD_DENSITY])n52        super().__init__(mass, WOOD_DENSITY)
67 
68    @property
69    def volume(self) -> float:
70        return self.mass / self.density
71 
7253
73class Steel(Material):54class Steel(Material):
74    def __init__(self, mass: int):55    def __init__(self, mass: int):
n75        super().__init__(mass, [STEEL_DENSITY])n56        super().__init__(mass, STEEL_DENSITY)
76 
77    @property
78    def volume(self) -> float:
79        return self.mass / self.density
80 
8157
82class Factory:58class Factory:
nn59    _all_factories = []
60 
83    def __init__(self):61    def __init__(self):
84        self.materials = []62        self.materials = []
n85        ALL_FACTORIES.append(self)n63        Factory._all_factories.append(self)
8664
87    def __call__(self, *args, **kwargs):65    def __call__(self, *args, **kwargs):
88        if args and kwargs:66        if args and kwargs:
89            raise ValueError("Cannot mix positional and keyword arguments.")67            raise ValueError("Cannot mix positional and keyword arguments.")
90        if not args and not kwargs:68        if not args and not kwargs:
91            raise ValueError("Factory must be called with arguments.")69            raise ValueError("Factory must be called with arguments.")
nn70        if kwargs:
71            return self._create_from_kwargs(kwargs)
72        if args:
73            return self._create_from_args(args)
9274
n93        if kwargs:n75    def _create_from_kwargs(self, kwargs):
94            result = []76        result = []
95            for material_name, mass in kwargs.items():77        for material_name, mass in kwargs.items():
96                if material_name not in SHARED_CLASSES:78            if material_name not in SHARED_CLASSES:
97                    raise ValueError(f"Invalid material: {material_name}")79                raise ValueError(f"Invalid material: {material_name}")
98                material_creator = SHARED_CLASSES[material_name]80            material_creator = SHARED_CLASSES[material_name]
99                material = material_creator(mass)81            material = material_creator(mass)
100                self.materials.append(material)82            self.materials.append(material)
101                result.append(material)83            result.append(material)
102            return tuple(result) if len(result) > 1 else result[0]84        return tuple(result)
10385
n104        if args:n86    def _create_from_args(self, args):
105            for arg in args:87        for arg in args:
106                assert arg.is_valid, "Material has already been used and is invalid."88            assert arg.is_valid, "Material has already been used and is invalid."
107                arg.invalidate()89            arg.invalidate()
90        material_classes = sorted(arg.__class__.__name__ for arg in args)
91        class_name = "_".join(material_classes)
92        if class_name in SHARED_CLASSES:
93            alloy_class = SHARED_CLASSES[class_name]
94        else:
95            combined_densities = self._get_combined_densities(args)
96            alloy_class = self._create_alloy_class(class_name, combined_densities)
97        total_mass = sum(arg.mass for arg in args)
98        alloy_instance = alloy_class(total_mass)
99        self.materials.append(alloy_instance)
100        return alloy_instance
108101
n109            material_classes = sorted(arg.__class__.__name__ for arg in args)n102    def _get_combined_densities(self, args):
110            class_name = "_".join(material_classes)103        combined_densities = []
104        for arg in args:
105            combined_densities.extend(arg.base_densities)
106        return combined_densities
111107
n112            if class_name in SHARED_CLASSES:n108    def _create_alloy_class(self, class_name, combined_densities):
113                alloy_class = SHARED_CLASSES[class_name]
114            else:
115                combined_densities = []
116                for arg in args:
117                    combined_densities.extend(arg.base_densities)
118 
119                average_density = sum(combined_densities) / len(combined_densities)109        average_density = sum(combined_densities) / len(combined_densities)
120 
121                class Alloy(Material):110        class Alloy(Material):
122                    def __init__(self, mass: int):111            def __init__(self, mass: int):
123                        super().__init__(mass, combined_densities)112                super().__init__(mass, average_density)
124 
125                    @property
126                    def volume(self) -> float:
127                        return self.mass / self.density
128 
129                Alloy.__name__ = class_name113        Alloy.__name__ = class_name
130                SHARED_CLASSES[class_name] = lambda mass: Alloy(mass)114        SHARED_CLASSES[class_name] = lambda mass: Alloy(mass)
131                alloy_class = Alloy115        return Alloy
132 
133            total_mass = sum(arg.mass for arg in args)
134            alloy_instance = alloy_class(total_mass)
135            self.materials.append(alloy_instance)
136            return alloy_instance
137116
138    def can_build(self, required_volume: int) -> bool:117    def can_build(self, required_volume: int) -> bool:
139        total_volume = sum(material.volume for material in self.materials if material.is_valid)118        total_volume = sum(material.volume for material in self.materials if material.is_valid)
140        return total_volume >= required_volume119        return total_volume >= required_volume
141120
142    @classmethod121    @classmethod
143    def can_build_together(cls, required_volume: int) -> bool:122    def can_build_together(cls, required_volume: int) -> bool:
144        total_volume = sum(123        total_volume = sum(
145            material.volume124            material.volume
n146            for factory in ALL_FACTORIESn125            for factory in cls._all_factories
147            for material in factory.materials126            for material in factory.materials
148            if material.is_valid127            if material.is_valid
149        )128        )
150        return total_volume >= required_volume129        return total_volume >= required_volume
tt130 
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op