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 Person:
14 def __init__(self, position):
15 self._position = position
16
17 def get_position(self):
18 return self._position
19
20 def set_position(self, new_position):
21 self._position = new_position
22
23
24class Kid(Person):
25 def __init__(self, position, initiative):
26 super().__init__(position)
27 self._initiative = initiative
28 self._basket_with_candies = []
29
30 def get_initiative(self):
31 return self._initiative
32
33 def add_candy(self, candy):
34 self._basket_with_candies.append(candy)
35
36 def is_critical(self):
37 total_uranium = sum(candy.get_uranium_quantity()
38 for candy in self._basket_with_candies)
39 return total_uranium > 20
40
41
42class Host(Person):
43 def __init__(self, position, candies):
44 super().__init__(position)
45 self._candies = [Candy(mass, uranium) for mass, uranium in candies]
46
47 def remove_candy(self, selection_function):
48 if not self._candies:
49 return None
50 selected_candy = selection_function(self._candies)
51 self._candies.remove(selected_candy)
52 return selected_candy
53
54
55class FluxCapacitor:
56 def __init__(self, participants):
57 self._kids = [p for p in participants if isinstance(p, Kid)]
58 self._hosts = [p for p in participants if isinstance(p, Host)]
59 self._victims = set()
60 self._visited_hosts = {kid: set() for kid in self._kids}
61
62 @staticmethod
63 def distance(pos1, pos2):
64 return ((pos1[0] - pos2[0]) ** 2 + (pos1[1] - pos2[1]) ** 2) ** 0.5
65
66 def closer_host(self, pos1, pos2):
67 if pos1[0] == pos2[0]:
68 return pos1[1] < pos2[1]
69 return pos1[0] < pos2[0]
70
71 def closest_host(self, kid):
72 closest_host = None
73 min_distance = float('inf')
74 kid_position = kid.get_position()
75 for host in self._hosts:
76 if host not in self._visited_hosts[kid]:
77 host_position = host.get_position()
78 distance = self.distance(kid_position, host_position)
79 if distance < min_distance:
80 min_distance = distance
81 closest_host = host
82 elif distance == min_distance:
83 if self.closer_host(host_position, closest_host.get_position()):
84 closest_host = host
85 return closest_host, min_distance
86
87 def get_victim(self):
88 while True:
89 for kid in sorted(self._kids, key=lambda x: x.get_initiative(), reverse=True):
90 closest_host, _ = self.closest_host(kid)
91 if closest_host and closest_host not in self._visited_hosts[kid]:
92 kid.set_position(closest_host.get_position())
93 candy = closest_host.remove_candy(choose_heaviest)
94 if candy:
95 kid.add_candy(candy)
96 self._visited_hosts[kid].add(closest_host)
97 for kid in self._kids:
98 if kid.is_critical():
99 self._victims.add(kid)
100 if self._victims:
101 break
102 if all(len(self._visited_hosts[kid]) == len(self._hosts) for kid in self._kids):
103 break
104
105 return self._victims if self._victims else None
106
107def choose_heaviest(candies):
108 return max(candies, key=lambda candy: candy.get_mass())
............
----------------------------------------------------------------------
Ran 12 tests in 0.001s
OK
Виктор Бечев
08.11.2023 13:10Отвъд дребната дори-не-бих-казал-забележка - чист код.
|
08.11.2023 13:09