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

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

9 точки общо

9 успешни теста
1 неуспешни теста
Код

  1class Material:
  2    def __init__(self, weight):
  3        self.weight = weight
  4
  5    @property
  6    def volume(self):
  7        return self.weight / self.density
  8
  9
 10class Concrete(Material):
 11    density = 2500
 12
 13
 14class Brick(Material):
 15    density = 2000
 16
 17
 18class Stone(Material):
 19    density = 1600
 20
 21
 22class Wood(Material):
 23    density = 600
 24
 25
 26class Steel(Material):
 27    density = 7700
 28
 29
 30class Factory:
 31    _used_instances = set()
 32    _all_created_instances = []
 33    _dynamic_classes = {}
 34    volume = 0
 35    def __init__(self):
 36        self.created_instances = []
 37        self.volume = 0
 38
 39    def __call__(self, *args, **kwargs):
 40        if args and kwargs:
 41            raise ValueError("Cannot mix positional and keyword arguments.")
 42        if not args and not kwargs:
 43            raise ValueError("Must provide arguments.")
 44        if args:
 45            return self._positional_arguments(*args)
 46        return self._keyword_args(**kwargs)
 47
 48    def _positional_arguments(self, *args):
 49        if len(args) == 1:
 50            if args[0] not in Factory._used_instances:
 51                self.volume += args[0].volume
 52                Factory.volume += args[0].volume
 53                Factory._used_instances.add(args[0])
 54                return args[0]
 55            raise AssertionError("This instance has already been used.")
 56        for obj in args:
 57            if obj in Factory._used_instances:
 58                raise AssertionError("This instance has already been used.")
 59            Factory._used_instances.add(obj)
 60            self.volume -= obj.volume
 61            Factory.volume -= obj.volume
 62        base_materials = self._get_base_materials(args)
 63        new_class_name = "_".join(sorted(base_materials.keys()))
 64        if new_class_name in Factory._dynamic_classes:
 65            dynamic_class = Factory._dynamic_classes[new_class_name]
 66        else:
 67            new_density = sum(base_materials.values()) / len(base_materials)
 68
 69            class DynamicMaterial(Material):
 70                density = new_density
 71                _base_classes = base_materials
 72
 73            DynamicMaterial.__name__ = new_class_name
 74            Factory._dynamic_classes[new_class_name] = DynamicMaterial
 75            globals()[new_class_name] = DynamicMaterial
 76            dynamic_class = DynamicMaterial
 77        dynamic_class_weight = sum(obj.weight for obj in args)
 78        instance = dynamic_class(dynamic_class_weight)
 79        Factory._all_created_instances.append(instance)
 80        self.created_instances.append(instance)
 81        self.volume += instance.volume
 82        Factory.volume += instance.volume
 83        return instance
 84
 85    def _get_base_materials(self, materials):
 86        base_classes = {}
 87        for obj in materials:
 88            if isinstance(obj, Material):
 89                if hasattr(obj, "_base_classes"):
 90                    base_classes.update(obj._base_classes)
 91                else:
 92                    base_classes[obj.__class__.__name__] = obj.density
 93            else:
 94                raise ValueError(f"Unrecognized material: {obj}")
 95        return base_classes
 96
 97    def _keyword_args(self, **kwargs):
 98        result = []
 99        for name, weight in kwargs.items():
100            if name not in globals() and name not in Factory._dynamic_classes:
101                raise ValueError(f"Unknown material: {name}")
102            material = globals().get(name) or Factory._dynamic_classes[name]
103            instance = material(weight)
104            result.append(instance)
105            Factory._all_created_instances.append(instance)
106            self.created_instances.append(instance)
107            self.volume += instance.volume
108            Factory.volume += instance.volume
109        return tuple(result)
110
111    def can_build(self, volume):
112        return self.volume >= volume
113
114    @staticmethod
115    def can_build_together(volume):
116        return Factory.volume >= volume

