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