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

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

8 точки общо

8 успешни теста
2 неуспешни теста
Код

  1class Material:
  2    """Base material class."""
  3    density = 1
  4
  5    def __init__(self, weight):
  6        self.weight = weight
  7
  8    @property
  9    def volume(self):
 10        """Calculate material's volume."""
 11        return self.weight / self.density
 12
 13
 14class Concrete(Material):
 15    density = 2500
 16
 17
 18class Brick(Material):
 19    density = 2000
 20
 21
 22class Stone(Material):
 23    density = 1600
 24
 25
 26class Wood(Material):
 27    density = 600
 28
 29
 30class Steel(Material):
 31    density = 7700
 32
 33
 34class Factory:
 35    """Create (new) materials."""
 36    # dict to keep track of existing materials
 37    existing_materials = {"Concrete": Concrete, "Brick": Brick, "Stone": Stone,
 38                      "Wood": Wood, "Steel": Steel}
 39    used_materials = [] # keeping the used positional arguments here
 40    available_materials = [] # valid materials for can_build_together()
 41
 42    def __init__(self):
 43        self.materials = [] # valid materials for can_build()
 44
 45    def __call__(self, *args, **kwargs):
 46        if (len(args) and len(kwargs)
 47            or not len(args) and not len(kwargs)):
 48            raise ValueError("Only positional or only keyword arguments allowed.")
 49
 50        if len(kwargs):
 51            created_materials = []
 52            for material in kwargs.items():
 53                if material[0] not in self.existing_materials:
 54                    raise ValueError(f"No such material: {material[0]}.")
 55                created_materials.append(self.existing_materials[material[0]](material[1]))
 56            self.materials.extend(created_materials)
 57            Factory.available_materials.extend(created_materials)
 58            return tuple(created_materials)
 59
 60        # else: len(args) > 0
 61        for pos_arg in args:
 62            if pos_arg in Factory.used_materials:
 63                raise AssertionError("Material has already been used.")
 64            if pos_arg in self.materials:
 65                self.materials.remove(pos_arg)
 66
 67            # in case a material from another factory is passed
 68            if pos_arg in Factory.available_materials:
 69                Factory.available_materials.remove(pos_arg)
 70            Factory.used_materials.append(pos_arg)
 71
 72        materials_to_combine = list(map(lambda x: type(x).__name__, args))
 73        for element in materials_to_combine:
 74            separated_element = element.split('_')
 75            materials_to_combine.remove(element)
 76            materials_to_combine.extend(separated_element)
 77        materials_to_combine.sort()
 78        new_material_name = '_'.join(materials_to_combine)
 79
 80        sum_weights = sum(list(map(lambda x: x.weight, args)))
 81        sum_density = sum(list(map(lambda x: x.density, 
 82                                   [cls for cls in self.existing_materials.values()
 83                                    if cls.__name__ in materials_to_combine])))
 84
 85        if new_material_name not in self.existing_materials:
 86            self.existing_materials[new_material_name] = type(
 87                    new_material_name,
 88                    (Material,),
 89                    {"density": sum_density / len(materials_to_combine)}
 90                )
 91        new_material = self.existing_materials[new_material_name](sum_weights)
 92        self.materials.append(new_material)
 93        Factory.available_materials.append(new_material)
 94        return new_material
 95
 96    def can_build(self, wall_volume):
 97        """Whether instance's materials' volumes are enough to build a wall."""
 98        # in a separate list in case another factory has used materials from the current one
 99        valid_materials = [material for material in self.materials
100                           if material in Factory.available_materials]
101        return sum(list(map(lambda x: x.volume, valid_materials))) >= wall_volume
102
103    @classmethod
104    def can_build_together(cls, wall_volume):
105        """Whether class' materials' volumes are enough to build a wall."""
106        return sum(list(map(lambda x: x.volume, Factory.available_materials))) >= wall_volume

.....FF...
======================================================================
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 63, in __call__
raise AssertionError("Material has already been used.")
AssertionError: Material has already been used.

