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

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

7 точки общо

7 успешни теста
3 неуспешни теста
Код

  1class Material:
  2    DENSITIES = {"Concrete": 2500, "Brick": 2000, "Stone": 1600, "Wood": 600, "Steel": 7700}
  3
  4    def __init__(self, mass):
  5        if not isinstance(mass, int):
  6            raise TypeError("Mass should be an integer.")
  7        self.mass = mass
  8        self.used = False
  9        self.components = [type(self).__name__]
 10
 11    @property
 12    def volume(self):
 13        return float(self.mass / self.density)
 14
 15
 16class Concrete(Material):
 17    density = Material.DENSITIES["Concrete"]
 18
 19
 20class Brick(Material):
 21    density = Material.DENSITIES["Brick"]
 22
 23
 24class Stone(Material):
 25    density = Material.DENSITIES["Stone"]
 26
 27
 28class Wood(Material):
 29    density = Material.DENSITIES["Wood"]
 30
 31
 32class Steel(Material):
 33    density = Material.DENSITIES["Steel"]
 34
 35
 36class Factory:
 37    ACCESS_CLASS = {"Concrete": Concrete, "Brick": Brick,
 38                    "Stone": Stone, "Wood": Wood, "Steel": Steel}
 39    dynamic_classes = {}
 40    all_materials = []
 41
 42    def __init__(self):
 43        self.materials = []
 44
 45    def __call__(self, *args, **kwargs):
 46        if (args and kwargs) or (not args and not kwargs):
 47            raise ValueError("Input error for factory arguments.")
 48        if kwargs:
 49            return self.create_materials_from_kwargs(kwargs)
 50        elif args:
 51            return self.create_alloy_from_args(args)
 52
 53    def create_materials_from_kwargs(self, kwargs):
 54        instance = []
 55        for class_name, mass in kwargs.items():
 56            if class_name not in self.ACCESS_CLASS:
 57                raise ValueError("Invalid material name.")
 58            cls = self.ACCESS_CLASS[class_name]
 59            material = cls(mass)
 60            instance.append(material)
 61            self.materials.append(material)
 62            self.all_materials.append(material)
 63        return tuple(instance)
 64
 65    def create_alloy_from_args(self, args):
 66        if any(arg.used for arg in args) or any(not isinstance(arg, Material) for arg in args):
 67            raise AssertionError("Materials have already been used or are invalid.")
 68
 69        used_materials = []
 70        for arg in args:
 71            if isinstance(arg, Material):
 72                for component in arg.components:
 73                    if "_" in component:
 74                        used_materials.extend(component.split("_"))
 75                    else:
 76                        used_materials.append(component)
 77            else:
 78                raise ValueError("Invalid argument type.")
 79            
 80        class_name = "_".join(sorted(set(used_materials)))
 81        mass = sum(arg.mass for arg in args)
 82
 83        if class_name not in self.dynamic_classes:
 84            all_densities = [self.ACCESS_CLASS[comp].density if comp in self.ACCESS_CLASS else self.dynamic_classes[comp].density
 85                             for comp in set(used_materials)]
 86            average_density = sum(all_densities) / len(all_densities)
 87            dynamic_class = type(class_name, (Material,), {'density': average_density})
 88            self.dynamic_classes[class_name] = dynamic_class
 89        else:
 90            dynamic_class = self.dynamic_classes[class_name]
 91
 92        new_material = dynamic_class(mass)
 93        self.materials.append(new_material)
 94        self.all_materials.append(new_material)
 95
 96        for arg in args:
 97            arg.used = True
 98
 99        return new_material
100
101    def can_build(self, required_volume):
102        return sum(material.volume for material in self.materials if not material.used) >= required_volume
103
104    @classmethod
105    def can_build_together(cls, required_volume):
106        return sum(material.volume for material in cls.all_materials if not material.used) >= required_volume

