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

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

9 точки общо

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

  1class Material:
  2    """
  3    Define a material with a given mass and calculate its volume using a predefined density.
  4    """
  5    def __init__(self, mass):
  6        self.mass = mass
  7 
  8    @property
  9    def volume(self):
 10        return self.mass / self.DENSITY
 11 
 12 
 13class Concrete(Material):
 14    DENSITY = 2500
 15 
 16 
 17class Brick(Material):
 18    DENSITY = 2000
 19 
 20 
 21class Stone(Material):
 22    DENSITY = 1600
 23 
 24 
 25class Wood(Material):
 26    DENSITY = 600
 27 
 28 
 29class Steel(Material):
 30    DENSITY = 7700
 31 
 32 
 33class Factory:
 34    """
 35    Manage the creation and combination of materials while enforcing reuse and uniqueness rules.
 36    """
 37    _used_instances = []
 38 
 39    _dynamic_classes = {}
 40 
 41    _all_factories = []
 42 
 43    _all_base_materials = {
 44        "Concrete": Concrete,
 45        "Brick": Brick,
 46        "Stone": Stone,
 47        "Wood": Wood,
 48        "Steel": Steel,
 49    }
 50 
 51    def __init__(self):
 52        self._created_materials = []
 53        self._all_factories.append(self) 
 54 
 55    def __call__(self, *args, **kwargs):
 56        if not args and not kwargs:
 57            raise ValueError("Cannot have an instance without an argument or arguments.")
 58        if args and kwargs:
 59            raise ValueError("There cannot be an instance with a mixture of positional and named arguments.")
 60 
 61        if args:
 62            return self._create_from_args(*args)
 63        return self._create_from_kwargs(**kwargs)
 64 
 65    def _create_from_args(self, *args):
 66        if not self._validate_unused_materials(args):
 67            raise AssertionError("One or more materials have been used.")
 68        self._used_instances.extend(args)
 69 
 70        components = {}
 71 
 72        for material in args:
 73            material_name = material.__class__.__name__
 74            if material_name in self._all_base_materials.keys():
 75                components[material_name] = self._all_base_materials[material_name]
 76            else:
 77                class_components = material.__class__.__name__.split("_")
 78                for component_name in class_components:
 79                    components[component_name] = self._all_base_materials[component_name]
 80 
 81        class_name = "_".join(sorted(components.keys()))
 82 
 83        if class_name not in self._dynamic_classes.keys():
 84            self._create_dynamic_material(class_name, components)
 85 
 86        total_mass = 0
 87        for material in args:
 88            total_mass += material.mass
 89        new_material = self._dynamic_classes[class_name](total_mass)
 90        self._created_materials.append(new_material)
 91        return new_material
 92 
 93    def _create_from_kwargs(self, **kwargs):
 94        created_instances = []
 95        for name, mass in kwargs.items():
 96            if not self._validate_material_name(name):
 97                raise ValueError("Invalid material name")
 98            if name in self._all_base_materials:
 99                material_class = self._all_base_materials[name](mass)
100                created_instances.append(material_class)
101            elif name in self._dynamic_classes:
102                material_class = self._dynamic_classes[name](mass)
103                created_instances.append(material_class)
104 
105        self._created_materials.extend(created_instances)
106        return tuple(created_instances)
107 
108    def _create_dynamic_material(self, name, components):
109        total_density = 0
110        for current in components.values():
111            total_density += current.DENSITY
112 
113        if len(components):
114            num_components = len(components)
115        else:
116            num_components = 1
117        average_density = total_density / num_components
118
119        dynamic_material = type(name,
120                                (Material,), 
121                                {
122                                    'DENSITY': average_density 
123                                }
124                            )
125        self._dynamic_classes[name] = dynamic_material
126 
127    def _validate_unused_materials(self, materials):
128        return all(material not in self._used_instances for material in materials)
129 
130    def _validate_material_name(self, name):
131        return name in self._all_base_materials or name in self._dynamic_classes
132 
133    def can_build(self, wall_volume):
134        current_volume = 0
135        for material in self._created_materials:
136            if material not in self._used_instances:
137                current_volume += material.volume
138        return current_volume >= wall_volume
139 
140    @classmethod
141    def can_build_together(cls, wall_volume):
142        total_volume = 0
143        for factory in cls._all_factories:
144            for material in factory._created_materials:
145                if material not in cls._used_instances:
146                    total_volume += material.volume
147        return total_volume >= wall_volume
148    

