1import math
2
3class Candy:
4 def __init__(self, mass, uranium):
5 self.mass = mass
6 self.uranium = uranium
7
8 def get_uranium_quantity(self):
9 return self.mass * self.uranium
10
11 def get_mass(self):
12 return self.mass
13
14
15class Person:
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, new_position):
23 self.position = new_position
24
25
26class Kid(Person):
27 CRITICAL_URANIUM_MASS = 20
28
29 def __init__(self, position, initiative):
30 super().__init__(position)
31 self.initiative = initiative
32 self.candies = []
33
34 def get_initiative(self):
35 return self.initiative
36
37 def add_candy(self, candy):
38 self.candies.append(candy)
39
40 def is_critical(self):
41 uranium_mass = sum(candy.get_uranium_quantity() for candy in self.candies)
42 return uranium_mass > Kid.CRITICAL_URANIUM_MASS
43
44 def move_to_host(self, host):
45 self.set_position(host.get_position())
46
47
48class Host(Person):
49 def __init__(self, position, candies):
50 super().__init__(position)
51 self.candies = [Candy(mass, uranium) for mass, uranium in candies]
52
53 def remove_candy(self, selection_function):
54 if not self.candies:
55 return None
56 selected_candy = selection_function(self.candies)
57 self.candies.remove(selected_candy)
58 return selected_candy
59
60
61class FluxCapacitor:
62 def __init__(self, participants):
63 self.kids = {p for p in participants if isinstance(p, Kid)}
64 self.hosts = {p for p in participants if isinstance(p, Host)}
65 self.victims = set()
66 self.simulate_halloween()
67
68 def get_victim(self):
69 return self.victims if self.victims else None
70
71 def simulate_halloween(self):
72 visited_hosts = {kid: set() for kid in self.kids}
73 while self.hosts and not self.victims:
74 for kid in sorted(self.kids, key=lambda k: k.get_initiative(), reverse=True):
75 closest_host = self.find_closest_host(kid, visited_hosts[kid])
76 if closest_host:
77 visited_hosts[kid].add(closest_host)
78 kid.move_to_host(closest_host)
79 candy = closest_host.remove_candy(lambda candies: max(candies, key=lambda c: c.get_mass()))
80 if candy:
81 kid.add_candy(candy)
82 self.victims = {kid for kid in self.kids if kid.is_critical()}
83 if self.victims:
84 break
85 self.hosts = {host for host in self.hosts if host.candies}
86 if not any(visited_hosts[kid] != self.hosts for kid in self.kids):
87 break
88
89 def find_closest_host(self, kid, visited_hosts):
90 unvisited_hosts = [(host, self.calculate_distance(kid.get_position(), host.get_position()))
91 for host in self.hosts if host not in visited_hosts]
92 unvisited_hosts.sort(key=lambda x: (x[1], x[0].get_position()))
93 return unvisited_hosts[0][0] if unvisited_hosts else None
94
95 def calculate_distance(self, position1, position2):
96 return ((position1[0] - position2[0]) ** 2 + (position1[1] - position2[1]) ** 2) ** 0.5
............
----------------------------------------------------------------------
Ran 12 tests in 0.001s
OK
| f | 1 | import math | f | 1 | import math |
| 2 | 2 | ||||
| 3 | class Candy: | 3 | class Candy: | ||
| 4 | def __init__(self, mass, uranium): | 4 | def __init__(self, mass, uranium): | ||
| 5 | self.mass = mass | 5 | self.mass = mass | ||
| 6 | self.uranium = uranium | 6 | self.uranium = uranium | ||
| 7 | 7 | ||||
| 8 | def get_uranium_quantity(self): | 8 | def get_uranium_quantity(self): | ||
| 9 | return self.mass * self.uranium | 9 | return self.mass * self.uranium | ||
| 10 | 10 | ||||
| 11 | def get_mass(self): | 11 | def get_mass(self): | ||
| 12 | return self.mass | 12 | return self.mass | ||
| 13 | 13 | ||||
| 14 | 14 | ||||
| 15 | class Person: | 15 | class Person: | ||
| 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, new_position): | 22 | def set_position(self, new_position): | ||
| 23 | self.position = new_position | 23 | self.position = new_position | ||
| 24 | 24 | ||||
| 25 | 25 | ||||
| 26 | class Kid(Person): | 26 | class Kid(Person): | ||
| n | n | 27 | CRITICAL_URANIUM_MASS = 20 | ||
| 28 | |||||
| 27 | def __init__(self, position, initiative): | 29 | def __init__(self, position, initiative): | ||
| 28 | super().__init__(position) | 30 | super().__init__(position) | ||
| 29 | self.initiative = initiative | 31 | self.initiative = initiative | ||
| 30 | self.candies = [] | 32 | self.candies = [] | ||
| 31 | 33 | ||||
| 32 | def get_initiative(self): | 34 | def get_initiative(self): | ||
| 33 | return self.initiative | 35 | return self.initiative | ||
| 34 | 36 | ||||
| 35 | def add_candy(self, candy): | 37 | def add_candy(self, candy): | ||
| 36 | self.candies.append(candy) | 38 | self.candies.append(candy) | ||
| 37 | 39 | ||||
| 38 | def is_critical(self): | 40 | def is_critical(self): | ||
| 39 | uranium_mass = sum(candy.get_uranium_quantity() for candy in self.candies) | 41 | uranium_mass = sum(candy.get_uranium_quantity() for candy in self.candies) | ||
| n | 40 | return uranium_mass > 20 | n | 42 | return uranium_mass > Kid.CRITICAL_URANIUM_MASS |
| 41 | 43 | ||||
| 42 | def move_to_host(self, host): | 44 | def move_to_host(self, host): | ||
| 43 | self.set_position(host.get_position()) | 45 | self.set_position(host.get_position()) | ||
| 44 | 46 | ||||
| 45 | 47 | ||||
| 46 | class Host(Person): | 48 | class Host(Person): | ||
| 47 | def __init__(self, position, candies): | 49 | def __init__(self, position, candies): | ||
| 48 | super().__init__(position) | 50 | super().__init__(position) | ||
| 49 | self.candies = [Candy(mass, uranium) for mass, uranium in candies] | 51 | self.candies = [Candy(mass, uranium) for mass, uranium in candies] | ||
| 50 | 52 | ||||
| 51 | def remove_candy(self, selection_function): | 53 | def remove_candy(self, selection_function): | ||
| 52 | if not self.candies: | 54 | if not self.candies: | ||
| 53 | return None | 55 | return None | ||
| 54 | selected_candy = selection_function(self.candies) | 56 | selected_candy = selection_function(self.candies) | ||
| 55 | self.candies.remove(selected_candy) | 57 | self.candies.remove(selected_candy) | ||
| 56 | return selected_candy | 58 | return selected_candy | ||
| 57 | 59 | ||||
| 58 | 60 | ||||
| 59 | class FluxCapacitor: | 61 | class FluxCapacitor: | ||
| 60 | def __init__(self, participants): | 62 | def __init__(self, participants): | ||
| 61 | self.kids = {p for p in participants if isinstance(p, Kid)} | 63 | self.kids = {p for p in participants if isinstance(p, Kid)} | ||
| 62 | self.hosts = {p for p in participants if isinstance(p, Host)} | 64 | self.hosts = {p for p in participants if isinstance(p, Host)} | ||
| 63 | self.victims = set() | 65 | self.victims = set() | ||
| 64 | self.simulate_halloween() | 66 | self.simulate_halloween() | ||
| 65 | 67 | ||||
| n | n | 68 | def get_victim(self): | ||
| 69 | return self.victims if self.victims else None | ||||
| 70 | |||||
| 66 | def simulate_halloween(self): | 71 | def simulate_halloween(self): | ||
| 67 | visited_hosts = {kid: set() for kid in self.kids} | 72 | visited_hosts = {kid: set() for kid in self.kids} | ||
| 68 | while self.hosts and not self.victims: | 73 | while self.hosts and not self.victims: | ||
| 69 | for kid in sorted(self.kids, key=lambda k: k.get_initiative(), reverse=True): | 74 | for kid in sorted(self.kids, key=lambda k: k.get_initiative(), reverse=True): | ||
| 70 | closest_host = self.find_closest_host(kid, visited_hosts[kid]) | 75 | closest_host = self.find_closest_host(kid, visited_hosts[kid]) | ||
| 71 | if closest_host: | 76 | if closest_host: | ||
| 72 | visited_hosts[kid].add(closest_host) | 77 | visited_hosts[kid].add(closest_host) | ||
| 73 | kid.move_to_host(closest_host) | 78 | kid.move_to_host(closest_host) | ||
| 74 | candy = closest_host.remove_candy(lambda candies: max(candies, key=lambda c: c.get_mass())) | 79 | candy = closest_host.remove_candy(lambda candies: max(candies, key=lambda c: c.get_mass())) | ||
| 75 | if candy: | 80 | if candy: | ||
| 76 | kid.add_candy(candy) | 81 | kid.add_candy(candy) | ||
| 77 | self.victims = {kid for kid in self.kids if kid.is_critical()} | 82 | self.victims = {kid for kid in self.kids if kid.is_critical()} | ||
| 78 | if self.victims: | 83 | if self.victims: | ||
| n | 79 | return self.victims | n | 84 | break |
| 80 | self.hosts = {host for host in self.hosts if host.candies} | 85 | self.hosts = {host for host in self.hosts if host.candies} | ||
| 81 | if not any(visited_hosts[kid] != self.hosts for kid in self.kids): | 86 | if not any(visited_hosts[kid] != self.hosts for kid in self.kids): | ||
| n | 82 | return None | n | 87 | break |
| 83 | 88 | ||||
| 84 | def find_closest_host(self, kid, visited_hosts): | 89 | def find_closest_host(self, kid, visited_hosts): | ||
| n | 85 | unvisited_hosts = [host for host in self.hosts if host not in visited_hosts] | n | ||
| 86 | closest_host = None | ||||
| 87 | min_distance = float('inf') | ||||
| 88 | |||||
| 89 | for host in unvisited_hosts: | ||||
| 90 | distance = self.calculate_distance(kid.get_position(), host.get_position()) | 90 | unvisited_hosts = [(host, self.calculate_distance(kid.get_position(), host.get_position())) | ||
| 91 | if distance < min_distance or (distance == min_distance and self.is_closer_by_coordinates(host, closest_host)): | 91 | for host in self.hosts if host not in visited_hosts] | ||
| 92 | min_distance = distance | 92 | unvisited_hosts.sort(key=lambda x: (x[1], x[0].get_position())) | ||
| 93 | closest_host = host | 93 | return unvisited_hosts[0][0] if unvisited_hosts else None | ||
| 94 | return closest_host | ||||
| 95 | 94 | ||||
| 96 | def calculate_distance(self, position1, position2): | 95 | def calculate_distance(self, position1, position2): | ||
| 97 | return ((position1[0] - position2[0]) ** 2 + (position1[1] - position2[1]) ** 2) ** 0.5 | 96 | return ((position1[0] - position2[0]) ** 2 + (position1[1] - position2[1]) ** 2) ** 0.5 | ||
| t | 98 | t | |||
| 99 | def is_closer_by_coordinates(self, host1, host2): | ||||
| 100 | if not host2 or host1.get_position()[0] < host2.get_position()[0]: | ||||
| 101 | return True | ||||
| 102 | elif host1.get_position()[0] == host2.get_position()[0] and host1.get_position()[1] < host2.get_position()[1]: | ||||
| 103 | return True | ||||
| 104 | return False |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||
| f | 1 | import math | f | 1 | import math |
| 2 | 2 | ||||
| 3 | class Candy: | 3 | class Candy: | ||
| 4 | def __init__(self, mass, uranium): | 4 | def __init__(self, mass, uranium): | ||
| 5 | self.mass = mass | 5 | self.mass = mass | ||
| 6 | self.uranium = uranium | 6 | self.uranium = uranium | ||
| 7 | 7 | ||||
| 8 | def get_uranium_quantity(self): | 8 | def get_uranium_quantity(self): | ||
| 9 | return self.mass * self.uranium | 9 | return self.mass * self.uranium | ||
| 10 | 10 | ||||
| 11 | def get_mass(self): | 11 | def get_mass(self): | ||
| 12 | return self.mass | 12 | return self.mass | ||
| 13 | 13 | ||||
| 14 | 14 | ||||
| 15 | class Person: | 15 | class Person: | ||
| 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, new_position): | 22 | def set_position(self, new_position): | ||
| 23 | self.position = new_position | 23 | self.position = new_position | ||
| 24 | 24 | ||||
| 25 | 25 | ||||
| 26 | class Kid(Person): | 26 | class Kid(Person): | ||
| 27 | def __init__(self, position, initiative): | 27 | def __init__(self, position, initiative): | ||
| 28 | super().__init__(position) | 28 | super().__init__(position) | ||
| 29 | self.initiative = initiative | 29 | self.initiative = initiative | ||
| 30 | self.candies = [] | 30 | self.candies = [] | ||
| 31 | 31 | ||||
| 32 | def get_initiative(self): | 32 | def get_initiative(self): | ||
| 33 | return self.initiative | 33 | return self.initiative | ||
| 34 | 34 | ||||
| 35 | def add_candy(self, candy): | 35 | def add_candy(self, candy): | ||
| 36 | self.candies.append(candy) | 36 | self.candies.append(candy) | ||
| 37 | 37 | ||||
| 38 | def is_critical(self): | 38 | def is_critical(self): | ||
| 39 | uranium_mass = sum(candy.get_uranium_quantity() for candy in self.candies) | 39 | uranium_mass = sum(candy.get_uranium_quantity() for candy in self.candies) | ||
| 40 | return uranium_mass > 20 | 40 | return uranium_mass > 20 | ||
| 41 | 41 | ||||
| 42 | def move_to_host(self, host): | 42 | def move_to_host(self, host): | ||
| 43 | self.set_position(host.get_position()) | 43 | self.set_position(host.get_position()) | ||
| 44 | 44 | ||||
| n | n | 45 | |||
| 45 | class Host(Person): | 46 | class Host(Person): | ||
| 46 | def __init__(self, position, candies): | 47 | def __init__(self, position, candies): | ||
| 47 | super().__init__(position) | 48 | super().__init__(position) | ||
| 48 | self.candies = [Candy(mass, uranium) for mass, uranium in candies] | 49 | self.candies = [Candy(mass, uranium) for mass, uranium in candies] | ||
| 49 | 50 | ||||
| 50 | def remove_candy(self, selection_function): | 51 | def remove_candy(self, selection_function): | ||
| 51 | if not self.candies: | 52 | if not self.candies: | ||
| 52 | return None | 53 | return None | ||
| 53 | selected_candy = selection_function(self.candies) | 54 | selected_candy = selection_function(self.candies) | ||
| 54 | self.candies.remove(selected_candy) | 55 | self.candies.remove(selected_candy) | ||
| 55 | return selected_candy | 56 | return selected_candy | ||
| 56 | 57 | ||||
| 57 | 58 | ||||
| 58 | class FluxCapacitor: | 59 | class FluxCapacitor: | ||
| 59 | def __init__(self, participants): | 60 | def __init__(self, participants): | ||
| 60 | self.kids = {p for p in participants if isinstance(p, Kid)} | 61 | self.kids = {p for p in participants if isinstance(p, Kid)} | ||
| 61 | self.hosts = {p for p in participants if isinstance(p, Host)} | 62 | self.hosts = {p for p in participants if isinstance(p, Host)} | ||
| 62 | self.victims = set() | 63 | self.victims = set() | ||
| 63 | self.simulate_halloween() | 64 | self.simulate_halloween() | ||
| 64 | 65 | ||||
| 65 | def simulate_halloween(self): | 66 | def simulate_halloween(self): | ||
| 66 | visited_hosts = {kid: set() for kid in self.kids} | 67 | visited_hosts = {kid: set() for kid in self.kids} | ||
| n | 67 | n | |||
| 68 | while self.hosts and not self.victims: | 68 | while self.hosts and not self.victims: | ||
| 69 | for kid in sorted(self.kids, key=lambda k: k.get_initiative(), reverse=True): | 69 | for kid in sorted(self.kids, key=lambda k: k.get_initiative(), reverse=True): | ||
| 70 | closest_host = self.find_closest_host(kid, visited_hosts[kid]) | 70 | closest_host = self.find_closest_host(kid, visited_hosts[kid]) | ||
| 71 | if closest_host: | 71 | if closest_host: | ||
| 72 | visited_hosts[kid].add(closest_host) | 72 | visited_hosts[kid].add(closest_host) | ||
| 73 | kid.move_to_host(closest_host) | 73 | kid.move_to_host(closest_host) | ||
| n | 74 | n | |||
| 75 | candy = closest_host.remove_candy(lambda candies: max(candies, key=lambda c: c.get_mass())) | 74 | candy = closest_host.remove_candy(lambda candies: max(candies, key=lambda c: c.get_mass())) | ||
| 76 | if candy: | 75 | if candy: | ||
| 77 | kid.add_candy(candy) | 76 | kid.add_candy(candy) | ||
| n | 78 | n | |||
| 79 | self.victims = {kid for kid in self.kids if kid.is_critical()} | 77 | self.victims = {kid for kid in self.kids if kid.is_critical()} | ||
| 80 | if self.victims: | 78 | if self.victims: | ||
| 81 | return self.victims | 79 | return self.victims | ||
| n | 82 | n | |||
| 83 | self.hosts = {host for host in self.hosts if host.candies} | 80 | self.hosts = {host for host in self.hosts if host.candies} | ||
| 84 | if not any(visited_hosts[kid] != self.hosts for kid in self.kids): | 81 | if not any(visited_hosts[kid] != self.hosts for kid in self.kids): | ||
| 85 | return None | 82 | return None | ||
| 86 | 83 | ||||
| 87 | def find_closest_host(self, kid, visited_hosts): | 84 | def find_closest_host(self, kid, visited_hosts): | ||
| 88 | unvisited_hosts = [host for host in self.hosts if host not in visited_hosts] | 85 | unvisited_hosts = [host for host in self.hosts if host not in visited_hosts] | ||
| 89 | closest_host = None | 86 | closest_host = None | ||
| 90 | min_distance = float('inf') | 87 | min_distance = float('inf') | ||
| 91 | 88 | ||||
| 92 | for host in unvisited_hosts: | 89 | for host in unvisited_hosts: | ||
| 93 | distance = self.calculate_distance(kid.get_position(), host.get_position()) | 90 | distance = self.calculate_distance(kid.get_position(), host.get_position()) | ||
| 94 | if distance < min_distance or (distance == min_distance and self.is_closer_by_coordinates(host, closest_host)): | 91 | if distance < min_distance or (distance == min_distance and self.is_closer_by_coordinates(host, closest_host)): | ||
| 95 | min_distance = distance | 92 | min_distance = distance | ||
| 96 | closest_host = host | 93 | closest_host = host | ||
| t | 97 | t | |||
| 98 | return closest_host | 94 | return closest_host | ||
| 99 | 95 | ||||
| 100 | def calculate_distance(self, position1, position2): | 96 | def calculate_distance(self, position1, position2): | ||
| 101 | return ((position1[0] - position2[0]) ** 2 + (position1[1] - position2[1]) ** 2) ** 0.5 | 97 | return ((position1[0] - position2[0]) ** 2 + (position1[1] - position2[1]) ** 2) ** 0.5 | ||
| 102 | 98 | ||||
| 103 | def is_closer_by_coordinates(self, host1, host2): | 99 | def is_closer_by_coordinates(self, host1, host2): | ||
| 104 | if not host2 or host1.get_position()[0] < host2.get_position()[0]: | 100 | if not host2 or host1.get_position()[0] < host2.get_position()[0]: | ||
| 105 | return True | 101 | return True | ||
| 106 | elif host1.get_position()[0] == host2.get_position()[0] and host1.get_position()[1] < host2.get_position()[1]: | 102 | elif host1.get_position()[0] == host2.get_position()[0] and host1.get_position()[1] < host2.get_position()[1]: | ||
| 107 | return True | 103 | return True | ||
| 108 | return False | 104 | return False |
| Legends | ||||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
| |||||||||