1class Material:
2 def __init__(self, mass, density):
3 self.mass = mass
4 self.density = density
5 self.usable = True
6
7 @property
8 def volume(self):
9 return float(self.mass) / self.density
10
11 def use(self):
12 if not self.usable:
13 raise AssertionError("Material isn't usable.")
14 self.usable = False
15
16
17class Concrete(Material):
18 def __init__(self, mass):
19 super().__init__(mass, density=2500)
20
21
22class Brick(Material):
23 def __init__(self, mass):
24 super().__init__(mass, density=2000)
25
26
27class Stone(Material):
28 def __init__(self, mass):
29 super().__init__(mass, density=1600)
30
31
32class Wood(Material):
33 def __init__(self, mass):
34 super().__init__(mass, density=600)
35
36
37class Steel(Material):
38 def __init__(self, mass):
39 super().__init__(mass, density=7700)
40
41
42class Factory:
43 _fusions = {}
44 __class_instances = []
45
46 def __init__(self):
47 self.__class_instances.append(self)
48 self._materials = []
49
50 def __del__(self):
51 self.__class_instances.remove(self)
52
53 @property
54 def volume(self):
55 return sum(material.volume for material in self._materials if material.usable)
56
57 def can_build(self, volume):
58 return self.volume >= volume
59
60 @classmethod
61 def can_build_together(cls, volume):
62 return sum(
63 material.volume
64 for factory in cls.__class_instances
65 for material in factory._materials
66 if material.usable
67 ) >= volume
68
69 def __call__(self, *args, **kwargs):
70 if args and kwargs:
71 raise ValueError("Only positional or keyword arguments are allowed, not both.")
72
73 if not args and not kwargs:
74 raise ValueError("Factory can't be called without arguments.")
75
76 if kwargs:
77 materials = []
78 for name, mass in kwargs.items():
79 material_class = globals().get(name)
80 if not material_class:
81 material_class = self._fusions.get(name,None)
82 if not material_class or not issubclass(material_class, Material):
83 raise ValueError("Invalid material.")
84 material = material_class(mass)
85 materials.append(material)
86 self._materials.append(material)
87 return tuple(materials)
88
89 if args:
90 new_args = []
91 for material in args:
92 if type(material).__name__.__contains__("_"):
93 # here we get the class name from the globals and use its init with the material mass
94 new_args += map(lambda name: globals()[name](material.mass), type(material).__name__.split("_"))
95 else:
96 new_args.append(material)
97
98 class_name = "_".join(sorted(set(type(material).__name__ for material in new_args)))
99 if class_name not in self._fusions:
100 density = sum(material.density for material in new_args) / len(new_args)
101
102 class Fusion(Material):
103 def __init__(self, mass):
104 super().__init__(mass, density=int(density))
105
106 Fusion.__name__ = class_name
107 self._fusions[class_name] = Fusion
108
109 total_mass = sum(material.mass for material in new_args)
110 new_material = self._fusions[class_name](total_mass)
111 for material in args:
112 material.use()
113 self._materials.append(new_material)
114 return new_material
.....FFF..
======================================================================
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 112, in __call__
material.use()
File "/tmp/solution.py", line 13, in use
raise AssertionError("Material isn't usable.")
AssertionError: Material isn't usable.
======================================================================
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 125, in test_positional_arguments_multiple_argument_with_dynamics
self.assertAlmostEqual(brick_concrete_stone.volume, 5.2131, places=4)
AssertionError: 5.213969503197245 != 5.2131 within 4 places (0.0008695031972454359 difference)
======================================================================
FAIL: 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 80, in test_positional_arguments_single_argument
self.assertIs(type(concrete2), solution.Concrete)
AssertionError: <class 'solution.Factory.__call__.<locals>.Fusion'> is not <class 'solution.Concrete'>
----------------------------------------------------------------------
Ran 10 tests in 0.018s
FAILED (failures=3)
Рада Димитрова
26.11.2024 19:11Мерси.
|
Георги Кунчев
26.11.2024 18:49След крайния срок всички тестове са публични. Виж под дефиницията на домашното.
|
Рада Димитрова
26.11.2024 18:35Има ли шанс да видя теста за self.assertAlmostEqual(brick_concrete_stone.volume, 5.2131, places=4)
AssertionError: 5.213969503197245 != 5.2131 within 4 places (0.0008695031972454359 difference), за да сравня какво не правя коректно при изчислението локално със същите примери?
|
f | 1 | class Material: | f | 1 | class Material: |
2 | def __init__(self, mass, density): | 2 | def __init__(self, mass, density): | ||
3 | self.mass = mass | 3 | self.mass = mass | ||
4 | self.density = density | 4 | self.density = density | ||
5 | self.usable = True | 5 | self.usable = True | ||
6 | 6 | ||||
7 | @property | 7 | @property | ||
8 | def volume(self): | 8 | def volume(self): | ||
9 | return float(self.mass) / self.density | 9 | return float(self.mass) / self.density | ||
10 | 10 | ||||
11 | def use(self): | 11 | def use(self): | ||
12 | if not self.usable: | 12 | if not self.usable: | ||
13 | raise AssertionError("Material isn't usable.") | 13 | raise AssertionError("Material isn't usable.") | ||
14 | self.usable = False | 14 | self.usable = False | ||
15 | 15 | ||||
16 | 16 | ||||
17 | class Concrete(Material): | 17 | class Concrete(Material): | ||
18 | def __init__(self, mass): | 18 | def __init__(self, mass): | ||
19 | super().__init__(mass, density=2500) | 19 | super().__init__(mass, density=2500) | ||
20 | 20 | ||||
21 | 21 | ||||
22 | class Brick(Material): | 22 | class Brick(Material): | ||
23 | def __init__(self, mass): | 23 | def __init__(self, mass): | ||
24 | super().__init__(mass, density=2000) | 24 | super().__init__(mass, density=2000) | ||
25 | 25 | ||||
26 | 26 | ||||
27 | class Stone(Material): | 27 | class Stone(Material): | ||
28 | def __init__(self, mass): | 28 | def __init__(self, mass): | ||
29 | super().__init__(mass, density=1600) | 29 | super().__init__(mass, density=1600) | ||
30 | 30 | ||||
31 | 31 | ||||
32 | class Wood(Material): | 32 | class Wood(Material): | ||
33 | def __init__(self, mass): | 33 | def __init__(self, mass): | ||
34 | super().__init__(mass, density=600) | 34 | super().__init__(mass, density=600) | ||
35 | 35 | ||||
36 | 36 | ||||
37 | class Steel(Material): | 37 | class Steel(Material): | ||
38 | def __init__(self, mass): | 38 | def __init__(self, mass): | ||
39 | super().__init__(mass, density=7700) | 39 | super().__init__(mass, density=7700) | ||
40 | 40 | ||||
41 | 41 | ||||
42 | class Factory: | 42 | class Factory: | ||
43 | _fusions = {} | 43 | _fusions = {} | ||
44 | __class_instances = [] | 44 | __class_instances = [] | ||
45 | 45 | ||||
46 | def __init__(self): | 46 | def __init__(self): | ||
47 | self.__class_instances.append(self) | 47 | self.__class_instances.append(self) | ||
48 | self._materials = [] | 48 | self._materials = [] | ||
49 | 49 | ||||
50 | def __del__(self): | 50 | def __del__(self): | ||
51 | self.__class_instances.remove(self) | 51 | self.__class_instances.remove(self) | ||
52 | 52 | ||||
53 | @property | 53 | @property | ||
54 | def volume(self): | 54 | def volume(self): | ||
55 | return sum(material.volume for material in self._materials if material.usable) | 55 | return sum(material.volume for material in self._materials if material.usable) | ||
56 | 56 | ||||
57 | def can_build(self, volume): | 57 | def can_build(self, volume): | ||
58 | return self.volume >= volume | 58 | return self.volume >= volume | ||
59 | 59 | ||||
60 | @classmethod | 60 | @classmethod | ||
61 | def can_build_together(cls, volume): | 61 | def can_build_together(cls, volume): | ||
62 | return sum( | 62 | return sum( | ||
63 | material.volume | 63 | material.volume | ||
64 | for factory in cls.__class_instances | 64 | for factory in cls.__class_instances | ||
65 | for material in factory._materials | 65 | for material in factory._materials | ||
66 | if material.usable | 66 | if material.usable | ||
67 | ) >= volume | 67 | ) >= volume | ||
68 | 68 | ||||
69 | def __call__(self, *args, **kwargs): | 69 | def __call__(self, *args, **kwargs): | ||
70 | if args and kwargs: | 70 | if args and kwargs: | ||
71 | raise ValueError("Only positional or keyword arguments are allowed, not both.") | 71 | raise ValueError("Only positional or keyword arguments are allowed, not both.") | ||
72 | 72 | ||||
73 | if not args and not kwargs: | 73 | if not args and not kwargs: | ||
74 | raise ValueError("Factory can't be called without arguments.") | 74 | raise ValueError("Factory can't be called without arguments.") | ||
75 | 75 | ||||
76 | if kwargs: | 76 | if kwargs: | ||
77 | materials = [] | 77 | materials = [] | ||
78 | for name, mass in kwargs.items(): | 78 | for name, mass in kwargs.items(): | ||
79 | material_class = globals().get(name) | 79 | material_class = globals().get(name) | ||
t | t | 80 | if not material_class: | ||
81 | material_class = self._fusions.get(name,None) | ||||
80 | if not material_class or not issubclass(material_class, Material): | 82 | if not material_class or not issubclass(material_class, Material): | ||
81 | raise ValueError("Invalid material.") | 83 | raise ValueError("Invalid material.") | ||
82 | material = material_class(mass) | 84 | material = material_class(mass) | ||
83 | materials.append(material) | 85 | materials.append(material) | ||
84 | self._materials.append(material) | 86 | self._materials.append(material) | ||
85 | return tuple(materials) | 87 | return tuple(materials) | ||
86 | 88 | ||||
87 | if args: | 89 | if args: | ||
88 | new_args = [] | 90 | new_args = [] | ||
89 | for material in args: | 91 | for material in args: | ||
90 | if type(material).__name__.__contains__("_"): | 92 | if type(material).__name__.__contains__("_"): | ||
91 | # here we get the class name from the globals and use its init with the material mass | 93 | # here we get the class name from the globals and use its init with the material mass | ||
92 | new_args += map(lambda name: globals()[name](material.mass), type(material).__name__.split("_")) | 94 | new_args += map(lambda name: globals()[name](material.mass), type(material).__name__.split("_")) | ||
93 | else: | 95 | else: | ||
94 | new_args.append(material) | 96 | new_args.append(material) | ||
95 | 97 | ||||
96 | class_name = "_".join(sorted(set(type(material).__name__ for material in new_args))) | 98 | class_name = "_".join(sorted(set(type(material).__name__ for material in new_args))) | ||
97 | if class_name not in self._fusions: | 99 | if class_name not in self._fusions: | ||
98 | density = sum(material.density for material in new_args) / len(new_args) | 100 | density = sum(material.density for material in new_args) / len(new_args) | ||
99 | 101 | ||||
100 | class Fusion(Material): | 102 | class Fusion(Material): | ||
101 | def __init__(self, mass): | 103 | def __init__(self, mass): | ||
102 | super().__init__(mass, density=int(density)) | 104 | super().__init__(mass, density=int(density)) | ||
103 | 105 | ||||
104 | Fusion.__name__ = class_name | 106 | Fusion.__name__ = class_name | ||
105 | self._fusions[class_name] = Fusion | 107 | self._fusions[class_name] = Fusion | ||
106 | 108 | ||||
107 | total_mass = sum(material.mass for material in new_args) | 109 | total_mass = sum(material.mass for material in new_args) | ||
108 | new_material = self._fusions[class_name](total_mass) | 110 | new_material = self._fusions[class_name](total_mass) | ||
109 | for material in args: | 111 | for material in args: | ||
110 | material.use() | 112 | material.use() | ||
111 | self._materials.append(new_material) | 113 | self._materials.append(new_material) | ||
112 | return new_material | 114 | return new_material |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|