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

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

7 точки общо

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

  1class Material:
  2    def __init__(self, mass, density):
  3        self.mass = mass
  4        self.density = density
  5        self.usable = True
  6
  7    @property
  8    def volume(self):
  9        return float(self.mass) / self.density
 10
 11    def use(self):
 12        if not self.usable:
 13            raise AssertionError("Material isn't usable.")
 14        self.usable = False
 15
 16
 17class Concrete(Material):
 18    def __init__(self, mass):
 19        super().__init__(mass, density=2500)
 20
 21
 22class Brick(Material):
 23    def __init__(self, mass):
 24        super().__init__(mass, density=2000)
 25
 26
 27class Stone(Material):
 28    def __init__(self, mass):
 29        super().__init__(mass, density=1600)
 30
 31
 32class Wood(Material):
 33    def __init__(self, mass):
 34        super().__init__(mass, density=600)
 35
 36
 37class Steel(Material):
 38    def __init__(self, mass):
 39        super().__init__(mass, density=7700)
 40
 41
 42class Factory:
 43    _fusions = {}
 44    __class_instances = []
 45
 46    def __init__(self):
 47        self.__class_instances.append(self)
 48        self._materials = []
 49
 50    def __del__(self):
 51        self.__class_instances.remove(self)
 52
 53    @property
 54    def volume(self):
 55        return sum(material.volume for material in self._materials if material.usable)
 56
 57    def can_build(self, volume):
 58        return self.volume >= volume
 59
 60    @classmethod
 61    def can_build_together(cls, volume):
 62        return sum(
 63            material.volume
 64            for factory in cls.__class_instances
 65            for material in factory._materials
 66            if material.usable
 67        ) >= volume
 68
 69    def __call__(self, *args, **kwargs):
 70        if args and kwargs:
 71            raise ValueError("Only positional or keyword arguments are allowed, not both.")
 72
 73        if not args and not kwargs:
 74            raise ValueError("Factory can't be called without arguments.")
 75        
 76        if kwargs:
 77            materials = []
 78            for name, mass in kwargs.items():
 79                material_class = globals().get(name)
 80                if not material_class:
 81                    material_class = self._fusions.get(name,None)
 82                    if not material_class or not issubclass(material_class, Material):
 83                        raise ValueError("Invalid material.")
 84                material = material_class(mass)
 85                materials.append(material)
 86                self._materials.append(material)
 87            return tuple(materials)
 88
 89        if args:
 90            new_args = []
 91            for material in args:
 92                if type(material).__name__.__contains__("_"):
 93                    # here we get the class name from the globals and use its init with the material mass
 94                    new_args += map(lambda name: globals()[name](material.mass), type(material).__name__.split("_"))
 95                else:
 96                    new_args.append(material)
 97
 98            class_name = "_".join(sorted(set(type(material).__name__ for material in new_args)))
 99            if class_name not in self._fusions:
100                density = sum(material.density for material in new_args) / len(new_args)
101
102                class Fusion(Material):
103                    def __init__(self, mass):
104                        super().__init__(mass, density=int(density))
105
106                Fusion.__name__ = class_name
107                self._fusions[class_name] = Fusion
108
109            total_mass = sum(material.mass for material in new_args)
110            new_material = self._fusions[class_name](total_mass)
111            for material in args:
112                material.use()
113            self._materials.append(new_material)
114            return new_material

.....FFF..
======================================================================
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 112, in __call__
material.use()
File "/tmp/solution.py", line 13, in use
raise AssertionError("Material isn't usable.")
AssertionError: Material isn't usable.

======================================================================
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 125, in test_positional_arguments_multiple_argument_with_dynamics
self.assertAlmostEqual(brick_concrete_stone.volume, 5.2131, places=4)
AssertionError: 5.213969503197245 != 5.2131 within 4 places (0.0008695031972454359 difference)

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

----------------------------------------------------------------------
Ran 10 tests in 0.018s

FAILED (failures=3)

Дискусия
Рада Димитрова
26.11.2024 19:11

Мерси.
Георги Кунчев
26.11.2024 18:49

След крайния срок всички тестове са публични. Виж под дефиницията на домашното.
Рада Димитрова
26.11.2024 18:35

Има ли шанс да видя теста за self.assertAlmostEqual(brick_concrete_stone.volume, 5.2131, places=4) AssertionError: 5.213969503197245 != 5.2131 within 4 places (0.0008695031972454359 difference), за да сравня какво не правя коректно при изчислението локално със същите примери?
История

