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 | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|