1class Candy:
2
3 def __init__(self, mass, uranium):
4 self.mass = mass
5 self.uranium = uranium
6
7 def get_uranium_quantity(self):
8 return self.mass * self.uranium
9
10 def get_mass(self):
11 return self.mass
12
13
14class Person:
15
16 def __init__(self, position):
17 self.position = position
18
19 def get_position(self):
20 return self.position
21
22 def set_position(self, position):
23 self.position = position
24
25
26class Kid(Person):
27
28 def __init__(self, position, initiative):
29 super().__init__(position)
30 self.initiative = initiative
31 self.candy_basket = []
32 self.CONST_CRITICAL = 20
33
34 def get_initiative(self):
35 return self.initiative
36
37 def add_candy(self, candy):
38 self.candy_basket.append(candy)
39
40 def is_critical(self):
41 return sum(candy.get_uranium_quantity() for candy in self.candy_basket) > self.CONST_CRITICAL
42
43
44class Host(Person):
45
46 def __init__(self, position, candies):
47 super().__init__(position)
48 self.candy_basket = [Candy(mass, uranium) for mass, uranium in candies]
49
50 def remove_candy(self, func):
51 if not self.candy_basket:
52 return None
53 removed_candy = func(self.candy_basket)
54 self.candy_basket.remove(removed_candy)
55 return removed_candy
56
57
58class FluxCapacitor:
59 def __init__(self, participants):
60 self.participants = participants
61 self.all_hosts = [participant for participant in self.participants if isinstance(participant, Host)]
62 self.all_kids = [participant for participant in self.participants if isinstance(participant, Kid)]
63
64 def get_victim(self):
65 victims = set()
66 visited_hosts = {kid: set() for kid in self.all_kids}
67
68 while True:
69 new_victims = False
70
71 for kid in [k for k in self.all_kids if k not in victims]:
72 closest_host = FluxCapacitor.find_closest_host(kid, visited_hosts[kid], self.all_hosts)
73
74 if closest_host is None:
75 continue
76
77 visited_hosts[kid].add(closest_host)
78 kid.set_position(closest_host.get_position())
79 candy = closest_host.remove_candy(FluxCapacitor.choose_candy_with_max_weight)
80
81 if candy is not None:
82 kid.add_candy(candy)
83 if kid.is_critical():
84 victims.add(kid)
85 new_victims = True
86
87 if new_victims or len(visited_hosts[kid]) == len(self.all_hosts):
88 break
89
90 return victims if victims else None
91
92 @staticmethod
93 def find_closest_host(kid, visited_hosts, hosts):
94 closest_host = None
95 closest_distance = float("inf")
96 closest_info_tuple = (closest_distance, 0, 0)
97
98 for host in [h for h in hosts if h not in visited_hosts]:
99 distance = FluxCapacitor.calculate_distance(kid.get_position(), host.get_position())
100 current_info_tuple = (distance, host.get_position()[0], host.get_position()[1])
101
102 if current_info_tuple < closest_info_tuple:
103 closest_host = host
104 closest_distance = distance
105 closest_info_tuple = (closest_distance, closest_host.get_position()[0], closest_host.get_position()[1])
106
107 return closest_host
108
109 @staticmethod
110 def calculate_distance(position1, position2):
111 return ((position1[0] - position2[0]) ** 2 + (position1[1] - position2[1]) ** 2) ** 0.5
112
113 @staticmethod
114 def choose_candy_with_max_weight(candies):
115 if not candies:
116 return None
117 return max(candies, key=lambda candy: candy.get_mass())
.E.E........
======================================================================
ERROR: test_empty (test.FluxCapacitorTest)
Test with empty collection.
----------------------------------------------------------------------
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 80, in test_empty
self.assertEqual(flux_capacitor.get_victim(), None)
File "/tmp/solution.py", line 87, in get_victim
if new_victims or len(visited_hosts[kid]) == len(self.all_hosts):
UnboundLocalError: local variable 'kid' referenced before assignment
======================================================================
ERROR: test_empty_kids (test.FluxCapacitorTest)
Test with empty kids.
----------------------------------------------------------------------
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 96, in test_empty_kids
self.assertEqual(flux_capacitor.get_victim(), None)
File "/tmp/solution.py", line 87, in get_victim
if new_victims or len(visited_hosts[kid]) == len(self.all_hosts):
UnboundLocalError: local variable 'kid' referenced before assignment
----------------------------------------------------------------------
Ran 12 tests in 0.001s
FAILED (errors=2)
| 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 | 5 | self.uranium = uranium | ||
| 6 | 6 | ||||
| 7 | def get_uranium_quantity(self): | 7 | def get_uranium_quantity(self): | ||
| 8 | return self.mass * self.uranium | 8 | return self.mass * 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 | 13 | ||||
| 14 | class Person: | 14 | class Person: | ||
| 15 | 15 | ||||
| 16 | def __init__(self, position): | 16 | def __init__(self, position): | ||
| 17 | self.position = position | 17 | self.position = position | ||
| 18 | 18 | ||||
| 19 | def get_position(self): | 19 | def get_position(self): | ||
| 20 | return self.position | 20 | return self.position | ||
| 21 | 21 | ||||
| 22 | def set_position(self, position): | 22 | def set_position(self, position): | ||
| 23 | self.position = position | 23 | self.position = position | ||
| 24 | 24 | ||||
| 25 | 25 | ||||
| 26 | class Kid(Person): | 26 | class Kid(Person): | ||
| 27 | 27 | ||||
| 28 | def __init__(self, position, initiative): | 28 | def __init__(self, position, initiative): | ||
| 29 | super().__init__(position) | 29 | super().__init__(position) | ||
| 30 | self.initiative = initiative | 30 | self.initiative = initiative | ||
| 31 | self.candy_basket = [] | 31 | self.candy_basket = [] | ||
| n | n | 32 | self.CONST_CRITICAL = 20 | ||
| 32 | 33 | ||||
| 33 | def get_initiative(self): | 34 | def get_initiative(self): | ||
| 34 | return self.initiative | 35 | return self.initiative | ||
| 35 | 36 | ||||
| 36 | def add_candy(self, candy): | 37 | def add_candy(self, candy): | ||
| 37 | self.candy_basket.append(candy) | 38 | self.candy_basket.append(candy) | ||
| 38 | 39 | ||||
| 39 | def is_critical(self): | 40 | def is_critical(self): | ||
| n | 40 | return sum(candy.get_uranium_quantity() for candy in self.candy_basket) > 20 | n | 41 | return sum(candy.get_uranium_quantity() for candy in self.candy_basket) > self.CONST_CRITICAL |
| 41 | 42 | ||||
| 42 | 43 | ||||
| 43 | class Host(Person): | 44 | class Host(Person): | ||
| 44 | 45 | ||||
| 45 | def __init__(self, position, candies): | 46 | def __init__(self, position, candies): | ||
| 46 | super().__init__(position) | 47 | super().__init__(position) | ||
| 47 | self.candy_basket = [Candy(mass, uranium) for mass, uranium in candies] | 48 | self.candy_basket = [Candy(mass, uranium) for mass, uranium in candies] | ||
| 48 | 49 | ||||
| 49 | def remove_candy(self, func): | 50 | def remove_candy(self, func): | ||
| 50 | if not self.candy_basket: | 51 | if not self.candy_basket: | ||
| 51 | return None | 52 | return None | ||
| 52 | removed_candy = func(self.candy_basket) | 53 | removed_candy = func(self.candy_basket) | ||
| 53 | self.candy_basket.remove(removed_candy) | 54 | self.candy_basket.remove(removed_candy) | ||
| 54 | return removed_candy | 55 | return removed_candy | ||
| 55 | 56 | ||||
| 56 | 57 | ||||
| 57 | class FluxCapacitor: | 58 | class FluxCapacitor: | ||
| 58 | def __init__(self, participants): | 59 | def __init__(self, participants): | ||
| 59 | self.participants = participants | 60 | self.participants = participants | ||
| n | n | 61 | self.all_hosts = [participant for participant in self.participants if isinstance(participant, Host)] | ||
| 62 | self.all_kids = [participant for participant in self.participants if isinstance(participant, Kid)] | ||||
| 60 | 63 | ||||
| 61 | def get_victim(self): | 64 | def get_victim(self): | ||
| 62 | victims = set() | 65 | victims = set() | ||
| n | 63 | all_hosts = [participant for participant in self.participants if isinstance(participant, Host)] | n | ||
| 64 | all_kids = [participant for participant in self.participants if isinstance(participant, Kid)] | ||||
| 65 | visited_hosts = {kid: set() for kid in all_kids} | 66 | visited_hosts = {kid: set() for kid in self.all_kids} | ||
| 66 | 67 | ||||
| 67 | while True: | 68 | while True: | ||
| n | 68 | no_new_victims = True | n | 69 | new_victims = False |
| 70 | |||||
| 69 | for kid in [k for k in all_kids if k not in victims]: | 71 | for kid in [k for k in self.all_kids if k not in victims]: | ||
| 70 | closest_host = FluxCapacitor.find_closest_host(kid, visited_hosts[kid], all_hosts) | 72 | closest_host = FluxCapacitor.find_closest_host(kid, visited_hosts[kid], self.all_hosts) | ||
| 71 | 73 | ||||
| 72 | if closest_host is None: | 74 | if closest_host is None: | ||
| 73 | continue | 75 | continue | ||
| 74 | 76 | ||||
| 75 | visited_hosts[kid].add(closest_host) | 77 | visited_hosts[kid].add(closest_host) | ||
| n | n | 78 | kid.set_position(closest_host.get_position()) | ||
| 76 | candy = closest_host.remove_candy(FluxCapacitor.choose_candy_with_max_weight) | 79 | candy = closest_host.remove_candy(FluxCapacitor.choose_candy_with_max_weight) | ||
| 77 | 80 | ||||
| 78 | if candy is not None: | 81 | if candy is not None: | ||
| 79 | kid.add_candy(candy) | 82 | kid.add_candy(candy) | ||
| n | 80 | visited_hosts[kid].add(closest_host) | n | ||
| 81 | if kid.is_critical(): | 83 | if kid.is_critical(): | ||
| 82 | victims.add(kid) | 84 | victims.add(kid) | ||
| n | 83 | no_new_victims = False | n | 85 | new_victims = True |
| 84 | 86 | ||||
| n | 85 | if no_new_victims: | n | 87 | if new_victims or len(visited_hosts[kid]) == len(self.all_hosts): |
| 86 | break | 88 | break | ||
| 87 | 89 | ||||
| 88 | return victims if victims else None | 90 | return victims if victims else None | ||
| 89 | 91 | ||||
| 90 | @staticmethod | 92 | @staticmethod | ||
| 91 | def find_closest_host(kid, visited_hosts, hosts): | 93 | def find_closest_host(kid, visited_hosts, hosts): | ||
| 92 | closest_host = None | 94 | closest_host = None | ||
| 93 | closest_distance = float("inf") | 95 | closest_distance = float("inf") | ||
| n | n | 96 | closest_info_tuple = (closest_distance, 0, 0) | ||
| 94 | 97 | ||||
| 95 | for host in [h for h in hosts if h not in visited_hosts]: | 98 | for host in [h for h in hosts if h not in visited_hosts]: | ||
| 96 | distance = FluxCapacitor.calculate_distance(kid.get_position(), host.get_position()) | 99 | distance = FluxCapacitor.calculate_distance(kid.get_position(), host.get_position()) | ||
| n | 97 | if distance < closest_distance or (distance == closest_distance and (host.get_position() < closest_host.get_position())): | n | 100 | current_info_tuple = (distance, host.get_position()[0], host.get_position()[1]) |
| 101 | |||||
| 102 | if current_info_tuple < closest_info_tuple: | ||||
| 98 | closest_host = host | 103 | closest_host = host | ||
| 99 | closest_distance = distance | 104 | closest_distance = distance | ||
| t | t | 105 | closest_info_tuple = (closest_distance, closest_host.get_position()[0], closest_host.get_position()[1]) | ||
| 100 | 106 | ||||
| 101 | return closest_host | 107 | return closest_host | ||
| 102 | 108 | ||||
| 103 | @staticmethod | 109 | @staticmethod | ||
| 104 | def calculate_distance(position1, position2): | 110 | def calculate_distance(position1, position2): | ||
| 105 | return ((position1[0] - position2[0]) ** 2 + (position1[1] - position2[1]) ** 2) ** 0.5 | 111 | return ((position1[0] - position2[0]) ** 2 + (position1[1] - position2[1]) ** 2) ** 0.5 | ||
| 106 | 112 | ||||
| 107 | @staticmethod | 113 | @staticmethod | ||
| 108 | def choose_candy_with_max_weight(candies): | 114 | def choose_candy_with_max_weight(candies): | ||
| 109 | if not candies: | 115 | if not candies: | ||
| 110 | return None | 116 | return None | ||
| 111 | return max(candies, key=lambda candy: candy.get_mass()) | 117 | return max(candies, key=lambda candy: candy.get_mass()) |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||