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

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

9 точки общо

9 успешни теста
1 неуспешни теста
Код
Скрий всички коментари

  1CONCRETE = 2500
  2BRICK = 2000
  3STONE = 1600
  4WOOD = 600
  5STEEL = 7700
  6
  7
  8class Material:
  9    def __init__(self, mass, density):
 10        self.mass = mass
 11        self.density = density
 12        self._used = False
 13        self._number_of_materials_in_it = 1
 14
 15    @property
 16    def volume(self):
 17        return self.mass / self.density
 18
 19    def is_used(self):
 20        if self._used:
 21            raise AssertionError
 22        self._used = True
 23
 24
 25class Concrete(Material):
 26    def __init__(self, mass):
 27        super().__init__(mass, CONCRETE)
 28
 29
 30class Brick(Material):
 31    def __init__(self, mass):
 32        super().__init__(mass, BRICK)
 33
 34
 35class Stone(Material):
 36    def __init__(self, mass):
 37        super().__init__(mass, STONE)
 38
 39
 40class Wood(Material):
 41    def __init__(self, mass):
 42        super().__init__(mass, WOOD)
 43
 44
 45class Steel(Material):
 46    def __init__(self, mass):
 47        super().__init__(mass, STEEL)
 48
 49
 50class Factory:
 51
 52    MATERIAL_NAMES = {
 53        "Brick": Brick,
 54        "Concrete": Concrete,
 55        "Stone": Stone,
 56        "Wood": Wood,
 57        "Steel": Steel,
 58    }
 59
 60    all_created_materials = []
 61
 62    def __init__(self):
 63        self.created_materials = []
 64
 65    def _create_class_name_from_materials(self, materials):
 66        class_names = []
 67        for material in materials:
 68            class_name = type(material).__name__
 69            class_names.extend(class_name.split("_"))
 70
 71        sorted_class_names = sorted(class_names)
 72        return "_".join(sorted_class_names)
 73
 74    def _calculate_density_and_ingredients(self, materials):
 75        new_class_density = 0
 76        number_ingredients = 0
 77        for material in materials:
 78            new_class_density += material.density * material._number_of_materials_in_it
 79            number_ingredients += material._number_of_materials_in_it
 80        new_class_density /= number_ingredients
 81        return new_class_density, number_ingredients
 82
 83    def _create_new_class(self, class_name, density):
 84        new_class = type(class_name, (Material,), {
 85            '__init__': lambda self, mass: super(type(self), self).__init__(mass, density)
 86        })
 87        self.MATERIAL_NAMES[class_name] = new_class
 88        return new_class
 89
 90    def _handle_kwargs(self, kwargs):
 91        result = []
 92        for material_name, material_mass in kwargs.items():
 93            if (material_name in self.MATERIAL_NAMES):
 94                material_instance = self.MATERIAL_NAMES[material_name](material_mass)
 95                self.created_materials.append(material_instance)
 96                Factory.all_created_materials.append(material_instance)
 97                result.append(material_instance)
 98            else:
 99                raise ValueError
100        return tuple(result)
101
102    def _handle_args(self, args):
103        temp_used_materials = []
104
105        try:
106            for material in args:
107                material.is_used()
108                temp_used_materials.append(material)
109
110            class_name = self._create_class_name_from_materials(args)
111
112            if class_name in self.MATERIAL_NAMES:
113                new_mass = sum(material.mass for material in args)
114                result_material = self.MATERIAL_NAMES[class_name](new_mass)
115                self.created_materials.append(result_material)
116                Factory.all_created_materials.append(result_material)
117                return result_material
118            else:
119                new_class_density, number_ingredients = self._calculate_density_and_ingredients(args)
120                new_class = self._create_new_class(class_name, new_class_density)
121                new_mass = sum(material.mass for material in args)
122                result_material = new_class(new_mass)
123                result_material._number_of_materials_in_it = number_ingredients
124                self.created_materials.append(result_material)
125                Factory.all_created_materials.append(result_material)
126                return result_material
127
128        except AssertionError as e:
129            for material in temp_used_materials:
130                material._used = False
131            raise e
132
133    def __call__(self, *args, **kwargs):
134        if args and kwargs:
135            raise ValueError
136        if not args and not kwargs:
137            raise ValueError
138
139        self.created_materials.clear()
140
141        if kwargs:
142            return self._handle_kwargs(kwargs)
143
144        if args:
145            return self._handle_args(args)
146
147    def can_build(self, needed_volume):
148        total_volume = sum(
149            material.volume for material in self.created_materials)
150        return total_volume >= needed_volume
151
152    @classmethod
153    def can_build_together(cls, needed_volume):
154        total_volume = sum(
155            material.volume for material in cls.all_created_materials)
156        return total_volume >= needed_volume

.F........
======================================================================
FAIL: test_can_build (test.TestFactory.test_can_build)
Test can_build methods.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 177, in test_can_build
self.assertFalse(solution.Factory.can_build_together(6.0001))
AssertionError: True is not false

----------------------------------------------------------------------
Ran 10 tests in 0.015s

FAILED (failures=1)

Дискусия
История
Това решение има само една версия.