..E.E..F..
======================================================================
ERROR: test_materials_between_factories (test.TestFactory.test_materials_between_factories)
Test materials sharing.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 156, in test_materials_between_factories
result2, = self.factory2(Brick_Concrete_Steel_Stone_Wood=2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 49, in __call__
return self.create_materials_from_kwargs(kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 57, in create_materials_from_kwargs
raise ValueError("Invalid material name.")
ValueError: Invalid material name.

======================================================================
ERROR: test_named_arguments_with_dynamically_created_classes (test.TestFactory.test_named_arguments_with_dynamically_created_classes)
Test dynamically created classes uniqueness.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 145, in test_named_arguments_with_dynamically_created_classes
result2, = self.factory1(Brick_Concrete_Steel_Stone_Wood=2)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 49, in __call__
return self.create_materials_from_kwargs(kwargs)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 57, in create_materials_from_kwargs
raise ValueError("Invalid material name.")
ValueError: Invalid material name.

======================================================================
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.Concrete'> is not <class 'solution.Concrete'>

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

FAILED (failures=1, errors=2)

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

f1class Material:f1class Material:
2    DENSITIES = {"Concrete": 2500, "Brick": 2000, "Stone": 1600, "Wood": 600, "Steel": 7700}2    DENSITIES = {"Concrete": 2500, "Brick": 2000, "Stone": 1600, "Wood": 600, "Steel": 7700}
33
4    def __init__(self, mass):4    def __init__(self, mass):
5        if not isinstance(mass, int):5        if not isinstance(mass, int):
6            raise TypeError("Mass should be an integer.")6            raise TypeError("Mass should be an integer.")
7        self.mass = mass7        self.mass = mass
8        self.used = False8        self.used = False
9        self.components = [type(self).__name__]9        self.components = [type(self).__name__]
1010
11    @property11    @property
12    def volume(self):12    def volume(self):
13        return float(self.mass / self.density)13        return float(self.mass / self.density)
1414
1515
16class Concrete(Material):16class Concrete(Material):
17    density = Material.DENSITIES["Concrete"]17    density = Material.DENSITIES["Concrete"]
1818
1919
20class Brick(Material):20class Brick(Material):
21    density = Material.DENSITIES["Brick"]21    density = Material.DENSITIES["Brick"]
2222
2323
24class Stone(Material):24class Stone(Material):
25    density = Material.DENSITIES["Stone"]25    density = Material.DENSITIES["Stone"]
2626
2727
28class Wood(Material):28class Wood(Material):
29    density = Material.DENSITIES["Wood"]29    density = Material.DENSITIES["Wood"]
3030
3131
32class Steel(Material):32class Steel(Material):
33    density = Material.DENSITIES["Steel"]33    density = Material.DENSITIES["Steel"]
3434
3535
36class Factory:36class Factory:
37    ACCESS_CLASS = {"Concrete": Concrete, "Brick": Brick,37    ACCESS_CLASS = {"Concrete": Concrete, "Brick": Brick,
38                    "Stone": Stone, "Wood": Wood, "Steel": Steel}38                    "Stone": Stone, "Wood": Wood, "Steel": Steel}
39    dynamic_classes = {}39    dynamic_classes = {}
40    all_materials = []40    all_materials = []
4141
42    def __init__(self):42    def __init__(self):
43        self.materials = []43        self.materials = []
4444
45    def __call__(self, *args, **kwargs):45    def __call__(self, *args, **kwargs):
46        if (args and kwargs) or (not args and not kwargs):46        if (args and kwargs) or (not args and not kwargs):
47            raise ValueError("Input error for factory arguments.")47            raise ValueError("Input error for factory arguments.")
48        if kwargs:48        if kwargs:
49            return self.create_materials_from_kwargs(kwargs)49            return self.create_materials_from_kwargs(kwargs)
50        elif args:50        elif args:
51            return self.create_alloy_from_args(args)51            return self.create_alloy_from_args(args)
5252
53    def create_materials_from_kwargs(self, kwargs):53    def create_materials_from_kwargs(self, kwargs):
54        instance = []54        instance = []
55        for class_name, mass in kwargs.items():55        for class_name, mass in kwargs.items():
56            if class_name not in self.ACCESS_CLASS:56            if class_name not in self.ACCESS_CLASS:
57                raise ValueError("Invalid material name.")57                raise ValueError("Invalid material name.")
58            cls = self.ACCESS_CLASS[class_name]58            cls = self.ACCESS_CLASS[class_name]
59            material = cls(mass)59            material = cls(mass)
60            instance.append(material)60            instance.append(material)
61            self.materials.append(material)61            self.materials.append(material)
62            self.all_materials.append(material)62            self.all_materials.append(material)
63        return tuple(instance)63        return tuple(instance)
6464
65    def create_alloy_from_args(self, args):65    def create_alloy_from_args(self, args):
66        if any(arg.used for arg in args) or any(not isinstance(arg, Material) for arg in args):66        if any(arg.used for arg in args) or any(not isinstance(arg, Material) for arg in args):
67            raise AssertionError("Materials have already been used or are invalid.")67            raise AssertionError("Materials have already been used or are invalid.")
6868
69        used_materials = []69        used_materials = []
70        for arg in args:70        for arg in args:
71            if isinstance(arg, Material):71            if isinstance(arg, Material):
72                for component in arg.components:72                for component in arg.components:
73                    if "_" in component:73                    if "_" in component:
74                        used_materials.extend(component.split("_"))74                        used_materials.extend(component.split("_"))
75                    else:75                    else:
76                        used_materials.append(component)76                        used_materials.append(component)
77            else:77            else:
78                raise ValueError("Invalid argument type.")78                raise ValueError("Invalid argument type.")
79            79            
80        class_name = "_".join(sorted(set(used_materials)))80        class_name = "_".join(sorted(set(used_materials)))
81        mass = sum(arg.mass for arg in args)81        mass = sum(arg.mass for arg in args)
8282
83        if class_name not in self.dynamic_classes:83        if class_name not in self.dynamic_classes:
84            all_densities = [self.ACCESS_CLASS[comp].density if comp in self.ACCESS_CLASS else self.dynamic_classes[comp].density84            all_densities = [self.ACCESS_CLASS[comp].density if comp in self.ACCESS_CLASS else self.dynamic_classes[comp].density
85                             for comp in set(used_materials)]85                             for comp in set(used_materials)]
86            average_density = sum(all_densities) / len(all_densities)86            average_density = sum(all_densities) / len(all_densities)
87            dynamic_class = type(class_name, (Material,), {'density': average_density})87            dynamic_class = type(class_name, (Material,), {'density': average_density})
88            self.dynamic_classes[class_name] = dynamic_class88            self.dynamic_classes[class_name] = dynamic_class
89        else:89        else:
90            dynamic_class = self.dynamic_classes[class_name]90            dynamic_class = self.dynamic_classes[class_name]
9191
92        new_material = dynamic_class(mass)92        new_material = dynamic_class(mass)
93        self.materials.append(new_material)93        self.materials.append(new_material)
94        self.all_materials.append(new_material)94        self.all_materials.append(new_material)
9595
96        for arg in args:96        for arg in args:
97            arg.used = True97            arg.used = True
9898
99        return new_material99        return new_material
100100
101    def can_build(self, required_volume):101    def can_build(self, required_volume):
n102        total_volume = sum(material.volume for material in self.materials if not material.used)n102        return sum(material.volume for material in self.materials if not material.used) >= required_volume
103        return total_volume >= required_volume
104103
105    @classmethod104    @classmethod
106    def can_build_together(cls, required_volume):105    def can_build_together(cls, required_volume):
t107        total_volume = sum(material.volume for material in cls.all_materials if not material.used)t106        return sum(material.volume for material in cls.all_materials if not material.used) >= required_volume
108        return total_volume >= required_volume
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op

n1class Mixin:n1class Material:
2    DENSITIES = {"Concrete" : 2500, "Brick" : 2000, "Stone" : 1600, "Wood" : 600, "Steel" : 7700}2    DENSITIES = {"Concrete": 2500, "Brick": 2000, "Stone": 1600, "Wood": 600, "Steel": 7700}
33
n4    def __init__(self, mass, density):n4    def __init__(self, mass):
5        if not isinstance(mass, int):5        if not isinstance(mass, int):
6            raise TypeError("Mass should be an integer.")6            raise TypeError("Mass should be an integer.")
n7 n
8        self.mass = mass7        self.mass = mass
n9        self.density = densityn
10        self.used = False8        self.used = False
11        self.components = [type(self).__name__]9        self.components = [type(self).__name__]
1210
13    @property11    @property
14    def volume(self):12    def volume(self):
15        return float(self.mass / self.density)13        return float(self.mass / self.density)
1614
1715
n18class Concrete(Mixin):n16class Concrete(Material):
19    def __init__(self, mass):17    density = Material.DENSITIES["Concrete"]
20        super().__init__(mass, self.DENSITIES["Concrete"])
2118
2219
n23class Brick(Mixin):n20class Brick(Material):
24    def __init__(self, mass):21    density = Material.DENSITIES["Brick"]
25        super().__init__(mass, self.DENSITIES["Brick"])
2622
2723
n28class Stone(Mixin):n24class Stone(Material):
29    def __init__(self, mass):25    density = Material.DENSITIES["Stone"]
30        super().__init__(mass, self.DENSITIES["Stone"])
3126
3227
n33class Wood(Mixin):n28class Wood(Material):
34    def __init__(self, mass):29    density = Material.DENSITIES["Wood"]
35        super().__init__(mass, self.DENSITIES["Wood"])
3630
3731
n38class Steel(Mixin):n32class Steel(Material):
39    def __init__(self, mass):33    density = Material.DENSITIES["Steel"]
40        super().__init__(mass, self.DENSITIES["Steel"])
4134
4235
43class Factory:36class Factory:
n44    ACCESS_CLASS = {"Concrete" : Concrete, "Brick" : Brick,n37    ACCESS_CLASS = {"Concrete": Concrete, "Brick": Brick,
45                    "Stone" : Stone, "Wood" : Wood, "Steel" : Steel}38                    "Stone": Stone, "Wood": Wood, "Steel": Steel}
46    dynamic_classes = {}39    dynamic_classes = {}
47    all_materials = []40    all_materials = []
4841
49    def __init__(self):42    def __init__(self):
50        self.materials = []43        self.materials = []
5144
52    def __call__(self, *args, **kwargs):45    def __call__(self, *args, **kwargs):
53        if (args and kwargs) or (not args and not kwargs):46        if (args and kwargs) or (not args and not kwargs):
n54            raise ValueError("Input error for factory argements.")n47            raise ValueError("Input error for factory arguments.")
55        if kwargs:48        if kwargs:
56            return self.create_materials_from_kwargs(kwargs)49            return self.create_materials_from_kwargs(kwargs)
57        elif args:50        elif args:
58            return self.create_alloy_from_args(args)51            return self.create_alloy_from_args(args)
5952
60    def create_materials_from_kwargs(self, kwargs):53    def create_materials_from_kwargs(self, kwargs):
61        instance = []54        instance = []
62        for class_name, mass in kwargs.items():55        for class_name, mass in kwargs.items():
63            if class_name not in self.ACCESS_CLASS:56            if class_name not in self.ACCESS_CLASS:
64                raise ValueError("Invalid material name.")57                raise ValueError("Invalid material name.")
n65            cls = self.ACCESS_CLASS.get(class_name) or self.dynamic_classes[class_name]n58            cls = self.ACCESS_CLASS[class_name]
66            if not cls:59            material = cls(mass)
67                raise ValueError("Invalid material name.")
68            instance.append(cls(mass))60            instance.append(material)
61            self.materials.append(material)
69            self.all_materials.append(cls(mass))62            self.all_materials.append(material)
70        return tuple(instance)63        return tuple(instance)
7164
72    def create_alloy_from_args(self, args):65    def create_alloy_from_args(self, args):
n73        if any(arg.used for arg in args) or any(not isinstance(arg, Mixin) for arg in args):n66        if any(arg.used for arg in args) or any(not isinstance(arg, Material) for arg in args):
74            raise AssertionError("Materials have already been used.")67            raise AssertionError("Materials have already been used or are invalid.")
7568
76        used_materials = []69        used_materials = []
77        for arg in args:70        for arg in args:
n78            if isinstance(arg, Mixin):                n71            if isinstance(arg, Material):
79                for component in arg.components:72                for component in arg.components:
80                    if "_" in component:73                    if "_" in component:
81                        used_materials.extend(component.split("_"))74                        used_materials.extend(component.split("_"))
82                    else:75                    else:
83                        used_materials.append(component)76                        used_materials.append(component)
84            else:77            else:
85                raise ValueError("Invalid argument type.")78                raise ValueError("Invalid argument type.")
n86 n79            
87        class_name = "_".join(sorted(set(used_materials)))80        class_name = "_".join(sorted(set(used_materials)))
88        mass = sum(arg.mass for arg in args)81        mass = sum(arg.mass for arg in args)
n89        average_density = sum(arg.density for arg in args) / len(args)n
9082
91        if class_name not in self.dynamic_classes:83        if class_name not in self.dynamic_classes:
nn84            all_densities = [self.ACCESS_CLASS[comp].density if comp in self.ACCESS_CLASS else self.dynamic_classes[comp].density
85                             for comp in set(used_materials)]
86            average_density = sum(all_densities) / len(all_densities)
92            dynamic_class = type(class_name, (Mixin,), {'density': average_density})87            dynamic_class = type(class_name, (Material,), {'density': average_density})
93            self.dynamic_classes[class_name] = dynamic_class88            self.dynamic_classes[class_name] = dynamic_class
94        else:89        else:
95            dynamic_class = self.dynamic_classes[class_name]90            dynamic_class = self.dynamic_classes[class_name]
9691
n97        new_material = dynamic_class(mass, average_density)n92        new_material = dynamic_class(mass)
98        self.materials.append(new_material)93        self.materials.append(new_material)
99        self.all_materials.append(new_material)94        self.all_materials.append(new_material)
10095
101        for arg in args:96        for arg in args:
102            arg.used = True97            arg.used = True
10398
104        return new_material99        return new_material
105100
106    def can_build(self, required_volume):101    def can_build(self, required_volume):
n107        return sum(cur_material.volume for cur_material in self.materials) >= required_volumen102        total_volume = sum(material.volume for material in self.materials if not material.used)
103        return total_volume >= required_volume
108104
109    @classmethod105    @classmethod
110    def can_build_together(cls, required_volume):106    def can_build_together(cls, required_volume):
t111        return sum(cur_material.volume for cur_material in cls.all_materials if not cur_material.used) >= required_volumet107        total_volume = sum(material.volume for material in cls.all_materials if not material.used)
108        return total_volume >= required_volume
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op