1def calculate_distance(first_person, second_person):
2 square_sum = 0
3 for first_coord, second_coord in zip(first_person.position, second_person.position):
4 square_sum += (first_coord - second_coord) ** 2
5 return square_sum ** 0.5
6
7
8class Candy:
9
10 def __init__(self, mass, uranium):
11 self.mass = mass
12 self.uranium = uranium
13
14 def get_uranium_quantity(self):
15 return self.mass * self.uranium
16
17 def get_mass(self):
18 return self.mass
19
20 def __gt__(self, other):
21 return self.mass > other.mass
22
23
24class Person:
25
26 def __init__(self, position):
27 self.position = position
28
29 def get_position(self):
30 return self.position
31
32 def set_position(self, new_position):
33 self.position = new_position
34
35
36class Kid(Person):
37
38 def __init__(self, curr_position, initiative):
39 self.position = curr_position
40 self.initiative = initiative
41 self.basket = []
42 self.level_uranium = 0
43 self.hosts_available = []
44
45 def get_initiative(self):
46 return self.initiative
47
48 def add_candy(self, candy):
49 self.basket.append(candy)
50 self.level_uranium += candy.get_uranium_quantity()
51
52 def is_critical(self):
53 return self.level_uranium > 20
54
55 def find_closest_host(self):
56 closest_host = self.hosts_available[0]
57 for host in self.hosts_available:
58 if calculate_distance(self, host) > calculate_distance(self, closest_host):
59 continue
60 elif calculate_distance(self, host) < calculate_distance(self, closest_host):
61 closest_host = host
62 continue
63 elif host < closest_host:
64 closest_host = host
65 return closest_host
66
67 def __gt__(self, other):
68 return self.initiative > other.initiative
69
70
71class Host(Person):
72
73 def __init__(self, position, candies):
74 self.position = position
75 self.basket = []
76 self.kids_in_waiting = []
77 for mass, uranium in candies:
78 self.basket.append(Candy(mass, uranium))
79
80 def remove_candy(self, func):
81 if not self.basket:
82 return None
83 removed_candy = func(self.basket)
84 self.basket.remove(removed_candy)
85 return removed_candy
86
87 @staticmethod
88 def find_the_biggest_candy(basket_with_candies):
89 basket_with_candies.sort(reverse=True)
90 return basket_with_candies[0]
91
92 def __lt__(self, other):
93 self_x, self_y = self.position
94 other_x, other_y = other.position
95 if self_x > other_x:
96 return False
97 if self_x < other_x:
98 return True
99 if self_y > other_y:
100 return False
101 return True
102
103
104class FluxCapacitor:
105
106 def __init__(self, participants):
107 self.participants = participants
108 self.victims = set()
109 self.kids = []
110 self.hosts = []
111
112 def separete_hosts_kids(self):
113 """Creation of two lists keeping the hosts and the kids separetely. """
114 for person in self.participants:
115 if isinstance(person, Host):
116 self.hosts.append(person)
117 else:
118 self.kids.append(person)
119
120 def perform_one_itteration_in_the_game(self):
121 """Performing 1 iteration of the Halloween in Priyat game. """
122 for kid in self.kids:
123 curr_host = kid.find_closest_host()
124 # Going to the closest host; changing the position of the kid.
125 kid.set_position(curr_host.position)
126 # Make sure that we can not visit the same host again.
127 kid.hosts_available.remove(curr_host)
128 index_host = self.hosts.index(curr_host)
129 # Keep track of the kids who are going to visit the host for this iteration of the game.
130 self.hosts[index_host].kids_in_waiting.append(kid)
131
132 for host in self.hosts:
133 if not host.basket:
134 # If the host doesn't have any candies, the kids do a trick for him and continue.
135 continue
136 # Sorting the kids in descending order by their initiatives.
137 host.kids_in_waiting.sort(reverse=True)
138 for kid in host.kids_in_waiting:
139 candy = host.remove_candy(host.find_the_biggest_candy)
140 index_kid = self.kids.index(kid)
141 self.kids[index_kid].add_candy(candy)
142
143 def get_victim(self):
144 self.separete_hosts_kids()
145 for kid in self.kids:
146 kid.hosts_available = [host for host in self.hosts]
147 for iteration in range(len(self.hosts)):
148 self.victims = {kid for kid in self.kids if kid.is_critical()}
149 self.perform_one_itteration_in_the_game()
150 if self.victims:
151 # If there are victims, the game is over.
152 return self.victims
153
154 return None
............
----------------------------------------------------------------------
Ran 12 tests in 0.001s
OK
07.11.2023 10:03
07.11.2023 10:04
07.11.2023 10:04
07.11.2023 10:04
07.11.2023 10:05