.....F....
======================================================================
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 45, in __call__
return self._positional_arguments(*args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 58, in _positional_arguments
raise AssertionError("This instance has already been used.")
AssertionError: This instance has already been used.

----------------------------------------------------------------------
Ran 10 tests in 0.011s

FAILED (failures=1)

Дискусия
История

f1class Material:f1class Material:
2    def __init__(self, weight):2    def __init__(self, weight):
3        self.weight = weight3        self.weight = weight
44
5    @property5    @property
6    def volume(self):6    def volume(self):
7        return self.weight / self.density7        return self.weight / self.density
88
99
10class Concrete(Material):10class Concrete(Material):
11    density = 250011    density = 2500
1212
1313
14class Brick(Material):14class Brick(Material):
15    density = 200015    density = 2000
1616
1717
18class Stone(Material):18class Stone(Material):
19    density = 160019    density = 1600
2020
2121
22class Wood(Material):22class Wood(Material):
23    density = 60023    density = 600
2424
2525
26class Steel(Material):26class Steel(Material):
27    density = 770027    density = 7700
2828
2929
30class Factory:30class Factory:
n31    _material_classes = {}n
32    _used_instances = set()31    _used_instances = set()
33    _all_created_instances = []32    _all_created_instances = []
34    _dynamic_classes = {}33    _dynamic_classes = {}
n35 n34    volume = 0
36    def __init__(self):35    def __init__(self):
37        self.created_instances = []36        self.created_instances = []
nn37        self.volume = 0
3838
39    def __call__(self, *args, **kwargs):39    def __call__(self, *args, **kwargs):
40        if args and kwargs:40        if args and kwargs:
41            raise ValueError("Cannot mix positional and keyword arguments.")41            raise ValueError("Cannot mix positional and keyword arguments.")
42        if not args and not kwargs:42        if not args and not kwargs:
43            raise ValueError("Must provide arguments.")43            raise ValueError("Must provide arguments.")
44        if args:44        if args:
45            return self._positional_arguments(*args)45            return self._positional_arguments(*args)
46        return self._keyword_args(**kwargs)46        return self._keyword_args(**kwargs)
4747
48    def _positional_arguments(self, *args):48    def _positional_arguments(self, *args):
nn49        if len(args) == 1:
50            if args[0] not in Factory._used_instances:
51                self.volume += args[0].volume
52                Factory.volume += args[0].volume
53                Factory._used_instances.add(args[0])
54                return args[0]
55            raise AssertionError("This instance has already been used.")
49        for obj in args:56        for obj in args:
50            if obj in Factory._used_instances:57            if obj in Factory._used_instances:
51                raise AssertionError("This instance has already been used.")58                raise AssertionError("This instance has already been used.")
52            Factory._used_instances.add(obj)59            Factory._used_instances.add(obj)
nn60            self.volume -= obj.volume
61            Factory.volume -= obj.volume
53        base_materials = self._get_base_materials(args)62        base_materials = self._get_base_materials(args)
54        new_class_name = "_".join(sorted(base_materials.keys()))63        new_class_name = "_".join(sorted(base_materials.keys()))
55        if new_class_name in Factory._dynamic_classes:64        if new_class_name in Factory._dynamic_classes:
56            dynamic_class = Factory._dynamic_classes[new_class_name]65            dynamic_class = Factory._dynamic_classes[new_class_name]
57        else:66        else:
58            new_density = sum(base_materials.values()) / len(base_materials)67            new_density = sum(base_materials.values()) / len(base_materials)
5968
60            class DynamicMaterial(Material):69            class DynamicMaterial(Material):
61                density = new_density70                density = new_density
62                _base_classes = base_materials71                _base_classes = base_materials
6372
64            DynamicMaterial.__name__ = new_class_name73            DynamicMaterial.__name__ = new_class_name
65            Factory._dynamic_classes[new_class_name] = DynamicMaterial74            Factory._dynamic_classes[new_class_name] = DynamicMaterial
66            globals()[new_class_name] = DynamicMaterial75            globals()[new_class_name] = DynamicMaterial
67            dynamic_class = DynamicMaterial76            dynamic_class = DynamicMaterial
68        dynamic_class_weight = sum(obj.weight for obj in args)77        dynamic_class_weight = sum(obj.weight for obj in args)
69        instance = dynamic_class(dynamic_class_weight)78        instance = dynamic_class(dynamic_class_weight)
70        Factory._all_created_instances.append(instance)79        Factory._all_created_instances.append(instance)
71        self.created_instances.append(instance)80        self.created_instances.append(instance)
nn81        self.volume += instance.volume
82        Factory.volume += instance.volume
72        return instance83        return instance
7384
74    def _get_base_materials(self, materials):85    def _get_base_materials(self, materials):
75        base_classes = {}86        base_classes = {}
76        for obj in materials:87        for obj in materials:
77            if isinstance(obj, Material):88            if isinstance(obj, Material):
78                if hasattr(obj, "_base_classes"):89                if hasattr(obj, "_base_classes"):
79                    base_classes.update(obj._base_classes)90                    base_classes.update(obj._base_classes)
80                else:91                else:
81                    base_classes[obj.__class__.__name__] = obj.density92                    base_classes[obj.__class__.__name__] = obj.density
82            else:93            else:
83                raise ValueError(f"Unrecognized material: {obj}")94                raise ValueError(f"Unrecognized material: {obj}")
84        return base_classes95        return base_classes
8596
86    def _keyword_args(self, **kwargs):97    def _keyword_args(self, **kwargs):
87        result = []98        result = []
88        for name, weight in kwargs.items():99        for name, weight in kwargs.items():
89            if name not in globals() and name not in Factory._dynamic_classes:100            if name not in globals() and name not in Factory._dynamic_classes:
90                raise ValueError(f"Unknown material: {name}")101                raise ValueError(f"Unknown material: {name}")
91            material = globals().get(name) or Factory._dynamic_classes[name]102            material = globals().get(name) or Factory._dynamic_classes[name]
n92            Factory._used_instances.add(material)n
93            instance = material(weight)103            instance = material(weight)
94            result.append(instance)104            result.append(instance)
95            Factory._all_created_instances.append(instance)105            Factory._all_created_instances.append(instance)
96            self.created_instances.append(instance)106            self.created_instances.append(instance)
nn107            self.volume += instance.volume
108            Factory.volume += instance.volume
97        return tuple(result)109        return tuple(result)
98110
n99    @staticmethodn
100    def all_is_base_classes(classes):
101        for obj in classes:
102            if obj.__class__ not in [Concrete, Brick, Wood, Stone, Steel]:
103                return False
104        return True
105 
106    def can_build(self, volume):111    def can_build(self, volume):
n107        wall_density = 0n
108        wall_weight = 0
109        if self.all_is_base_classes(self.created_instances):
110            wall_volume = sum(obj.volume for obj in self.created_instances)
111            return wall_volume >= volume112        return self.volume >= volume
112        for obj in self.created_instances:
113            if obj in self._used_instances:
114                continue
115            obj_class_name = type(obj).__name__
116            base_class_names = obj_class_name.split("_")
117            base_classes = [globals()[name] for name in base_class_names if name in globals()]
118            for cls in base_classes:
119                wall_density += cls.density
120            wall_density /= len(base_classes)
121            wall_weight += obj.weight
122        if wall_density == 0:
123            raise ZeroDivisionError
124        return wall_weight / wall_density >= volume
125113
126    @staticmethod114    @staticmethod
127    def can_build_together(volume):115    def can_build_together(volume):
t128        wall_density = 0t
129        wall_weight = 0
130        if Factory.all_is_base_classes(Factory._all_created_instances):
131            wall_volume = sum(obj.volume for obj in Factory._all_created_instances)
132            return wall_volume >= volume116        return Factory.volume >= volume
133        for obj in Factory._all_created_instances:117 
134            if obj in Factory._used_instances:
135                continue
136            obj_class_name = type(obj).__name__
137            base_class_names = obj_class_name.split("_")
138            base_classes = [globals()[name] for name in base_class_names if name in globals()]
139            for cls in base_classes:
140                wall_density += cls.density
141            wall_density /= len(base_classes)
142            wall_weight += obj.weight
143        return wall_weight / wall_density >= volume
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op