.......F..
======================================================================
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.010s

FAILED (failures=1)

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

f1class Material:f1class Material:
2    """2    """
3    Define a material with a given mass and calculate its volume using a predefined density.3    Define a material with a given mass and calculate its volume using a predefined density.
4    """4    """
5    def __init__(self, mass):5    def __init__(self, mass):
6        self.mass = mass6        self.mass = mass
7 7 
8    @property8    @property
9    def volume(self):9    def volume(self):
10        return self.mass / self.DENSITY10        return self.mass / self.DENSITY
11 11 
12 12 
13class Concrete(Material):13class Concrete(Material):
14    DENSITY = 250014    DENSITY = 2500
15 15 
16 16 
17class Brick(Material):17class Brick(Material):
18    DENSITY = 200018    DENSITY = 2000
19 19 
20 20 
21class Stone(Material):21class Stone(Material):
22    DENSITY = 160022    DENSITY = 1600
23 23 
24 24 
25class Wood(Material):25class Wood(Material):
26    DENSITY = 60026    DENSITY = 600
27 27 
28 28 
29class Steel(Material):29class Steel(Material):
30    DENSITY = 770030    DENSITY = 7700
31 31 
32 32 
33class Factory:33class Factory:
34    """34    """
35    Manage the creation and combination of materials while enforcing reuse and uniqueness rules.35    Manage the creation and combination of materials while enforcing reuse and uniqueness rules.
36    """36    """
37    _used_instances = []37    _used_instances = []
n38 n38 
39    _dynamic_classes = {}39    _dynamic_classes = {}
n40 n40 
41    _all_factories = []41    _all_factories = []
n42 n42 
43    _all_base_materials = {43    _all_base_materials = {
44        "Concrete": Concrete,44        "Concrete": Concrete,
45        "Brick": Brick,45        "Brick": Brick,
46        "Stone": Stone,46        "Stone": Stone,
47        "Wood": Wood,47        "Wood": Wood,
48        "Steel": Steel,48        "Steel": Steel,
49    }49    }
50 50 
51    def __init__(self):51    def __init__(self):
52        self._created_materials = []52        self._created_materials = []
n53        Factory._all_factories.append(self) n53        self._all_factories.append(self) 
54        54 
55    def __call__(self, *args, **kwargs):55    def __call__(self, *args, **kwargs):
56        if not args and not kwargs:56        if not args and not kwargs:
57            raise ValueError("Cannot have an instance without an argument or arguments.")57            raise ValueError("Cannot have an instance without an argument or arguments.")
58        if args and kwargs:58        if args and kwargs:
59            raise ValueError("There cannot be an instance with a mixture of positional and named arguments.")59            raise ValueError("There cannot be an instance with a mixture of positional and named arguments.")
60 60 
61        if args:61        if args:
62            return self._create_from_args(*args)62            return self._create_from_args(*args)
63        return self._create_from_kwargs(**kwargs)63        return self._create_from_kwargs(**kwargs)
64 64 
65    def _create_from_args(self, *args):65    def _create_from_args(self, *args):
66        if not self._validate_unused_materials(args):66        if not self._validate_unused_materials(args):
67            raise AssertionError("One or more materials have been used.")67            raise AssertionError("One or more materials have been used.")
n68        Factory._used_instances.extend(args)n68        self._used_instances.extend(args)
69 69 
70        components = {}70        components = {}
n71        n71 
72        for material in args:72        for material in args:
73            material_name = material.__class__.__name__73            material_name = material.__class__.__name__
n74            if material_name in Factory._all_base_materials.keys():n74            if material_name in self._all_base_materials.keys():
75                components[material_name] = Factory._all_base_materials[material_name]75                components[material_name] = self._all_base_materials[material_name]
76            else:76            else:
77                class_components = material.__class__.__name__.split("_")77                class_components = material.__class__.__name__.split("_")
78                for component_name in class_components:78                for component_name in class_components:
n79                    components[component_name] = Factory._all_base_materials[component_name]n79                    components[component_name] = self._all_base_materials[component_name]
80 80 
81        class_name = "_".join(sorted(components.keys()))81        class_name = "_".join(sorted(components.keys()))
82 82 
n83        if class_name not in Factory._dynamic_classes.keys():n83        if class_name not in self._dynamic_classes.keys():
84            self._create_dynamic_material(class_name, components)84            self._create_dynamic_material(class_name, components)
85 85 
86        total_mass = 086        total_mass = 0
87        for material in args:87        for material in args:
88            total_mass += material.mass88            total_mass += material.mass
89        new_material = self._dynamic_classes[class_name](total_mass)89        new_material = self._dynamic_classes[class_name](total_mass)
90        self._created_materials.append(new_material)90        self._created_materials.append(new_material)
91        return new_material91        return new_material
92 92 
93    def _create_from_kwargs(self, **kwargs):93    def _create_from_kwargs(self, **kwargs):
94        created_instances = []94        created_instances = []
95        for name, mass in kwargs.items():95        for name, mass in kwargs.items():
96            if not self._validate_material_name(name):96            if not self._validate_material_name(name):
97                raise ValueError("Invalid material name")97                raise ValueError("Invalid material name")
n98            if name in Factory._all_base_materials:n98            if name in self._all_base_materials:
99                material_class = Factory._all_base_materials[name](mass)99                material_class = self._all_base_materials[name](mass)
100                created_instances.append(material_class)100                created_instances.append(material_class)
n101            elif name in Factory._dynamic_classes:n101            elif name in self._dynamic_classes:
102                material_class = Factory._dynamic_classes[name](mass)102                material_class = self._dynamic_classes[name](mass)
103                created_instances.append(material_class)103                created_instances.append(material_class)
n104            n104 
105        self._created_materials.extend(created_instances)105        self._created_materials.extend(created_instances)
106        return tuple(created_instances)106        return tuple(created_instances)
107 107 
108    def _create_dynamic_material(self, name, components):108    def _create_dynamic_material(self, name, components):
109        total_density = 0109        total_density = 0
110        for current in components.values():110        for current in components.values():
111            total_density += current.DENSITY111            total_density += current.DENSITY
n112 n112 
113        if len(components):113        if len(components):
114            num_components = len(components)114            num_components = len(components)
115        else:115        else:
116            num_components = 1116            num_components = 1
117        average_density = total_density / num_components117        average_density = total_density / num_components
n118 n118 
119        sorted_component_names = "_".join(sorted(components.keys()))
120        dynamic_material = type(sorted_component_names,119        dynamic_material = type(name,
121                                (Material,), 120                                (Material,), 
122                                {121                                {
123                                    'DENSITY': average_density 122                                    'DENSITY': average_density 
124                                }123                                }
125                            )124                            )
n126        Factory._dynamic_classes[sorted_component_names] = dynamic_materialn125        self._dynamic_classes[name] = dynamic_material
127 126 
128    def _validate_unused_materials(self, materials):127    def _validate_unused_materials(self, materials):
n129        return all(material not in Factory._used_instances for material in materials)n128        return all(material not in self._used_instances for material in materials)
130 129 
131    def _validate_material_name(self, name):130    def _validate_material_name(self, name):
n132        return name in Factory._all_base_materials or name in Factory._dynamic_classesn131        return name in self._all_base_materials or name in self._dynamic_classes
133 132 
134    def can_build(self, wall_volume):133    def can_build(self, wall_volume):
135        current_volume = 0134        current_volume = 0
136        for material in self._created_materials:135        for material in self._created_materials:
n137            if material not in Factory._used_instances:n136            if material not in self._used_instances:
138                current_volume += material.volume137                current_volume += material.volume
139        return current_volume >= wall_volume138        return current_volume >= wall_volume
n140 n139 
141    @classmethod140    @classmethod
142    def can_build_together(cls, wall_volume):141    def can_build_together(cls, wall_volume):
143        total_volume = 0142        total_volume = 0
144        for factory in cls._all_factories:143        for factory in cls._all_factories:
145            for material in factory._created_materials:144            for material in factory._created_materials:
146                if material not in cls._used_instances:145                if material not in cls._used_instances:
147                    total_volume += material.volume146                    total_volume += material.volume
148        return total_volume >= wall_volume147        return total_volume >= wall_volume
tt148    
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op