Домашни > Another brick in the wall > Решения > Решението на Ивайло Кънчев

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

10 точки общо

10 успешни теста
0 неуспешни теста
Код (Малко refactoring...)

  1BASICS_DENSITY = {
  2    'Concrete': 2500,
  3    'Brick': 2000,
  4    'Stone': 1600,
  5    'Wood': 600,
  6    'Steel': 7700
  7}
  8
  9class Material:
 10    _DENSITY = 1
 11
 12    def __init__(self, mass):
 13        self.mass = mass
 14        self.is_used = False
 15
 16    @property
 17    def volume(self):
 18        return self.mass / self._DENSITY
 19
 20
 21class Concrete(Material):
 22    _DENSITY = BASICS_DENSITY['Concrete']
 23
 24
 25class Brick(Material):
 26    _DENSITY = BASICS_DENSITY['Brick']
 27
 28
 29class Stone(Material):
 30    _DENSITY = BASICS_DENSITY['Stone']
 31
 32
 33class Wood(Material):
 34    _DENSITY = BASICS_DENSITY['Wood']
 35
 36
 37class Steel(Material):
 38    _DENSITY = BASICS_DENSITY['Steel']
 39
 40
 41class Factory:
 42    """Create different building materials including some interesting 'alloys'.
 43    A fancy way to demonstrate the factory design pattern"""
 44
 45    _valid_classes = {
 46        'Concrete': Concrete,
 47        'Brick': Brick,
 48        'Stone': Stone,
 49        'Wood': Wood,
 50        'Steel': Steel
 51    }  # we start with the basic classes first and gradually add dynamic ones
 52
 53    _all_produced_materials = []
 54
 55    def __init__(self):
 56        self._produced_materials = []
 57
 58    def _handle_kwargs(self, **kwargs):
 59        materials_list = []
 60        for material_name, mass in kwargs.items():
 61            if material_name not in self._valid_classes:
 62                raise ValueError('Invalid class name!')
 63            materials_list.append(self._valid_classes[material_name](mass))
 64        self._produced_materials.extend(materials_list)
 65        self._all_produced_materials.extend(materials_list)
 66        return tuple(materials_list)
 67
 68    @staticmethod
 69    def _create_new_class(class_name, density):
 70        new_class = type(class_name, (Material,), { '_DENSITY': density })
 71        return new_class
 72
 73    def _handle_args(self, *args):
 74        total_mass = 0
 75        all_names = []
 76
 77        for arg in args:
 78            if arg.is_used:
 79                raise AssertionError('This material is already used in some factory!')
 80            arg_class_name = type(arg).__name__
 81            total_mass += arg.mass
 82            split_names = arg_class_name.split('_')
 83            all_names.extend(split_names)
 84
 85        for arg in args:  # in another loop to make sure no fails happen when we mix used and unused args
 86            arg.is_used = True
 87
 88        all_names = sorted(all_names)
 89        combined_name = '_'.join(all_names)
 90
 91        if combined_name not in self._valid_classes:
 92            avg_density = sum(BASICS_DENSITY[name] for name in all_names) / len(all_names)
 93            self._valid_classes[combined_name] = self._create_new_class(combined_name, avg_density)
 94
 95        to_return = self._valid_classes[combined_name](total_mass)
 96
 97        self._produced_materials.append(to_return)
 98        self._all_produced_materials.append(to_return)
 99
100        return to_return
101
102    def __call__(self, *args, **kwargs):
103        if (not args and not kwargs) or (args and kwargs):
104            raise ValueError('Invalid arguments!')
105        if kwargs:
106            return self._handle_kwargs(**kwargs)
107        elif args:
108            return self._handle_args(*args)
109
110    def can_build(self, target_volume):
111        total_volume = sum(material.volume for material in self._produced_materials if not material.is_used)
112        return total_volume >= target_volume
113
114    @classmethod
115    def can_build_together(cls, target_volume):
116        total_volume = sum(material.volume for material in cls._all_produced_materials if not material.is_used)
117        return total_volume >= target_volume

..........
----------------------------------------------------------------------
Ran 10 tests in 0.012s

OK

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