f1class Material:f1class Material:
2    def __init__(self, mass, density):2    def __init__(self, mass, density):
3        self.mass = mass3        self.mass = mass
4        self.density = density4        self.density = density
5        self.usable = True5        self.usable = True
66
7    @property7    @property
8    def volume(self):8    def volume(self):
9        return float(self.mass) / self.density9        return float(self.mass) / self.density
1010
11    def use(self):11    def use(self):
12        if not self.usable:12        if not self.usable:
13            raise AssertionError("Material isn't usable.")13            raise AssertionError("Material isn't usable.")
14        self.usable = False14        self.usable = False
1515
1616
17class Concrete(Material):17class Concrete(Material):
18    def __init__(self, mass):18    def __init__(self, mass):
19        super().__init__(mass, density=2500)19        super().__init__(mass, density=2500)
2020
2121
22class Brick(Material):22class Brick(Material):
23    def __init__(self, mass):23    def __init__(self, mass):
24        super().__init__(mass, density=2000)24        super().__init__(mass, density=2000)
2525
2626
27class Stone(Material):27class Stone(Material):
28    def __init__(self, mass):28    def __init__(self, mass):
29        super().__init__(mass, density=1600)29        super().__init__(mass, density=1600)
3030
3131
32class Wood(Material):32class Wood(Material):
33    def __init__(self, mass):33    def __init__(self, mass):
34        super().__init__(mass, density=600)34        super().__init__(mass, density=600)
3535
3636
37class Steel(Material):37class Steel(Material):
38    def __init__(self, mass):38    def __init__(self, mass):
39        super().__init__(mass, density=7700)39        super().__init__(mass, density=7700)
4040
4141
42class Factory:42class Factory:
43    _fusions = {}43    _fusions = {}
44    __class_instances = []44    __class_instances = []
4545
46    def __init__(self):46    def __init__(self):
47        self.__class_instances.append(self)47        self.__class_instances.append(self)
48        self._materials = []48        self._materials = []
4949
50    def __del__(self):50    def __del__(self):
51        self.__class_instances.remove(self)51        self.__class_instances.remove(self)
5252
53    @property53    @property
54    def volume(self):54    def volume(self):
55        return sum(material.volume for material in self._materials if material.usable)55        return sum(material.volume for material in self._materials if material.usable)
5656
57    def can_build(self, volume):57    def can_build(self, volume):
58        return self.volume >= volume58        return self.volume >= volume
5959
60    @classmethod60    @classmethod
61    def can_build_together(cls, volume):61    def can_build_together(cls, volume):
62        return sum(62        return sum(
63            material.volume63            material.volume
64            for factory in cls.__class_instances64            for factory in cls.__class_instances
65            for material in factory._materials65            for material in factory._materials
66            if material.usable66            if material.usable
67        ) >= volume67        ) >= volume
6868
69    def __call__(self, *args, **kwargs):69    def __call__(self, *args, **kwargs):
70        if args and kwargs:70        if args and kwargs:
71            raise ValueError("Only positional or keyword arguments are allowed, not both.")71            raise ValueError("Only positional or keyword arguments are allowed, not both.")
7272
73        if not args and not kwargs:73        if not args and not kwargs:
74            raise ValueError("Factory can't be called without arguments.")74            raise ValueError("Factory can't be called without arguments.")
75        75        
76        if kwargs:76        if kwargs:
77            materials = []77            materials = []
78            for name, mass in kwargs.items():78            for name, mass in kwargs.items():
79                material_class = globals().get(name)79                material_class = globals().get(name)
tt80                if not material_class:
81                    material_class = self._fusions.get(name,None)
80                if not material_class or not issubclass(material_class, Material):82                    if not material_class or not issubclass(material_class, Material):
81                    raise ValueError("Invalid material.")83                        raise ValueError("Invalid material.")
82                material = material_class(mass)84                material = material_class(mass)
83                materials.append(material)85                materials.append(material)
84                self._materials.append(material)86                self._materials.append(material)
85            return tuple(materials)87            return tuple(materials)
8688
87        if args:89        if args:
88            new_args = []90            new_args = []
89            for material in args:91            for material in args:
90                if type(material).__name__.__contains__("_"):92                if type(material).__name__.__contains__("_"):
91                    # here we get the class name from the globals and use its init with the material mass93                    # here we get the class name from the globals and use its init with the material mass
92                    new_args += map(lambda name: globals()[name](material.mass), type(material).__name__.split("_"))94                    new_args += map(lambda name: globals()[name](material.mass), type(material).__name__.split("_"))
93                else:95                else:
94                    new_args.append(material)96                    new_args.append(material)
9597
96            class_name = "_".join(sorted(set(type(material).__name__ for material in new_args)))98            class_name = "_".join(sorted(set(type(material).__name__ for material in new_args)))
97            if class_name not in self._fusions:99            if class_name not in self._fusions:
98                density = sum(material.density for material in new_args) / len(new_args)100                density = sum(material.density for material in new_args) / len(new_args)
99101
100                class Fusion(Material):102                class Fusion(Material):
101                    def __init__(self, mass):103                    def __init__(self, mass):
102                        super().__init__(mass, density=int(density))104                        super().__init__(mass, density=int(density))
103105
104                Fusion.__name__ = class_name106                Fusion.__name__ = class_name
105                self._fusions[class_name] = Fusion107                self._fusions[class_name] = Fusion
106108
107            total_mass = sum(material.mass for material in new_args)109            total_mass = sum(material.mass for material in new_args)
108            new_material = self._fusions[class_name](total_mass)110            new_material = self._fusions[class_name](total_mass)
109            for material in args:111            for material in args:
110                material.use()112                material.use()
111            self._materials.append(new_material)113            self._materials.append(new_material)
112            return new_material114            return new_material
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op