======================================================================
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 128, in test_positional_arguments_multiple_argument_with_dynamics
self.assertEqual(mega_material.__class__.__name__,
AssertionError: 'Brick_Concrete_Stone_Steel_Wood' != 'Brick_Concrete_Steel_Stone_Wood'
- Brick_Concrete_Stone_Steel_Wood
? ------
+ Brick_Concrete_Steel_Stone_Wood
? ++++++

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

FAILED (failures=2)

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

f1class Material:f1class Material:
2    """Base material class."""2    """Base material class."""
3    density = 13    density = 1
44
5    def __init__(self, weight):5    def __init__(self, weight):
6        self.weight = weight6        self.weight = weight
77
8    @property8    @property
9    def volume(self):9    def volume(self):
10        """Calculate material's volume."""10        """Calculate material's volume."""
11        return self.weight / self.density11        return self.weight / self.density
1212
1313
14class Concrete(Material):14class Concrete(Material):
15    density = 250015    density = 2500
1616
1717
18class Brick(Material):18class Brick(Material):
19    density = 200019    density = 2000
2020
2121
22class Stone(Material):22class Stone(Material):
23    density = 160023    density = 1600
2424
2525
26class Wood(Material):26class Wood(Material):
27    density = 60027    density = 600
2828
2929
30class Steel(Material):30class Steel(Material):
31    density = 770031    density = 7700
3232
3333
n34# global dict to keep track of existing materialsn
35existing_materials = {"Concrete": Concrete, "Brick": Brick, "Stone": Stone,
36                      "Wood": Wood, "Steel": Steel}
37 
38 
39class Factory:34class Factory:
40    """Create (new) materials."""35    """Create (new) materials."""
nn36    # dict to keep track of existing materials
37    existing_materials = {"Concrete": Concrete, "Brick": Brick, "Stone": Stone,
38                      "Wood": Wood, "Steel": Steel}
41    used_materials = [] # keeping the used positional arguments here39    used_materials = [] # keeping the used positional arguments here
42    available_materials = [] # valid materials for can_build_together()40    available_materials = [] # valid materials for can_build_together()
4341
44    def __init__(self):42    def __init__(self):
45        self.materials = [] # valid materials for can_build()43        self.materials = [] # valid materials for can_build()
4644
47    def __call__(self, *args, **kwargs):45    def __call__(self, *args, **kwargs):
48        if (len(args) and len(kwargs)46        if (len(args) and len(kwargs)
49            or not len(args) and not len(kwargs)):47            or not len(args) and not len(kwargs)):
50            raise ValueError("Only positional or only keyword arguments allowed.")48            raise ValueError("Only positional or only keyword arguments allowed.")
5149
52        if len(kwargs):50        if len(kwargs):
53            created_materials = []51            created_materials = []
n54            for material in kwargs:n52            for material in kwargs.items():
55                if material not in existing_materials:53                if material[0] not in self.existing_materials:
56                    raise ValueError(f"No such material: {material}.")54                    raise ValueError(f"No such material: {material[0]}.")
57                created_materials.append(existing_materials[material](kwargs[material]))55                created_materials.append(self.existing_materials[material[0]](material[1]))
58            self.materials.extend(created_materials)56            self.materials.extend(created_materials)
59            Factory.available_materials.extend(created_materials)57            Factory.available_materials.extend(created_materials)
60            return tuple(created_materials)58            return tuple(created_materials)
6159
62        # else: len(args) > 060        # else: len(args) > 0
n63        for used in args:n61        for pos_arg in args:
64            if used in Factory.used_materials:62            if pos_arg in Factory.used_materials:
65                raise AssertionError("Material has already been used.")63                raise AssertionError("Material has already been used.")
n66            if used in self.materials:n64            if pos_arg in self.materials:
67                self.materials.remove(used)65                self.materials.remove(pos_arg)
6866
69            # in case a material from another factory is passed67            # in case a material from another factory is passed
n70            if used in Factory.available_materials:n68            if pos_arg in Factory.available_materials:
71                Factory.available_materials.remove(used)69                Factory.available_materials.remove(pos_arg)
72            Factory.used_materials.append(used)70            Factory.used_materials.append(pos_arg)
7371
74        materials_to_combine = list(map(lambda x: type(x).__name__, args))72        materials_to_combine = list(map(lambda x: type(x).__name__, args))
75        for element in materials_to_combine:73        for element in materials_to_combine:
n76            if '_' in element:n
77                separated_element = element.split('_')74            separated_element = element.split('_')
78                materials_to_combine.remove(element)75            materials_to_combine.remove(element)
79                materials_to_combine.extend(separated_element)76            materials_to_combine.extend(separated_element)
80        materials_to_combine.sort()77        materials_to_combine.sort()
81        new_material_name = '_'.join(materials_to_combine)78        new_material_name = '_'.join(materials_to_combine)
8279
83        sum_weights = sum(list(map(lambda x: x.weight, args)))80        sum_weights = sum(list(map(lambda x: x.weight, args)))
n84        sum_density = sum(list(map(lambda x: x.density, [cls for cls in existing_materials.values()n81        sum_density = sum(list(map(lambda x: x.density, 
82                                   [cls for cls in self.existing_materials.values()
85                                                         if cls.__name__ in materials_to_combine])))83                                    if cls.__name__ in materials_to_combine])))
8684
n87        if new_material_name not in existing_materials:n85        if new_material_name not in self.existing_materials:
88            existing_materials[new_material_name] = type(86            self.existing_materials[new_material_name] = type(
89                    new_material_name,87                    new_material_name,
90                    (Material,),88                    (Material,),
91                    {"density": sum_density / len(materials_to_combine)}89                    {"density": sum_density / len(materials_to_combine)}
92                )90                )
t93        to_add = existing_materials[new_material_name](sum_weights)t91        new_material = self.existing_materials[new_material_name](sum_weights)
94        self.materials.append(to_add)92        self.materials.append(new_material)
95        Factory.available_materials.append(to_add)93        Factory.available_materials.append(new_material)
96        return to_add94        return new_material
9795
98    def can_build(self, wall_volume):96    def can_build(self, wall_volume):
99        """Whether instance's materials' volumes are enough to build a wall."""97        """Whether instance's materials' volumes are enough to build a wall."""
100        # in a separate list in case another factory has used materials from the current one98        # in a separate list in case another factory has used materials from the current one
101        valid_materials = [material for material in self.materials99        valid_materials = [material for material in self.materials
102                           if material in Factory.available_materials]100                           if material in Factory.available_materials]
103        return sum(list(map(lambda x: x.volume, valid_materials))) >= wall_volume101        return sum(list(map(lambda x: x.volume, valid_materials))) >= wall_volume
104102
105    @classmethod103    @classmethod
106    def can_build_together(cls, wall_volume):104    def can_build_together(cls, wall_volume):
107        """Whether class' materials' volumes are enough to build a wall."""105        """Whether class' materials' volumes are enough to build a wall."""
108        return sum(list(map(lambda x: x.volume, Factory.available_materials))) >= wall_volume106        return sum(list(map(lambda x: x.volume, Factory.available_materials))) >= wall_volume
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op