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

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

7 точки общо

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

  1class Material:
  2    def __init__(self, mass, density, is_alloy = False):
  3        self.density = density
  4        self.mass = mass
  5        self.used = False
  6        self.alloy = is_alloy
  7    
  8    @property
  9    def volume(self):
 10        return self.mass / self.density
 11    
 12    def __str__(self):
 13        return self.__class__.__name__
 14
 15
 16class Concrete(Material):
 17    DENSITY = 2500
 18    def __init__(self, arg):
 19        super().__init__(arg, self.DENSITY)
 20
 21
 22class Brick(Material):
 23    DENSITY = 2000
 24    def __init__(self, arg):
 25        super().__init__(arg, self.DENSITY)
 26    
 27
 28class Stone(Material):
 29    DENSITY = 1600
 30    def __init__(self, arg):
 31        super().__init__(arg, self.DENSITY)
 32
 33
 34class Wood(Material):
 35    DENSITY = 600
 36    def __init__(self, arg):
 37        super().__init__(arg, self.DENSITY)
 38
 39
 40class Steel(Material):
 41    DENSITY = 7700
 42    def __init__(self, arg):
 43        super().__init__(arg, self.DENSITY)
 44
 45
 46class Factory:
 47    factories = [] 
 48    dynamic_classes = {}  
 49
 50    def __init__(self):
 51        self.used_materials = []
 52        self.existing_alloys = set()
 53        self.__class__.factories.append(self) 
 54    
 55    def get_subclass(self, name):
 56        subclasses = {cls.__name__: cls for cls in Material.__subclasses__()}
 57        if name in subclasses:
 58            return subclasses[name]
 59        return None 
 60
 61    def call_with_named_args(self, kwargs):
 62        result = []
 63        for key, value in kwargs.items():
 64            if self.get_subclass(key):
 65                result.append(self.get_subclass(key)(value))
 66            else:
 67                raise ValueError("invalid materials") 
 68        self.materials = tuple(result)
 69    
 70    def call_with_pos_args(self, args):
 71        used_materials = []
 72        materials_list = []
 73        new_mass = new_density = 0
 74        names = []
 75        for material in args:
 76            if self.get_subclass(str(material)) is None:
 77                raise TypeError("invalid material")
 78            elif material.used:
 79                raise AssertionError("material is already used")
 80            elif material.alloy == False:
 81                names.append(str(material))
 82                new_density += material.density
 83                materials_list.append(material)
 84            else:
 85                for m in material.materials:
 86                    names.append(str(m))
 87                    new_density += m.density
 88                    materials_list.append(m)
 89            used_materials.append(material)
 90            material.used = True
 91            new_mass += material.mass
 92        new_density = new_density / len(names)
 93        new_name = "_".join(sorted(names))
 94        if new_name in Factory.dynamic_classes:
 95            new_class = Factory.dynamic_classes[new_name]
 96        else:
 97            def init(self, mass):
 98                Material.__init__(self, mass, new_density, True)
 99                self.materials = materials_list
100            
101            new_class = type(new_name, (Material,), {"__init__": init})
102            Factory.dynamic_classes[new_name] = new_class
103        new_instance = new_class(new_mass)
104        self.used_materials.extend(used_materials)
105        self.existing_alloys.add(new_instance)
106        return new_instance
107
108    def __call__(self, *args, **kwargs):
109        if not args and kwargs:
110            self.call_with_named_args(kwargs)
111            return self.materials
112        elif args and not kwargs:
113            new_class_instance = self.call_with_pos_args(args)
114            return new_class_instance
115        raise ValueError("invalid arguments")
116    
117    def sum_of_volumes(self):
118        sum_of_volumes = 0
119        for material in self.used_materials:
120            if not material.used:
121                sum_of_volumes += material.volume
122        for material in self.existing_alloys:
123            if not material.used:
124                sum_of_volumes += material.volume
125        return sum_of_volumes
126
127    def can_build(self, needed_volume):
128        sum_of_volumes = self.sum_of_volumes()
129        return needed_volume <= sum_of_volumes
130
131    @classmethod
132    def can_build_together(cls, needed_volume):
133        sum_of_volumes = 0
134        for factory in cls.factories:
135            sum_of_volumes += factory.sum_of_volumes()
136        return needed_volume <= sum_of_volumes

.F...F.F..
======================================================================
FAIL: test_can_build (test.TestFactory.test_can_build)
Test can_build methods.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/tmp/test.py", line 174, in test_can_build
self.assertTrue(self.factory1.can_build(2.0))
AssertionError: False is not true

======================================================================
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 113, in __call__
new_class_instance = self.call_with_pos_args(args)
^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
File "/tmp/solution.py", line 79, in call_with_pos_args
raise AssertionError("material is already used")
AssertionError: material is already used

======================================================================
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=3)

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