1class Candy:
2 def __init__(self, mass, uranium):
3 self.__mass = mass
4 self.__uranium = uranium
5
6 def get_uranium_quantity(self):
7 return self.__mass*self.__uranium
8
9 def get_mass(self):
10 return self.__mass
11
12
13class CandyPouch:
14 def __init__(self, content=[], uranium_quantity=0):
15 self.__content = []
16 self.__uranium_quantity = uranium_quantity
17
18 for mass, uranium in content:
19 candy = Candy(mass, uranium)
20 self.__content.append(candy)
21 self.__uranium_quantity += candy.get_uranium_quantity()
22
23 @property
24 def critical_uranium_quantity(self):
25 return self.__uranium_quantity > 20
26
27 @property
28 def empty(self):
29 return not self.__content
30
31 @property
32 def content(self):
33 return self.__content
34
35 def append(self, candy):
36 self.__content.append(candy)
37 self.__uranium_quantity += candy.get_uranium_quantity()
38
39 def remove(self, candy):
40 self.__content.remove(candy)
41
42
43class Person:
44 def __init__(self, position):
45 self._position = position
46
47 def get_closest_person(self, other_people):
48 person_pos = self.get_position()
49 distance = []
50 for other in other_people:
51 other_pos = other.get_position()
52 if person_pos == other_pos:
53 continue
54 distance.append((((person_pos[0] - other_pos[0]) ** 2
55 + (person_pos[1] - other_pos[1]) ** 2) ** 1/2, other_pos[0], other))
56
57 distance.sort()
58 return distance[0][2]
59
60 def get_position(self):
61 return self._position
62
63 def set_position(self, position):
64 self._position = position
65
66
67class Kid(Person):
68 def __init__(self, position, initiative):
69 super().__init__(position)
70 self.__candy_pouch = CandyPouch()
71 self.__initiative = initiative
72
73 def get_initiative(self):
74 return self.__initiative
75
76 def add_candy(self, candy):
77 self.__candy_pouch.append(candy)
78
79 def is_critical(self):
80 return self.__candy_pouch.critical_uranium_quantity
81
82
83class Host(Person):
84 def __init__(self, position, candies):
85 super().__init__(position)
86 self.__candy_pouch = CandyPouch(candies)
87
88 def get_max_mass_candy(self):
89 def max_mass_candy(content):
90 return max(content, key=lambda candy: candy.get_mass())
91 return max_mass_candy
92
93 def remove_candy(self, get_candy):
94 if not self.__candy_pouch.empty:
95 candy = get_candy(self.__candy_pouch.content)
96 self.__candy_pouch.remove(candy)
97 return candy
98 return None
99
100
101class FluxCapacitor:
102 def __init__(self, participants):
103 self.__hosts = []
104 self.__kids = []
105
106 for participant in participants:
107 if isinstance(participant, Host):
108 self.__hosts.append(participant)
109 else:
110 self.__kids.append(participant)
111
112 def get_victim(self):
113 self.__kids.sort(key=lambda kid: kid.get_initiative(), reverse=True)
114 kid_to_host = {kid: self.__hosts for kid in self.__kids}
115 dead_kids = set()
116
117 while not dead_kids and any(kid_to_host.values()):
118 for kid, not_visited in kid_to_host.items():
119 if not not_visited:
120 continue;
121 closest_person = kid.get_closest_person(not_visited)
122 kid.add_candy(closest_person.remove_candy(closest_person.get_max_mass_candy()))
123 kid.set_position(closest_person.get_position())
124 updated_list = list(not_visited)
125 updated_list.remove(closest_person)
126 kid_to_host[kid] = updated_list
127
128 if kid.is_critical():
129 dead_kids.add(kid)
130
131 return dead_kids if dead_kids else None
....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 122, in get_victim
kid.add_candy(closest_person.remove_candy(closest_person.get_max_mass_candy()))
File "/tmp/solution.py", line 77, in add_candy
self.__candy_pouch.append(candy)
File "/tmp/solution.py", line 37, in append
self.__uranium_quantity += candy.get_uranium_quantity()
AttributeError: 'NoneType' object has no attribute 'get_uranium_quantity'
----------------------------------------------------------------------
Ran 12 tests in 0.001s
FAILED (errors=1)
f | 1 | class Candy: | f | 1 | class Candy: |
2 | def __init__(self, mass, uranium): | 2 | def __init__(self, mass, uranium): | ||
3 | self.__mass = mass | 3 | self.__mass = mass | ||
4 | self.__uranium = uranium | 4 | self.__uranium = uranium | ||
5 | 5 | ||||
6 | def get_uranium_quantity(self): | 6 | def get_uranium_quantity(self): | ||
7 | return self.__mass*self.__uranium | 7 | return self.__mass*self.__uranium | ||
8 | 8 | ||||
9 | def get_mass(self): | 9 | def get_mass(self): | ||
10 | return self.__mass | 10 | return self.__mass | ||
11 | 11 | ||||
12 | 12 | ||||
13 | class CandyPouch: | 13 | class CandyPouch: | ||
14 | def __init__(self, content=[], uranium_quantity=0): | 14 | def __init__(self, content=[], uranium_quantity=0): | ||
15 | self.__content = [] | 15 | self.__content = [] | ||
16 | self.__uranium_quantity = uranium_quantity | 16 | self.__uranium_quantity = uranium_quantity | ||
17 | 17 | ||||
18 | for mass, uranium in content: | 18 | for mass, uranium in content: | ||
19 | candy = Candy(mass, uranium) | 19 | candy = Candy(mass, uranium) | ||
20 | self.__content.append(candy) | 20 | self.__content.append(candy) | ||
21 | self.__uranium_quantity += candy.get_uranium_quantity() | 21 | self.__uranium_quantity += candy.get_uranium_quantity() | ||
22 | 22 | ||||
23 | @property | 23 | @property | ||
24 | def critical_uranium_quantity(self): | 24 | def critical_uranium_quantity(self): | ||
n | 25 | return self.__uranium_quantity >= 20 | n | 25 | return self.__uranium_quantity > 20 |
26 | 26 | ||||
27 | @property | 27 | @property | ||
28 | def empty(self): | 28 | def empty(self): | ||
29 | return not self.__content | 29 | return not self.__content | ||
30 | 30 | ||||
31 | @property | 31 | @property | ||
32 | def content(self): | 32 | def content(self): | ||
33 | return self.__content | 33 | return self.__content | ||
34 | 34 | ||||
35 | def append(self, candy): | 35 | def append(self, candy): | ||
36 | self.__content.append(candy) | 36 | self.__content.append(candy) | ||
37 | self.__uranium_quantity += candy.get_uranium_quantity() | 37 | self.__uranium_quantity += candy.get_uranium_quantity() | ||
38 | 38 | ||||
39 | def remove(self, candy): | 39 | def remove(self, candy): | ||
40 | self.__content.remove(candy) | 40 | self.__content.remove(candy) | ||
n | 41 | n | |||
42 | def print(self): | ||||
43 | for item in self.__content: | ||||
44 | print(item.print()) | ||||
45 | 41 | ||||
46 | 42 | ||||
47 | class Person: | 43 | class Person: | ||
48 | def __init__(self, position): | 44 | def __init__(self, position): | ||
49 | self._position = position | 45 | self._position = position | ||
50 | 46 | ||||
n | 51 | @staticmethod | n | ||
52 | def get_closest_person(person, other_people): | 47 | def get_closest_person(self, other_people): | ||
53 | person_pos = person.get_position() | 48 | person_pos = self.get_position() | ||
54 | distance = [] | 49 | distance = [] | ||
55 | for other in other_people: | 50 | for other in other_people: | ||
56 | other_pos = other.get_position() | 51 | other_pos = other.get_position() | ||
57 | if person_pos == other_pos: | 52 | if person_pos == other_pos: | ||
58 | continue | 53 | continue | ||
59 | distance.append((((person_pos[0] - other_pos[0]) ** 2 | 54 | distance.append((((person_pos[0] - other_pos[0]) ** 2 | ||
60 | + (person_pos[1] - other_pos[1]) ** 2) ** 1/2, other_pos[0], other)) | 55 | + (person_pos[1] - other_pos[1]) ** 2) ** 1/2, other_pos[0], other)) | ||
61 | 56 | ||||
62 | distance.sort() | 57 | distance.sort() | ||
63 | return distance[0][2] | 58 | return distance[0][2] | ||
64 | 59 | ||||
65 | def get_position(self): | 60 | def get_position(self): | ||
66 | return self._position | 61 | return self._position | ||
67 | 62 | ||||
68 | def set_position(self, position): | 63 | def set_position(self, position): | ||
69 | self._position = position | 64 | self._position = position | ||
70 | 65 | ||||
71 | 66 | ||||
72 | class Kid(Person): | 67 | class Kid(Person): | ||
73 | def __init__(self, position, initiative): | 68 | def __init__(self, position, initiative): | ||
74 | super().__init__(position) | 69 | super().__init__(position) | ||
75 | self.__candy_pouch = CandyPouch() | 70 | self.__candy_pouch = CandyPouch() | ||
76 | self.__initiative = initiative | 71 | self.__initiative = initiative | ||
77 | 72 | ||||
78 | def get_initiative(self): | 73 | def get_initiative(self): | ||
79 | return self.__initiative | 74 | return self.__initiative | ||
80 | 75 | ||||
81 | def add_candy(self, candy): | 76 | def add_candy(self, candy): | ||
82 | self.__candy_pouch.append(candy) | 77 | self.__candy_pouch.append(candy) | ||
83 | 78 | ||||
84 | def is_critical(self): | 79 | def is_critical(self): | ||
85 | return self.__candy_pouch.critical_uranium_quantity | 80 | return self.__candy_pouch.critical_uranium_quantity | ||
86 | 81 | ||||
87 | 82 | ||||
88 | class Host(Person): | 83 | class Host(Person): | ||
89 | def __init__(self, position, candies): | 84 | def __init__(self, position, candies): | ||
90 | super().__init__(position) | 85 | super().__init__(position) | ||
91 | self.__candy_pouch = CandyPouch(candies) | 86 | self.__candy_pouch = CandyPouch(candies) | ||
92 | 87 | ||||
93 | def get_max_mass_candy(self): | 88 | def get_max_mass_candy(self): | ||
94 | def max_mass_candy(content): | 89 | def max_mass_candy(content): | ||
n | 95 | max_mass = 0 | n | 90 | return max(content, key=lambda candy: candy.get_mass()) |
96 | max_candy = Candy(0, 0) | ||||
97 | for candy in content: | ||||
98 | if max_mass < candy.get_mass(): | ||||
99 | max_candy = candy | ||||
100 | return max_candy | ||||
101 | return max_mass_candy | 91 | return max_mass_candy | ||
102 | 92 | ||||
103 | def remove_candy(self, get_candy): | 93 | def remove_candy(self, get_candy): | ||
104 | if not self.__candy_pouch.empty: | 94 | if not self.__candy_pouch.empty: | ||
105 | candy = get_candy(self.__candy_pouch.content) | 95 | candy = get_candy(self.__candy_pouch.content) | ||
106 | self.__candy_pouch.remove(candy) | 96 | self.__candy_pouch.remove(candy) | ||
107 | return candy | 97 | return candy | ||
108 | return None | 98 | return None | ||
109 | 99 | ||||
110 | 100 | ||||
111 | class FluxCapacitor: | 101 | class FluxCapacitor: | ||
112 | def __init__(self, participants): | 102 | def __init__(self, participants): | ||
113 | self.__hosts = [] | 103 | self.__hosts = [] | ||
114 | self.__kids = [] | 104 | self.__kids = [] | ||
115 | 105 | ||||
116 | for participant in participants: | 106 | for participant in participants: | ||
117 | if isinstance(participant, Host): | 107 | if isinstance(participant, Host): | ||
118 | self.__hosts.append(participant) | 108 | self.__hosts.append(participant) | ||
119 | else: | 109 | else: | ||
120 | self.__kids.append(participant) | 110 | self.__kids.append(participant) | ||
121 | 111 | ||||
122 | def get_victim(self): | 112 | def get_victim(self): | ||
123 | self.__kids.sort(key=lambda kid: kid.get_initiative(), reverse=True) | 113 | self.__kids.sort(key=lambda kid: kid.get_initiative(), reverse=True) | ||
124 | kid_to_host = {kid: self.__hosts for kid in self.__kids} | 114 | kid_to_host = {kid: self.__hosts for kid in self.__kids} | ||
125 | dead_kids = set() | 115 | dead_kids = set() | ||
126 | 116 | ||||
n | 127 | while dead_kids == set() and any(kid_to_host.values()): | n | 117 | while not dead_kids and any(kid_to_host.values()): |
128 | for kid, not_visited in kid_to_host.items(): | 118 | for kid, not_visited in kid_to_host.items(): | ||
129 | if not not_visited: | 119 | if not not_visited: | ||
130 | continue; | 120 | continue; | ||
n | 131 | closest_person = Person.get_closest_person(kid, not_visited) | n | 121 | closest_person = kid.get_closest_person(not_visited) |
132 | kid.add_candy(closest_person.remove_candy(closest_person.get_max_mass_candy())) | 122 | kid.add_candy(closest_person.remove_candy(closest_person.get_max_mass_candy())) | ||
133 | kid.set_position(closest_person.get_position()) | 123 | kid.set_position(closest_person.get_position()) | ||
134 | updated_list = list(not_visited) | 124 | updated_list = list(not_visited) | ||
135 | updated_list.remove(closest_person) | 125 | updated_list.remove(closest_person) | ||
136 | kid_to_host[kid] = updated_list | 126 | kid_to_host[kid] = updated_list | ||
137 | 127 | ||||
138 | if kid.is_critical(): | 128 | if kid.is_critical(): | ||
139 | dead_kids.add(kid) | 129 | dead_kids.add(kid) | ||
140 | 130 | ||||
t | 141 | if dead_kids != set(): | t | 131 | return dead_kids if dead_kids else None |
142 | return dead_kids | ||||
143 | |||||
144 | return None |
Legends | ||||||||||
---|---|---|---|---|---|---|---|---|---|---|
|
|