1import math
2
3
4class Candy():
5 """A candy with mass and uranium content."""
6 def __init__(self, mass=0, uranium=0):
7 """Initialize a candy with the given mass and uranium content."""
8 self.mass = mass
9 self.uranium = uranium
10
11 def get_uranium_quantity(self):
12 """Calculate the uranium quantity in the candy."""
13 return self.mass * self.uranium
14
15 def get_mass(self):
16 """Get the mass of the candy."""
17 return self.mass
18
19
20class Person():
21 """A person with a position in a 2D space."""
22 def __init__(self, position=(0, 0)):
23 """Initialize a person with the given position."""
24 self.x, self.y = position
25
26 def get_position(self):
27 """Get the position of the person."""
28 return (self.x, self.y)
29
30 def set_position(self, position):
31 """Set the position of the person."""
32 self.x, self.y = position
33
34
35class Kid(Person):
36 def __init__(self, position=(0, 0), initiative=0):
37 """A kid with a position, initiative, and a collection of candies."""
38 super().__init__(position)
39 self.initiative = initiative
40 self.candy = []
41 self.uranium_mass = 0
42
43 def get_initiative(self):
44 """Get the initiative level of the kid."""
45 return self.initiative
46
47 def add_candy(self, candy):
48 """Add a candy to the kid's collection and update uranium mass."""
49 self.candy.append(candy)
50 self.uranium_mass += candy.get_uranium_quantity()
51
52 def is_critical(self):
53 """Check if the total uranium mass is critical."""
54 return self.uranium_mass > 20
55
56
57class Host(Person):
58 """A host with a position and a basket of candies."""
59 def __init__(self, position, candies):
60 """Initialize a host with the given position and candy basket."""
61 super().__init__(position)
62 self.candy_basket = [Candy(mass, uranium) for mass, uranium in candies]
63
64 def remove_candy(self, remove_func):
65 """Remove a candy from the candy basket using a removal function."""
66 selected_candy = remove_func(self.candy_basket) if len(self.candy_basket) > 0 else None
67 if selected_candy:
68 self.candy_basket.remove(selected_candy)
69 return selected_candy
70
71
72class FluxCapacitor():
73 """Game simulator for kid-host interactions."""
74 def __init__(self, participants):
75 """Initialize the game simulator with a set of participants (kids and hosts)."""
76 self.kids = [participant for participant in participants if isinstance(participant, Kid)]
77 self.hosts = [participant for participant in participants if isinstance(participant, Host)]
78 self.unvisited_hosts = {kid: list(self.hosts) for kid in self.kids}
79 self.victims = set()
80
81 self._play_game()
82
83 def get_victim(self):
84 """Get the victim kid(s) in the game or None if there are no victims."""
85 return self.victims if self.victims else None
86
87 def _play_game(self):
88 """Simulate the movement of kids to the closest hosts and distribute candies."""
89 if not self.kids or not self.hosts:
90 return
91 for _ in self.hosts:
92 current_hosts = {host: [] for host in self.hosts}
93 for kid in self.kids:
94 closest_host = min(
95 self.unvisited_hosts[kid],
96 key=lambda host: (
97 self.__calculate_distance(host.get_position(), kid.get_position()),
98 host.get_position()[0],
99 host.get_position()[1]
100 )
101 )
102 kid.set_position(closest_host.get_position())
103 current_hosts[closest_host].append(kid)
104 self.unvisited_hosts[kid].remove(closest_host)
105 for host, current_kids in current_hosts.items():
106 if len(current_kids) == 0:
107 continue
108 elif len(current_kids) == 1:
109 self._give_candy(host, current_kids[0])
110 else:
111 current_kids.sort(key=lambda x: x.get_initiative(), reverse=True)
112 for current_kid in current_kids:
113 self._give_candy(host, current_kid)
114 for kid in self.kids:
115 if kid.is_critical() is True:
116 self.victims.add(kid)
117 if self.victims:
118 return
119
120 def _give_candy(self, host, kid):
121 """Give candy from a host to a kid."""
122 candy = host.remove_candy(self.__select_candy_by_mass)
123 if candy:
124 kid.add_candy(candy)
125
126 def __calculate_distance(self, host_pos, kid_pos):
127 """Calculate the distance between a host and a kid."""
128 return math.sqrt((kid_pos[0]-host_pos[0])**2 + (kid_pos[1]-host_pos[1])**2)
129
130 @staticmethod
131 def __select_candy_by_mass(candies):
132 """Select candy based on mass from a list of candies."""
133 return max(candies, key=lambda candy: candy.get_mass())
134
............
----------------------------------------------------------------------
Ran 12 tests in 0.001s
OK
Виктор Бечев
08.11.2023 13:08Има някои спорни моменти, като това дали е добре да извикаш `_play_game` още при инициализиране или при извикване на `get_victim`, но иначе нямам кой знае какви стилови забележки (тук таме някои от нещата, които Жорката вчера спомена, например - `if kid.is_critical() is True`, вместо просто `if kid.is_critical()`.
|
10.11.2023 14:36
08.11.2023 13:04