1CONCRETE = 2500
2BRICK = 2000
3STONE = 1600
4WOOD = 600
5STEEL = 7700
6
7
8class Material:
9 def __init__(self, mass, density):
10 self.mass = mass
11 self.density = density
12 self._used = False
13 self._number_of_materials_in_it = 1
14
15 @property
16 def volume(self):
17 return self.mass / self.density
18
19 def is_used(self):
20 if self._used:
21 raise AssertionError
22 self._used = True
23
24
25class Concrete(Material):
26 def __init__(self, mass):
27 super().__init__(mass, CONCRETE)
28
29
30class Brick(Material):
31 def __init__(self, mass):
32 super().__init__(mass, BRICK)
33
34
35class Stone(Material):
36 def __init__(self, mass):
37 super().__init__(mass, STONE)
38
39
40class Wood(Material):
41 def __init__(self, mass):
42 super().__init__(mass, WOOD)
43
44
45class Steel(Material):
46 def __init__(self, mass):
47 super().__init__(mass, STEEL)
48
49
50class Factory:
51
52 MATERIAL_NAMES = {
53 "Brick": Brick,
54 "Concrete": Concrete,
55 "Stone": Stone,
56 "Wood": Wood,
57 "Steel": Steel,
58 }
59
60 all_created_materials = []
61
62 def __init__(self):
63 self.created_materials = []
64
65 def _create_class_name_from_materials(self, materials):
66 class_names = []
67 for material in materials:
68 class_name = type(material).__name__
69 class_names.extend(class_name.split("_"))
70
71 sorted_class_names = sorted(class_names)
72 return "_".join(sorted_class_names)
73
74 def _calculate_density_and_ingredients(self, materials):
75 new_class_density = 0
76 number_ingredients = 0
77 for material in materials:
78 new_class_density += material.density * material._number_of_materials_in_it
79 number_ingredients += material._number_of_materials_in_it
80 new_class_density /= number_ingredients
81 return new_class_density, number_ingredients
82
83 def _create_new_class(self, class_name, density):
84 new_class = type(class_name, (Material,), {
85 '__init__': lambda self, mass: super(type(self), self).__init__(mass, density)
86 })
87 self.MATERIAL_NAMES[class_name] = new_class
88 return new_class
89
90 def _handle_kwargs(self, kwargs):
91 result = []
92 for material_name, material_mass in kwargs.items():
93 if (material_name in self.MATERIAL_NAMES):
94 material_instance = self.MATERIAL_NAMES[material_name](material_mass)
95 self.created_materials.append(material_instance)
96 Factory.all_created_materials.append(material_instance)
97 result.append(material_instance)
98 else:
99 raise ValueError
100 return tuple(result)
101
102 def _handle_args(self, args):
103 temp_used_materials = []
104
105 try:
106 for material in args:
107 material.is_used()
108 temp_used_materials.append(material)
109
110 class_name = self._create_class_name_from_materials(args)
111
112 if class_name in self.MATERIAL_NAMES:
113 new_mass = sum(material.mass for material in args)
114 result_material = self.MATERIAL_NAMES[class_name](new_mass)
115 self.created_materials.append(result_material)
116 Factory.all_created_materials.append(result_material)
117 return result_material
118 else:
119 new_class_density, number_ingredients = self._calculate_density_and_ingredients(args)
120 new_class = self._create_new_class(class_name, new_class_density)
121 new_mass = sum(material.mass for material in args)
122 result_material = new_class(new_mass)
123 result_material._number_of_materials_in_it = number_ingredients
124 self.created_materials.append(result_material)
125 Factory.all_created_materials.append(result_material)
126 return result_material
127
128 except AssertionError as e:
129 for material in temp_used_materials:
130 material._used = False
131 raise e
132
133 def __call__(self, *args, **kwargs):
134 if args and kwargs:
135 raise ValueError
136 if not args and not kwargs:
137 raise ValueError
138
139 self.created_materials.clear()
140
141 if kwargs:
142 return self._handle_kwargs(kwargs)
143
144 if args:
145 return self._handle_args(args)
146
147 def can_build(self, needed_volume):
148 total_volume = sum(
149 material.volume for material in self.created_materials)
150 return total_volume >= needed_volume
151
152 @classmethod
153 def can_build_together(cls, needed_volume):
154 total_volume = sum(
155 material.volume for material in cls.all_created_materials)
156 return total_volume >= needed_volume
.F........
======================================================================
FAIL: test_can_build (test.TestFactory.test_can_build)
Test can_build methods.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 177, in test_can_build
self.assertFalse(solution.Factory.can_build_together(6.0001))
AssertionError: True is not false
----------------------------------------------------------------------
Ran 10 tests in 0.015s
FAILED (failures=1)
26.11.2024 14:51
26.11.2024 14:50
26.11.2024 14:55
26.11.2024 14:53
26.11.2024 14:57
26.11.2024 14:52