nn1BASICS_DENSITY = {
2    'Concrete': 2500,
3    'Brick': 2000,
4    'Stone': 1600,
5    'Wood': 600,
6    'Steel': 7700
7}
8 
1class Material:9class Material:
2    _DENSITY = 110    _DENSITY = 1
311
4    def __init__(self, mass):12    def __init__(self, mass):
5        self.mass = mass13        self.mass = mass
6        self.is_used = False14        self.is_used = False
715
8    @property16    @property
9    def volume(self):17    def volume(self):
10        return self.mass / self._DENSITY18        return self.mass / self._DENSITY
1119
1220
13class Concrete(Material):21class Concrete(Material):
n14    _DENSITY = 2500n22    _DENSITY = BASICS_DENSITY['Concrete']
1523
1624
17class Brick(Material):25class Brick(Material):
n18    _DENSITY = 2000n26    _DENSITY = BASICS_DENSITY['Brick']
1927
2028
21class Stone(Material):29class Stone(Material):
n22    _DENSITY = 1600n30    _DENSITY = BASICS_DENSITY['Stone']
2331
2432
25class Wood(Material):33class Wood(Material):
n26    _DENSITY = 600n34    _DENSITY = BASICS_DENSITY['Wood']
2735
2836
29class Steel(Material):37class Steel(Material):
n30    _DENSITY = 7700n38    _DENSITY = BASICS_DENSITY['Steel']
3139
3240
33class Factory:41class Factory:
n34    _basics_density = {n42    """Create different building materials including some interesting 'alloys'.
35        'Concrete': 2500,43    A fancy way to demonstrate the factory design pattern"""
36        'Brick': 2000,
37        'Stone': 1600,
38        'Wood': 600,
39        'Steel': 7700
40    }
4144
42    _valid_classes = {45    _valid_classes = {
43        'Concrete': Concrete,46        'Concrete': Concrete,
44        'Brick': Brick,47        'Brick': Brick,
45        'Stone': Stone,48        'Stone': Stone,
46        'Wood': Wood,49        'Wood': Wood,
47        'Steel': Steel50        'Steel': Steel
n48    }  # we start with the basic classes first and gradually add mixed onesn51    }  # we start with the basic classes first and gradually add dynamic ones
4952
50    _all_produced_materials = []53    _all_produced_materials = []
5154
52    def __init__(self):55    def __init__(self):
53        self._produced_materials = []56        self._produced_materials = []
5457
55    def _handle_kwargs(self, **kwargs):58    def _handle_kwargs(self, **kwargs):
56        materials_list = []59        materials_list = []
n57        for key, value in kwargs.items():n60        for material_name, mass in kwargs.items():
58            if key not in self._valid_classes:61            if material_name not in self._valid_classes:
59                raise ValueError('Invalid class name!')62                raise ValueError('Invalid class name!')
n60            materials_list.append(self._valid_classes[key](value))n63            materials_list.append(self._valid_classes[material_name](mass))
61        self._produced_materials.extend(materials_list)64        self._produced_materials.extend(materials_list)
62        self._all_produced_materials.extend(materials_list)65        self._all_produced_materials.extend(materials_list)
63        return tuple(materials_list)66        return tuple(materials_list)
6467
65    @staticmethod68    @staticmethod
66    def _create_new_class(class_name, density):69    def _create_new_class(class_name, density):
n67        new_class = type(n70        new_class = type(class_name, (Material,), { '_DENSITY': density })
68            class_name, (Material,),
69            {
70                '_DENSITY': density
71            }
72        )
73        return new_class71        return new_class
7472
75    def _handle_args(self, *args):73    def _handle_args(self, *args):
76        total_mass = 074        total_mass = 0
77        all_names = []75        all_names = []
7876
79        for arg in args:77        for arg in args:
80            if arg.is_used:78            if arg.is_used:
81                raise AssertionError('This material is already used in some factory!')79                raise AssertionError('This material is already used in some factory!')
82            arg_class_name = type(arg).__name__80            arg_class_name = type(arg).__name__
83            total_mass += arg.mass81            total_mass += arg.mass
84            split_names = arg_class_name.split('_')82            split_names = arg_class_name.split('_')
85            all_names.extend(split_names)83            all_names.extend(split_names)
8684
87        for arg in args:  # in another loop to make sure no fails happen when we mix used and unused args85        for arg in args:  # in another loop to make sure no fails happen when we mix used and unused args
88            arg.is_used = True86            arg.is_used = True
8987
90        all_names = sorted(all_names)88        all_names = sorted(all_names)
91        combined_name = '_'.join(all_names)89        combined_name = '_'.join(all_names)
9290
93        if combined_name not in self._valid_classes:91        if combined_name not in self._valid_classes:
n94            avg_density = sum(self._basics_density[name] for name in all_names) / len(all_names)n92            avg_density = sum(BASICS_DENSITY[name] for name in all_names) / len(all_names)
95            self._valid_classes[combined_name] = self._create_new_class(combined_name, avg_density)93            self._valid_classes[combined_name] = self._create_new_class(combined_name, avg_density)
9694
97        to_return = self._valid_classes[combined_name](total_mass)95        to_return = self._valid_classes[combined_name](total_mass)
9896
99        self._produced_materials.append(to_return)97        self._produced_materials.append(to_return)
100        self._all_produced_materials.append(to_return)98        self._all_produced_materials.append(to_return)
10199
102        return to_return100        return to_return
103101
104    def __call__(self, *args, **kwargs):102    def __call__(self, *args, **kwargs):
n105        if (len(args) == len(kwargs) == 0) or (len(args) != 0 and len(kwargs) != 0):n103        if (not args and not kwargs) or (args and kwargs):
106            raise ValueError('Invalid arguments!')104            raise ValueError('Invalid arguments!')
n107 n
108        if len(kwargs) != 0:105        if kwargs:
109            return self._handle_kwargs(**kwargs)106            return self._handle_kwargs(**kwargs)
n110        elif len(args) != 0:n107        elif args:
111            return self._handle_args(*args)108            return self._handle_args(*args)
112109
113    def can_build(self, target_volume):110    def can_build(self, target_volume):
n114        total_volume = 0n111        total_volume = sum(material.volume for material in self._produced_materials if not material.is_used)
115        for material in self._produced_materials:
116            if not material.is_used:
117                total_volume += material.volume
118        return total_volume >= target_volume112        return total_volume >= target_volume
119113
120    @classmethod114    @classmethod
121    def can_build_together(cls, target_volume):115    def can_build_together(cls, target_volume):
t122        total_volume = 0t116        total_volume = sum(material.volume for material in cls._all_produced_materials if not material.is_used)
123        for material in cls._all_produced_materials:
124            if not material.is_used:
125                total_volume += material.volume
126        return total_volume >= target_volume117        return total_volume >= target_volume
Legends
Colors
 Added 
Changed
Deleted
Links
(f)irst change
(n)ext change
(t)op