1class Candy:
2
3 def __init__(self, mass, uranium):
4 self._mass = mass
5 self._uranium = uranium * mass
6
7 def get_uranium_quantity(self):
8 return self._uranium
9
10 def get_mass(self):
11 return self._mass
12
13 def __gt__(self, other):
14 return self._mass > other._mass
15
16
17class Person:
18
19 def __init__(self, position):
20 self._position = position
21
22 def get_position(self):
23 return self._position
24
25 def set_position(self, position):
26 self._position = position
27
28 def get_distance_to(self, position):
29 return (self._position[0] - position[0])**2 + (self._position[1] - position[1])**2
30
31
32class Kid(Person):
33
34 _CRITICAL_MASS = 20
35
36 def __init__(self, position, initiative):
37 super().__init__(position)
38 self._initiative = initiative
39 self._candy_box = []
40 self._current_uranium = 0
41 self.hosts_to_visit = set()
42
43 def get_initiative(self):
44 return self._initiative
45
46 def add_candy(self, candy):
47 self._candy_box.append(candy)
48 self._current_uranium += candy.get_uranium_quantity()
49
50 def is_critical(self):
51 return self._current_uranium > self._CRITICAL_MASS
52
53 def visit_closest_host(self):
54 closest_host = min(self.hosts_to_visit, key = host_comparator(self._position))
55 self.hosts_to_visit.remove(closest_host)
56 self._position = closest_host.get_position()
57 closest_host.kids.add(self)
58
59 def __gt__(self, other):
60 return self._initiative > other._initiative
61
62
63
64class Host(Person):
65
66 def __init__(self, position, candy_info):
67 super().__init__(position)
68 self._candy_box = set(map(lambda info: Candy(*info), candy_info))
69 self.kids = set()
70
71 def remove_candy(self, func):
72 if not self._candy_box:
73 return None
74 result = func(self._candy_box)
75 self._candy_box.remove(result)
76 return result
77
78 def give_candy(self):
79 while self.kids:
80 kid = max(self.kids)
81 candy = self.remove_candy(max)
82 kid.add_candy(candy)
83 self.kids.remove(kid)
84
85
86class FluxCapacitor:
87
88 def __init__(self, persons):
89 self._kids = set(filter(lambda p: isinstance(p, Kid), persons))
90 self._hosts = set(filter(lambda p: isinstance(p, Host), persons))
91
92 def get_victim(self):
93 for kid in self._kids:
94 kid.hosts_to_visit = set(self._hosts)
95
96 victims = set()
97 for _ in self._hosts:
98 for kid in self._kids:
99 kid.visit_closest_host()
100 for host in self._hosts:
101 host.give_candy()
102 for kid in self._kids:
103 if kid.is_critical():
104 victims.add(kid)
105 if victims:
106 return victims
107 return None
108
109
110def host_comparator(kid_position):
111 def compare(host):
112 return (host.get_distance_to(kid_position), host.get_position()[0])
113 return compare
....E.......
======================================================================
ERROR: test_no_candies (test.FluxCapacitorTest)
Test with no candies.
----------------------------------------------------------------------
Traceback (most recent call last):
File "/usr/local/lib/python3.10/dist-packages/timeout_decorator/timeout_decorator.py", line 82, in new_function
return function(*args, **kwargs)
File "/tmp/test.py", line 106, in test_no_candies
self.assertEqual(flux_capacitor.get_victim(), None)
File "/tmp/solution.py", line 101, in get_victim
host.give_candy()
File "/tmp/solution.py", line 82, in give_candy
kid.add_candy(candy)
File "/tmp/solution.py", line 48, in add_candy
self._current_uranium += candy.get_uranium_quantity()
AttributeError: 'NoneType' object has no attribute 'get_uranium_quantity'
----------------------------------------------------------------------
Ran 12 tests in 0.001s
FAILED (errors=1)
|
Димитър Христов
05.11.2023 15:30Мисля, че частните атрибути са по-добре описани така. Също така имам и custom comparator за host относно позицията на дете, с оглед на забележката от миналото решение за намирането на следващ host, намирам това за най-удачно.
|
Георги Кунчев
04.11.2023 15:26Опитай да дефинираш частните атрибути на класовете с долна черта. Доста от атрибутите ти са частни и се използват само от самите инстанции. Нека се опитаме да го покажем, като следваме конвенцията.
|
| f | 1 | class Candy: | f | 1 | class Candy: |
| 2 | 2 | ||||
| 3 | def __init__(self, mass, uranium): | 3 | def __init__(self, mass, uranium): | ||
| 4 | self._mass = mass | 4 | self._mass = mass | ||
| 5 | self._uranium = uranium * mass | 5 | self._uranium = uranium * mass | ||
| 6 | 6 | ||||
| 7 | def get_uranium_quantity(self): | 7 | def get_uranium_quantity(self): | ||
| 8 | return self._uranium | 8 | return self._uranium | ||
| 9 | 9 | ||||
| 10 | def get_mass(self): | 10 | def get_mass(self): | ||
| 11 | return self._mass | 11 | return self._mass | ||
| 12 | 12 | ||||
| 13 | def __gt__(self, other): | 13 | def __gt__(self, other): | ||
| 14 | return self._mass > other._mass | 14 | return self._mass > other._mass | ||
| 15 | 15 | ||||
| 16 | 16 | ||||
| 17 | class Person: | 17 | class Person: | ||
| 18 | 18 | ||||
| 19 | def __init__(self, position): | 19 | def __init__(self, position): | ||
| 20 | self._position = position | 20 | self._position = position | ||
| 21 | 21 | ||||
| 22 | def get_position(self): | 22 | def get_position(self): | ||
| 23 | return self._position | 23 | return self._position | ||
| 24 | 24 | ||||
| 25 | def set_position(self, position): | 25 | def set_position(self, position): | ||
| 26 | self._position = position | 26 | self._position = position | ||
| 27 | 27 | ||||
| 28 | def get_distance_to(self, position): | 28 | def get_distance_to(self, position): | ||
| 29 | return (self._position[0] - position[0])**2 + (self._position[1] - position[1])**2 | 29 | return (self._position[0] - position[0])**2 + (self._position[1] - position[1])**2 | ||
| 30 | 30 | ||||
| 31 | 31 | ||||
| 32 | class Kid(Person): | 32 | class Kid(Person): | ||
| 33 | 33 | ||||
| 34 | _CRITICAL_MASS = 20 | 34 | _CRITICAL_MASS = 20 | ||
| 35 | 35 | ||||
| 36 | def __init__(self, position, initiative): | 36 | def __init__(self, position, initiative): | ||
| 37 | super().__init__(position) | 37 | super().__init__(position) | ||
| 38 | self._initiative = initiative | 38 | self._initiative = initiative | ||
| 39 | self._candy_box = [] | 39 | self._candy_box = [] | ||
| 40 | self._current_uranium = 0 | 40 | self._current_uranium = 0 | ||
| 41 | self.hosts_to_visit = set() | 41 | self.hosts_to_visit = set() | ||
| 42 | 42 | ||||
| 43 | def get_initiative(self): | 43 | def get_initiative(self): | ||
| 44 | return self._initiative | 44 | return self._initiative | ||
| 45 | 45 | ||||
| 46 | def add_candy(self, candy): | 46 | def add_candy(self, candy): | ||
| 47 | self._candy_box.append(candy) | 47 | self._candy_box.append(candy) | ||
| 48 | self._current_uranium += candy.get_uranium_quantity() | 48 | self._current_uranium += candy.get_uranium_quantity() | ||
| 49 | 49 | ||||
| 50 | def is_critical(self): | 50 | def is_critical(self): | ||
| 51 | return self._current_uranium > self._CRITICAL_MASS | 51 | return self._current_uranium > self._CRITICAL_MASS | ||
| 52 | 52 | ||||
| 53 | def visit_closest_host(self): | 53 | def visit_closest_host(self): | ||
| n | 54 | print(self._position) | n | ||
| 55 | closest_host = min(self.hosts_to_visit, key = host_comparator(self._position)) | 54 | closest_host = min(self.hosts_to_visit, key = host_comparator(self._position)) | ||
| 56 | self.hosts_to_visit.remove(closest_host) | 55 | self.hosts_to_visit.remove(closest_host) | ||
| 57 | self._position = closest_host.get_position() | 56 | self._position = closest_host.get_position() | ||
| 58 | closest_host.kids.add(self) | 57 | closest_host.kids.add(self) | ||
| t | 59 | print(list(map(lambda c: c.get_uranium_quantity(), self._candy_box))) | t | 58 | |
| 60 | print(self._position) | ||||
| 61 | |||||
| 62 | def __gt__(self, other): | 59 | def __gt__(self, other): | ||
| 63 | return self._initiative > other._initiative | 60 | return self._initiative > other._initiative | ||
| 64 | 61 | ||||
| 65 | 62 | ||||
| 66 | 63 | ||||
| 67 | class Host(Person): | 64 | class Host(Person): | ||
| 68 | 65 | ||||
| 69 | def __init__(self, position, candy_info): | 66 | def __init__(self, position, candy_info): | ||
| 70 | super().__init__(position) | 67 | super().__init__(position) | ||
| 71 | self._candy_box = set(map(lambda info: Candy(*info), candy_info)) | 68 | self._candy_box = set(map(lambda info: Candy(*info), candy_info)) | ||
| 72 | self.kids = set() | 69 | self.kids = set() | ||
| 73 | 70 | ||||
| 74 | def remove_candy(self, func): | 71 | def remove_candy(self, func): | ||
| 75 | if not self._candy_box: | 72 | if not self._candy_box: | ||
| 76 | return None | 73 | return None | ||
| 77 | result = func(self._candy_box) | 74 | result = func(self._candy_box) | ||
| 78 | self._candy_box.remove(result) | 75 | self._candy_box.remove(result) | ||
| 79 | return result | 76 | return result | ||
| 80 | 77 | ||||
| 81 | def give_candy(self): | 78 | def give_candy(self): | ||
| 82 | while self.kids: | 79 | while self.kids: | ||
| 83 | kid = max(self.kids) | 80 | kid = max(self.kids) | ||
| 84 | candy = self.remove_candy(max) | 81 | candy = self.remove_candy(max) | ||
| 85 | kid.add_candy(candy) | 82 | kid.add_candy(candy) | ||
| 86 | self.kids.remove(kid) | 83 | self.kids.remove(kid) | ||
| 87 | 84 | ||||
| 88 | 85 | ||||
| 89 | class FluxCapacitor: | 86 | class FluxCapacitor: | ||
| 90 | 87 | ||||
| 91 | def __init__(self, persons): | 88 | def __init__(self, persons): | ||
| 92 | self._kids = set(filter(lambda p: isinstance(p, Kid), persons)) | 89 | self._kids = set(filter(lambda p: isinstance(p, Kid), persons)) | ||
| 93 | self._hosts = set(filter(lambda p: isinstance(p, Host), persons)) | 90 | self._hosts = set(filter(lambda p: isinstance(p, Host), persons)) | ||
| 94 | 91 | ||||
| 95 | def get_victim(self): | 92 | def get_victim(self): | ||
| 96 | for kid in self._kids: | 93 | for kid in self._kids: | ||
| 97 | kid.hosts_to_visit = set(self._hosts) | 94 | kid.hosts_to_visit = set(self._hosts) | ||
| 98 | 95 | ||||
| 99 | victims = set() | 96 | victims = set() | ||
| 100 | for _ in self._hosts: | 97 | for _ in self._hosts: | ||
| 101 | for kid in self._kids: | 98 | for kid in self._kids: | ||
| 102 | kid.visit_closest_host() | 99 | kid.visit_closest_host() | ||
| 103 | for host in self._hosts: | 100 | for host in self._hosts: | ||
| 104 | host.give_candy() | 101 | host.give_candy() | ||
| 105 | for kid in self._kids: | 102 | for kid in self._kids: | ||
| 106 | if kid.is_critical(): | 103 | if kid.is_critical(): | ||
| 107 | victims.add(kid) | 104 | victims.add(kid) | ||
| 108 | if victims: | 105 | if victims: | ||
| 109 | return victims | 106 | return victims | ||
| 110 | return None | 107 | return None | ||
| 111 | 108 | ||||
| 112 | 109 | ||||
| 113 | def host_comparator(kid_position): | 110 | def host_comparator(kid_position): | ||
| 114 | def compare(host): | 111 | def compare(host): | ||
| 115 | return (host.get_distance_to(kid_position), host.get_position()[0]) | 112 | return (host.get_distance_to(kid_position), host.get_position()[0]) | ||
| 116 | return compare | 113 | return compare | ||
| 117 | 114 |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | class Candy: | f | 1 | class Candy: |
| 2 | 2 | ||||
| 3 | def __init__(self, mass, uranium): | 3 | def __init__(self, mass, uranium): | ||
| n | 4 | self.mass = mass | n | 4 | self._mass = mass |
| 5 | self.uranium = uranium * mass | 5 | self._uranium = uranium * mass | ||
| 6 | 6 | ||||
| 7 | def get_uranium_quantity(self): | 7 | def get_uranium_quantity(self): | ||
| n | 8 | return self.uranium | n | 8 | return self._uranium |
| 9 | 9 | ||||
| 10 | def get_mass(self): | 10 | def get_mass(self): | ||
| n | 11 | return self.mass | n | 11 | return self._mass |
| 12 | 12 | ||||
| 13 | def __gt__(self, other): | 13 | def __gt__(self, other): | ||
| n | 14 | return self.mass > other.mass | n | 14 | return self._mass > other._mass |
| 15 | 15 | ||||
| 16 | 16 | ||||
| 17 | class Person: | 17 | class Person: | ||
| 18 | 18 | ||||
| 19 | def __init__(self, position): | 19 | def __init__(self, position): | ||
| n | 20 | self.position = position | n | 20 | self._position = position |
| 21 | 21 | ||||
| 22 | def get_position(self): | 22 | def get_position(self): | ||
| n | 23 | return self.position | n | 23 | return self._position |
| 24 | 24 | ||||
| 25 | def set_position(self, position): | 25 | def set_position(self, position): | ||
| n | 26 | self.position = position | n | 26 | self._position = position |
| 27 | 27 | ||||
| n | 28 | def _get_distance_to_(self, position): | n | 28 | def get_distance_to(self, position): |
| 29 | return abs(self.position[0] - position[0])**2 + abs(self.position[1] - position[1])**2 | 29 | return (self._position[0] - position[0])**2 + (self._position[1] - position[1])**2 | ||
| 30 | 30 | ||||
| n | 31 | n | |||
| 32 | 31 | ||||
| 33 | class Kid(Person): | 32 | class Kid(Person): | ||
| 34 | 33 | ||||
| n | n | 34 | _CRITICAL_MASS = 20 | ||
| 35 | |||||
| 35 | def __init__(self, position, initiative): | 36 | def __init__(self, position, initiative): | ||
| 36 | super().__init__(position) | 37 | super().__init__(position) | ||
| n | 37 | self.initiative = initiative | n | 38 | self._initiative = initiative |
| 38 | self.candy_box = [] | 39 | self._candy_box = [] | ||
| 39 | self.current_uranium = 0 | 40 | self._current_uranium = 0 | ||
| 40 | self.hosts_to_visit = set() | 41 | self.hosts_to_visit = set() | ||
| 41 | 42 | ||||
| 42 | def get_initiative(self): | 43 | def get_initiative(self): | ||
| n | 43 | return self.initiative | n | 44 | return self._initiative |
| 44 | 45 | ||||
| 45 | def add_candy(self, candy): | 46 | def add_candy(self, candy): | ||
| n | 46 | self.candy_box.append(candy) | n | 47 | self._candy_box.append(candy) |
| 47 | self.current_uranium += candy.get_uranium_quantity() | 48 | self._current_uranium += candy.get_uranium_quantity() | ||
| 48 | 49 | ||||
| 49 | def is_critical(self): | 50 | def is_critical(self): | ||
| n | 50 | return self.current_uranium > 20 | n | 51 | return self._current_uranium > self._CRITICAL_MASS |
| 51 | 52 | ||||
| 52 | def visit_closest_host(self): | 53 | def visit_closest_host(self): | ||
| n | 53 | current_min_distance = 100000000 | n | 54 | print(self._position) |
| 54 | current_min_x = 100000000 | 55 | closest_host = min(self.hosts_to_visit, key = host_comparator(self._position)) | ||
| 55 | closest_host = None | ||||
| 56 | for host in self.hosts_to_visit: | ||||
| 57 | if (current_min_distance > self._get_distance_to_(host.position)) or (current_min_distance == self._get_distance_to_(host.position) and host.positon[0] < current_min_x): | ||||
| 58 | current_min_distance = self._get_distance_to_(host.position) | ||||
| 59 | closest_host = host | ||||
| 60 | current_min_x = host.position[0] | ||||
| 61 | self.hosts_to_visit.remove(closest_host) | 56 | self.hosts_to_visit.remove(closest_host) | ||
| n | n | 57 | self._position = closest_host.get_position() | ||
| 62 | closest_host.kids.add(self) | 58 | closest_host.kids.add(self) | ||
| n | n | 59 | print(list(map(lambda c: c.get_uranium_quantity(), self._candy_box))) | ||
| 60 | print(self._position) | ||||
| 63 | 61 | ||||
| 64 | def __gt__(self, other): | 62 | def __gt__(self, other): | ||
| n | 65 | return self.initiative > other.initiative | n | 63 | return self._initiative > other._initiative |
| 66 | 64 | ||||
| 67 | 65 | ||||
| n | 68 | n | |||
| 69 | 66 | ||||
| 70 | class Host(Person): | 67 | class Host(Person): | ||
| 71 | 68 | ||||
| 72 | def __init__(self, position, candy_info): | 69 | def __init__(self, position, candy_info): | ||
| 73 | super().__init__(position) | 70 | super().__init__(position) | ||
| n | 74 | self.candy_box = set(map(lambda info : Candy(info[0], info[1]), candy_info)) | n | 71 | self._candy_box = set(map(lambda info: Candy(*info), candy_info)) |
| 75 | self.kids = set() | 72 | self.kids = set() | ||
| 76 | 73 | ||||
| 77 | def remove_candy(self, func): | 74 | def remove_candy(self, func): | ||
| n | 78 | if len(self.candy_box) == 0: | n | 75 | if not self._candy_box: |
| 79 | return None | 76 | return None | ||
| n | 80 | result = func(self.candy_box) | n | 77 | result = func(self._candy_box) |
| 81 | self.candy_box.remove(result) | 78 | self._candy_box.remove(result) | ||
| 82 | return result | 79 | return result | ||
| 83 | 80 | ||||
| 84 | def give_candy(self): | 81 | def give_candy(self): | ||
| n | 85 | while len(self.kids) > 0: | n | 82 | while self.kids: |
| 86 | kid = max(self.kids) | 83 | kid = max(self.kids) | ||
| n | 87 | candy = self.remove_candy(get_max_mass_candy) | n | 84 | candy = self.remove_candy(max) |
| 88 | kid.add_candy(candy) | 85 | kid.add_candy(candy) | ||
| 89 | self.kids.remove(kid) | 86 | self.kids.remove(kid) | ||
| 90 | 87 | ||||
| 91 | 88 | ||||
| 92 | class FluxCapacitor: | 89 | class FluxCapacitor: | ||
| 93 | 90 | ||||
| 94 | def __init__(self, persons): | 91 | def __init__(self, persons): | ||
| n | 95 | self.kids = set(filter(lambda p: isinstance(p, Kid), persons)) | n | 92 | self._kids = set(filter(lambda p: isinstance(p, Kid), persons)) |
| 96 | self.hosts = set(filter(lambda p: isinstance(p, Host), persons)) | 93 | self._hosts = set(filter(lambda p: isinstance(p, Host), persons)) | ||
| 97 | 94 | ||||
| 98 | def get_victim(self): | 95 | def get_victim(self): | ||
| n | 99 | for kid in self.kids: | n | 96 | for kid in self._kids: |
| 100 | kid.hosts_to_visit = set(self.hosts) | 97 | kid.hosts_to_visit = set(self._hosts) | ||
| 101 | 98 | ||||
| 102 | victims = set() | 99 | victims = set() | ||
| n | 103 | for i in range(0, len(self.hosts)): | n | 100 | for _ in self._hosts: |
| 104 | for kid in self.kids: | 101 | for kid in self._kids: | ||
| 105 | kid.visit_closest_host() | 102 | kid.visit_closest_host() | ||
| n | 106 | for host in self.hosts: | n | 103 | for host in self._hosts: |
| 107 | host.give_candy() | 104 | host.give_candy() | ||
| n | 108 | for kid in self.kids: | n | 105 | for kid in self._kids: |
| 109 | if kid.is_critical(): | 106 | if kid.is_critical(): | ||
| 110 | victims.add(kid) | 107 | victims.add(kid) | ||
| n | 111 | if len(victims) > 0: | n | 108 | if victims: |
| 112 | return victims | 109 | return victims | ||
| 113 | return None | 110 | return None | ||
| 114 | 111 | ||||
| 115 | 112 | ||||
| t | 116 | def get_max_mass_candy(candy_box): | t | 113 | def host_comparator(kid_position): |
| 117 | return max(candy_box) | 114 | def compare(host): | ||
| 115 | return (host.get_distance_to(kid_position), host.get_position()[0]) | ||||
| 116 | return compare | ||||
| 117 |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||